nats-io / nats-streaming-server

NATS Streaming System Server
https://nats.io
Apache License 2.0
2.51k stars 283 forks source link

Is MaxInflight not honored? #1168

Closed tegk closed 3 years ago

tegk commented 3 years ago

I was reading in this issue https://github.com/nats-io/nats-server/issues/878 that it can happen that messages pile up at one subscriber with possibly leaving other subscribers with nothing to do for some time in a Queue Group.

So I figured that this would avoidable by setting MaxInflight to 1 and manual ACK after work is done:

    // Subscribe with manual ack mode, and set AckWait to 60 seconds
    aw, _ := time.ParseDuration("120s")
    sc.QueueSubscribe(channel,"test", func(msg *stan.Msg) {
        //doing work for some time, duration must be lower than AckWait
        msg.Ack() // Manual ACK

    }, stan.DurableName(durableID),
        stan.MaxInflight(1),
        stan.SetManualAckMode(),
        stan.AckWait(aw),
    )

But it turns out that nats-streaming-server is explicitly forcing delivery and does not honor MaxInflight that is set by the client?

// Constant to indicate that sendMsgToSub() should check number of acks pending
// against MaxInFlight to know if message should be sent out.
const (
    forceDelivery    = true
    honorMaxInFlight = false
)

Is it correct that MaxInflight is basically ignored and if that's the case why is that?

kozlovic commented 3 years ago

The server does not know that your application is processing the message. This is why every AckWait, the message is redelivered. Redelivered is different from a new message sent to your subscription. MaxInflight applies to new messages.

In non-queue subscriptions, there may be up to 1 message redelivered if you use MaxInflight(1). But for queue subscriptions, each member has its own AckWait and MaxInflight. But if a member has unacknowledged messages and suddenly leaves the group, then the server will reassign (send) those messages to the remaining queue members.

tegk commented 3 years ago

"For queue subscriptions, if a member has unacknowledged messages, when this member's AckWait (which is the duration given to the server before the server should attempt to redeliver unacknowledged messages) time elapses, the messages are redelivered to any other member in the group (including itself)."

I would expect therefore that that MaxInFlight in honored for new messages as long AckWait has not expired, is that correct? How could a subscriber only receive messages one by one?

kozlovic commented 3 years ago

I would expect therefore that that MaxInFlight in honored for new messages as long AckWait has not expired, is that correct?

No, again, for queue subscriptions, if a member has unacknowledged messages and leaves the group, the unack'ed messages will be redelivered right away to existing members.

How could a subscriber only receive messages one by one?

Not be a queue subscription and use MaxInflight(1), except for redelivered messages.

kozlovic commented 3 years ago

@tegk Let me know if your questions were addressed and if this issue can be closed.

tegk commented 3 years ago

Thanks for answering, this can be closed :-)