Akka streams graph stage stuck if onPull doesn't push

Hi all,

I’m developing a custom Akka source using GraphStage in Java.
I’m noticing that if during onPull(), no element is pushed, the stage is stuck.
Is my understanding incorrect that onPull() should be called again if no element was pushed?

Thanks!

{
                setHandler(out, new AbstractOutHandler() {
                    @Override
                    public void onPull() throws Exception {
                        if (count++ > 1000) {
                            completeStage();
                            return;
                        }
                        if (count % 2 != 0) {
                            Integer n = rand.nextInt(100);
                            buffer.add(n);
                            push(out, n);
                        } else {
                            // if this block is entered, source will be stuck
                            return;
                        }
                    }
                });
            }

That is not how it works. Pull signals upstream/to an inlet that your stage can handle one element, allowing upstream to push when/if it has one element to push. The same goes for a downstream/outlet, if it has signalled that it can handle one element, you are allowed to push one element.

I recommend carefully reading through the Custom stream processing section of the docs and make sure you understand the samples in there.

Thanks for your reply. The code above was just an example; I’m seeing that if upstream has no element to push during an onPull, and we don’t invoke push(), the stage gets stuck until push() is called (ex. from another async handler). No more onPull() handler invocations occur regardless of downstream demand if nothing is pushed during onPull().

This might be desired behaviour, I’m just trying to confirm that it is! Thanks!

I can just reiterate what Johan said: read through the docs. This is indeed desired behavior: it’s the core concept of the idea of backpressure. Especially look at the state diagrams. When onPull is called, it moves into a Pulled state. If you leave it in that state (by not calling push()) you are indicating that you have no work to give and therefore, indeed, the downstream will never call onPull.

It’s not “stuck”: it’s in a Pulled state.

Thanks for the clarification, appreciate it. I’ll give the docs a thorough read through!