B
B
bitwheeze2021-10-15 02:35:09
Spring
bitwheeze, 2021-10-15 02:35:09

How to make friends between web flux long polling request and scheduled method?

It is not possible to make the long polling request and the scheduled method work in parallel. I have an external data source. Once every 3 seconds, the scheduled method accesses this data source and fetches some data, storing it in my database, adding a timestamp (timestamp attribute) when the data was updated. To make life easier for the web application, I decided to add a long polling method that would wait for the timestamp field to change and, in case of a change, would return a dto with updated data. Or the old dto if there were no changes in 12 seconds.

Scheduled method is clear, simple method with @Schedule(fixedDelay) annotation
Long polling methods looks something like this

@GetMapping("/hook")
    public Mono<DataDto> publisher(@PathVariable String account) {
        var currentSession = service.load(account);
    if(currentSession.isEmpty()) {
      return Mono.empty();
    }
    try {
      Thread.sleep(3000);
      for(int i = 0; i < 4; i++) {
        var tempSession = service.load(account);
        if (currentSession.get().getTimestamp() < tempSession.get().getTimestamp()) {
          Mono.just(tempSession.get().dto());
        }
        Thread.sleep(3000);
      }
      Mono.just(currentSession.get().dto());
    } catch (Exception e) {
      log.error("error waiting new data", e);
    }
    throw new RuntimeException("dvferfge");
    }


I greatly simplified and changed the names so as not to give out company secrets.

So the problem is that everything works, but only on my computer in Intellij. If I pack everything in a container and run it as java -jar app.jar, then for some reason, as soon as a long polling request comes in, the scheduled method does not work. As soon as 12 seconds pass and the long polling method returns the old data, the scheduled method starts working again and updates the database. This also works on the server sometimes, that is, the scheduled method after the request arrives and during it, but rarely. Web flux seems to work in its own thread. As far as I understand it. I sin on service.load(account); This method is annotated with @Transactional in fact I think the ceuurentSession should be in the detached state.

All that remains for me is to rewrite the Scheduled method as a separate thread, otherwise I don’t understand why it blocks for the duration of the long polling method.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
B
bitwheeze, 2021-10-16
@bitwheeze

It seems to have worked. Rewrote everything reactively. The handler stopped blocking the scheduler. Maybe with two Mono.defer it's overkill, but I don't know how to do it differently yet. It is still unclear to me whether this call is in place with take(4) yet.

@GetMapping("/hooks/{account}/new_game")
    public Mono<TableauDto> publisher(@PathVariable String account) {
        log.debug("hooks/new_game {}", account);
        return Mono.defer(() -> {
            log.debug("get current startBlock {}", account);
            final var currentStartBlock = service
                    .load(account)
                    .map(session -> session.getStartBlock())
                    .orElse(0l);

            var res = Mono.defer(() -> service.getTableau(account, currentStartBlock))
                    .repeatWhenEmpty(c -> c.delayElements(Duration.ofMillis(3000)).take(4));

            log.debug("return res {}", res.single());

            return res;
        });
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question