public ResumeResult resume() { if (isPaused()) { if (resumeState.compareAndSet(ResumeState.NotPaused.ordinal(), ResumeState.Resuming.ordinal())) { try { drainBuffer(); // We have here a race condition, as onNext could be called just before paused is set to false, // but after the while loop above. That is why we need to drain the buffer, before each onNext. paused.set(false); if (completedWhenPaused) { onCompleted(); } else if (null != errorWhenPaused) { onError(errorWhenPaused); } return ResumeResult.Resumed; } catch (Exception e) { logger.error("Error while resuming notifications subject.", e); resumeState.compareAndSet(ResumeState.Resuming.ordinal(), ResumeState.Error.ordinal()); onError(e); return ResumeResult.Resumed; } finally { resumeState.compareAndSet(ResumeState.Resuming.ordinal(), ResumeState.NotPaused.ordinal()); } } else { return ResumeResult.DuplicateResume; } } else { return ResumeResult.NotPaused; } }