0

Given backend, which processes user requests of reading container logs(with follow option). Following approach is used:

Future<?> f = threadPool.submit(() -> {
  try {
    while (logStream.hasNext()) {
      LogMessage msg = logStream.next();
      String text = StandardCharsets.UTF_8.decode(msg.content()).toString();
      emitter.send(SseEmitter.event().data(text).name(msg.stream().name()));
    }
    emitter.complete();
  } catch (Exception ex) {
    emitter.completeWithError(ex);
  }
});

Where threadPool is just a Executors.newCachedThreadPool() and emitter is Spring's SseEmitter.

The problem is: when user no longer wants to read logs, he just closes the connection, but this thread is still running(execution is blocked in logStream.hasNext() which is calling InputStream.read(..)).

As far as I understand, hasNext() will never return false(at least while container is running properly), so this loop is endless, and we need to stop it somehow. Possible solution I tried:

emitter.onCompletion(() -> {
  f.cancel(true);
});

was not successful. No InterruptedException was thrown.

Question: Is there any way of unblocking thread? Or maybe there is another approach of solving this problem (i.e. have a possibility to stop waiting for logs)?

Flame239
  • 1,274
  • 1
  • 8
  • 20
  • You may set timeout for emitter and user, if he wants to, might connect again, when emitter is closed. – kr3v Jan 17 '19 at 20:30
  • @kr3v how does it solves the problem? – Flame239 Jan 18 '19 at 08:57
  • What is your problem? Thread loops forever. If you add `onInterrupt` callback on emitter which will interrupt thread, it will do it, as emitter has timeout. – kr3v Jan 18 '19 at 10:47
  • @kr3v Problem is that interrupting thread(via f.cancel(true)) has no effect whatsoever. – Flame239 Jan 18 '19 at 11:00
  • https://gist.github.com/kr3v/3f507e3d37079a2e7b24a42c85bd8f86 - code like this finishes with "Async request timed out" message in logger – kr3v Jan 18 '19 at 18:41

0 Answers0