@Override
    protected void process(ComplexEventChunk<StreamEvent> streamEventChunk, Processor nextProcessor,
                           StreamEventCloner streamEventCloner, WindowState state) {

        // event incoming trigger process. No events means no action
        if (streamEventChunk.getFirst() == null) {
            return;
        }

        List<ComplexEventChunk<StreamEvent>> complexEventChunks = new ArrayList<ComplexEventChunk<StreamEvent>>();
        synchronized (state) {
            initTiming(streamEventChunk.getFirst(), state);

            StreamEvent nextStreamEvent = streamEventChunk.getFirst();
            while (nextStreamEvent != null) {

                StreamEvent currStreamEvent = nextStreamEvent;
                nextStreamEvent = nextStreamEvent.getNext();

                if (currStreamEvent.getType() == ComplexEvent.Type.TIMER) {
                    if (state.lastScheduledTime <= currStreamEvent.getTimestamp()) {
                        // implies that there have not been any more events after this schedule has been done.
                        if (!state.flushed) {
                            flushToOutputChunk(streamEventCloner, complexEventChunks, state.lastCurrentEventTime,
                                    true, state);
                            state.flushed = true;
                        } else {
                            if (state.currentEventChunk.getFirst() != null) {
                                appendToOutputChunk(streamEventCloner, complexEventChunks, state.lastCurrentEventTime,
                                        true, state);
                            }
                        }

                        // rescheduling to emit the current batch after expiring it if no further events arrive.
                        state.lastScheduledTime = siddhiQueryContext.getSiddhiAppContext().
                                getTimestampGenerator().currentTime() + schedulerTimeout;
                        scheduler.notifyAt(state.lastScheduledTime);
                    }
                    continue;
                } else if (currStreamEvent.getType() != ComplexEvent.Type.CURRENT) {
                    continue;
                }

                long currentEventTime = (Long) timestampExpressionExecutor.execute(currStreamEvent);
                if (state.lastCurrentEventTime < currentEventTime) {
                    state.lastCurrentEventTime = currentEventTime;
                }

                if (currentEventTime < state.endTime) {
                    cloneAppend(streamEventCloner, currStreamEvent, state);
                } else {
                    if (state.flushed) {
                        appendToOutputChunk(streamEventCloner, complexEventChunks, state.lastCurrentEventTime,
                                false, state);
                        state.flushed = false;
                    } else {
                        flushToOutputChunk(streamEventCloner, complexEventChunks, state.lastCurrentEventTime,
                                false, state);
                    }
                    // update timestamp, call next processor
                    state.endTime = findEndTime(state.lastCurrentEventTime, state.startTime, timeToKeep);
                    cloneAppend(streamEventCloner, currStreamEvent, state);
                    // triggering the last batch expiration.
                    if (schedulerTimeout > 0) {
                        state.lastScheduledTime = siddhiQueryContext.getSiddhiAppContext().
                                getTimestampGenerator().currentTime() + schedulerTimeout;
                        scheduler.notifyAt(state.lastScheduledTime);
                    }
                }
            }
        }
        for (ComplexEventChunk<StreamEvent> complexEventChunk : complexEventChunks) {
            nextProcessor.process(complexEventChunk);
        }
    }
Here an assumption is taken:
Parameter: timestamp: The time which the window determines as current time and will act upon,
the value of this parameter should be monotonically increasing.
from https://docs.wso2.com/display/CEP400/Inbuilt+Windows#InbuiltWindows-externalTime
modules/siddhi-core/src/main/java/io/siddhi/core/query/processor/stream/window/ExternalTimeBatchWindowProcessor.java