2

I have a set of methods that handle a Flux<String> so

@GetMapping(value = "/web/{s}")
public Flux<String> getWeb(@PathVariable String s) {
    return myService.getFlux(s);
}

In the service class:

public Flux<String> getFlux(String json) throws Exception {
    return handleRequest(json);
}

private Flux<String> handleRequest(String json) throws Exception {
    Many<String> sink = Sinks.many().multicast().directBestEffort();

    ... do stuff with sink ... 

    /* Handle flux completion, termination, error */
    Flux<String> webFlux = sink.asFlux()
            .doOnTerminate(() -> { disposeSink(id); })
            .doOnComplete(() -> { completeSink(id); })
            .doAfterTerminate(() -> { terminateSink(id); }) 
            .doOnCancel(() -> { cancelSink(id); })

    return webFlux;
}

When I get the client to cut short, cancel, terminate their request before it completes, the doOnCancel call only works if it is attached to the initial calling method, i.e.

@GetMapping(value = "/web/{s}")
public Flux<String> getWeb(@PathVariable String s) {
    return myService.getFlux(s).doOnCancel(() -> Log.Info("Cancelled"));
}

This is not really where I want to put it, although it makes sense given it's the client facing call. Why doesn't the doOnCancel hook in the service class get back to the caller? Is a flux that's passed back to calling methods kind of publishing / subscribing to itself ?!!

rupweb
  • 3,052
  • 1
  • 30
  • 57

1 Answers1

0

This was a bit weird but I had to return the sink.asFlux() with the hooks directly like this:

private Flux<String> handleRequest(String json) throws Exception {
    Many<String> sink = Sinks.many().multicast().directBestEffort();

    ... do stuff with sink ... 

    /* Handle flux completion, termination, error */
    return sink.asFlux()
        .doOnTerminate(() -> { disposeSink(id); })
        .doOnComplete(() -> { completeSink(id); })
        .doAfterTerminate(() -> { terminateSink(id); }) 
        .doOnCancel(() -> { cancelSink(id); });
}

Then on the client facing class everything worked when the client randomly cancels the request. I also put the log() in that class

@GetMapping(value = "/web/{s}")
public Flux<String> getWeb(@PathVariable String s) {
    return myService.getFlux(s).log();
}

So basically there is no direct Flux initialization just transform a sink.asFlux() the one time and return it back up the stack.

rupweb
  • 3,052
  • 1
  • 30
  • 57