Code review comment: We might pick currentWork more than one time from workQueue. `currentTimeoutOperation ==  null` will indicate that are we picking up first time.    We do not need to process  currentWork if is picked up second time and no bufferMessages to send to it.  `while ((currentWork = workQueue.peek()) != null && (currentTimeoutOperation == null || bufferMessages.size() > 0 )) {`  The timeout Operation is not removing currentWork from he queue, thus currentWork needs be picked up again, thus we need to threat this different and go in the loop and remove this timeout work. setting `currentTimeoutOperation = null` indicate this case also.

Code under review:
private void drainQueue() {
        if (isTerminated()) {
            return;
        }

        
        synchronized (currentWorkLock) {

            
            if (currentWork != null && currentWork.isTerminal()) {
                workQueue.remove(currentWork);
                if (currentTimeoutOperation != null & !currentTimeoutOperation.isDisposed()) {
                    currentTimeoutOperation.dispose();
                }
                currentTimeoutOperation = null;
            }

            
            
            
            
            

            while ((currentWork = workQueue.peek()) != null && (currentTimeoutOperation == null || bufferMessages.size() > 0 )) {

                
                if (currentWork.isTerminal()) {
                    
                    workQueue.remove(currentWork);
                    if (currentTimeoutOperation != null & !currentTimeoutOperation.isDisposed()) {
                        currentTimeoutOperation.dispose();
                    }
                    currentTimeoutOperation = null;
                    continue;
                }

                if (currentTimeoutOperation == null) {
                    
                    currentTimeoutOperation = getTimeoutOperation(currentWork);
                }

                
                while (bufferMessages.size() > 0 && !currentWork.isTerminal()) {
                    currentWork.next(bufferMessages.poll());
                    remaining.decrementAndGet();
                }

                
                if (currentWork.isTerminal()) {
                    if (currentWork.getError() == null) {
                        currentWork.complete();
                    }
                    
                    workQueue.remove(currentWork);
                    if (currentTimeoutOperation != null & !currentTimeoutOperation.isDisposed()) {
                        currentTimeoutOperation.dispose();
                    }
                    currentTimeoutOperation = null;
                    logger.verbose("The work [{}] is complete.", currentWork.getId());
                } else {
                    
                    long creditToAdd = currentWork.getRemaining() - (remaining.get() + bufferMessages.size());
                    if (creditToAdd > 0) {
                        remaining.addAndGet(creditToAdd);
                        subscription.request(creditToAdd);
                        logger.verbose("Requesting [{}] from upstream for work [{}].", creditToAdd,
                            currentWork.getId());
                    }
                }
            }
        }
    }

Line commented on: currentTimeoutOperation = null;

Revised code:
private void drainQueue() {
        if (isTerminated()) {
            return;
        }

        
        synchronized (currentWorkLock) {

            
            if (currentWork != null && currentWork.isTerminal()) {
                workQueue.remove(currentWork);
                if (currentTimeoutOperation != null && !currentTimeoutOperation.isDisposed()) {
                    currentTimeoutOperation.dispose();
                }
                currentTimeoutOperation = null;
            }

            
            
            
            
            

            while ((currentWork = workQueue.peek()) != null
                && (!currentWork.isProcessingStarted() || bufferMessages.size() > 0)) {

                
                if (currentWork.isTerminal()) {
                    
                    workQueue.remove(currentWork);
                    if (currentTimeoutOperation != null && !currentTimeoutOperation.isDisposed()) {
                        currentTimeoutOperation.dispose();
                    }
                    continue;
                }

                if (!currentWork.isProcessingStarted()) {
                    
                    currentTimeoutOperation = getTimeoutOperation(currentWork);
                    currentWork.startedProcessing();
                }

                
                while (bufferMessages.size() > 0 && !currentWork.isTerminal()) {
                    currentWork.next(bufferMessages.poll());
                    remaining.decrementAndGet();
                }

                
                if (currentWork.isTerminal()) {
                    if (currentWork.getError() == null) {
                        currentWork.complete();
                    }
                    
                    workQueue.remove(currentWork);
                    if (currentTimeoutOperation != null && !currentTimeoutOperation.isDisposed()) {
                        currentTimeoutOperation.dispose();
                    }
                    logger.verbose("The work [{}] is complete.", currentWork.getId());
                } else {
                    
                    long creditToAdd = currentWork.getRemaining() - (remaining.get() + bufferMessages.size());
                    if (creditToAdd > 0) {
                        remaining.addAndGet(creditToAdd);
                        subscription.request(creditToAdd);
                        logger.verbose("Requesting [{}] from upstream for work [{}].", creditToAdd,
                            currentWork.getId());
                    }
                }
            }
        }
    }