Skip to content

fix(events/natsjs): default AutoAck does not match events contract #164

Description

@grechny

Describe the bug

events/natsjs.Stream.Consume defaults to manual acknowledgement even though
events.ConsumeOptions.AutoAck documents automatic acknowledgement as the
default.

The NATS Streaming and in-memory event implementations initialize
AutoAck: true. The NATS JetStream implementation initializes only Group, so
Go's zero value selects AutoAck: false. As a result, a default durable
JetStream consumer is created with AckExplicit, and messages are redelivered
unless every caller manually acknowledges them.

This is especially damaging to downstream consumers that rely on the documented
default. Under a bulk workload, unacknowledged messages accumulate and are
redelivered, increasing load until consumers can no longer drain the stream.

Steps to reproduce

  1. Start a NATS server with JetStream enabled.
  2. Create an events/natsjs stream.
  3. Call Consume(topic, events.WithGroup(group)) without WithAutoAck.
  4. Inspect the durable consumer with JetStream.ConsumerInfo(topic, group).

The consumer reports AckExplicitPolicy.

Expected behavior

The default should follow the events API contract and the other event stream
implementations by enabling automatic acknowledgement. Explicitly calling
events.WithAutoAck(false, ackWait) must continue to select manual
acknowledgement.

Actual behavior

The default selects manual acknowledgement because AutoAck is left at its
false zero value.

Downstream impact

This was observed with ownCloud Infinite Scale 8.1.0 during a bulk WebDAV import
of roughly 100,000 files. Durable consumers used AckExplicit, pending messages
were repeatedly redelivered, files remained in processing, and NATS became
overloaded. Setting the NATSJS default to AutoAck: true created AckNone
consumers and allowed the queue to drain.

Related downstream reports:

Proposed fix

Initialize events.ConsumeOptions with AutoAck: true in
v4/events/natsjs/nats.go and add an integration test that verifies:

  • default consumption uses AckNonePolicy;
  • WithAutoAck(false, ...) still uses AckExplicitPolicy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions