Skip to content

Commit e73918d

Browse files
committed
Add AckPolicy.FLOW_CONTROL and sourcing consumer test
The server requires the pre-created sourcing consumer to use the flow_control ack policy; without it the source fails at runtime with "stream source consumer requires flow control ack policy" (10217). Expose the policy on the enum and exercise the full sourcing flow from a workqueue stream against a 2.14+ server.
1 parent a61b5be commit e73918d

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

nats/src/nats/js/api.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,10 @@ class AckPolicy(str, Enum):
602602
NONE = "none"
603603
ALL = "all"
604604
EXPLICIT = "explicit"
605+
# Required on the pre-created consumer used for sourcing/mirroring from a
606+
# workqueue or interest stream (ADR-60). The sourcing stream, not a
607+
# client, drives acknowledgements.
608+
FLOW_CONTROL = "flow_control"
605609

606610

607611
class DeliverPolicy(str, Enum):

nats/tests/test_js.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5553,6 +5553,58 @@ def test_stream_source_consumer_round_trip(self):
55535553
assert round_tripped.consumer == original.consumer
55545554

55555555

5556+
class StreamConsumerSourceServerTest(SingleJetStreamServerTestCase):
5557+
@async_test
5558+
async def test_source_from_workqueue_with_consumer(self):
5559+
"""Source from a workqueue stream through a pre-created flow-control consumer (ADR-60)."""
5560+
nc = NATS()
5561+
await nc.connect()
5562+
5563+
server_version = nc.connected_server_version
5564+
if server_version.major == 2 and server_version.minor < 14:
5565+
pytest.skip("stream source consumer requires nats-server v2.14.0 or later")
5566+
5567+
js = nc.jetstream()
5568+
await js.add_stream(name="UP", subjects=["up"], retention=nats.js.api.RetentionPolicy.WORK_QUEUE)
5569+
await js.add_consumer(
5570+
"UP",
5571+
nats.js.api.ConsumerConfig(
5572+
durable_name="C",
5573+
deliver_subject="deliver.up",
5574+
ack_policy=nats.js.api.AckPolicy.FLOW_CONTROL,
5575+
),
5576+
)
5577+
cinfo = await js.consumer_info("UP", "C")
5578+
assert cinfo.config.ack_policy == nats.js.api.AckPolicy.FLOW_CONTROL
5579+
5580+
info = await js.add_stream(
5581+
name="DOWN",
5582+
sources=[
5583+
nats.js.api.StreamSource(
5584+
name="UP",
5585+
consumer=nats.js.api.StreamConsumerSource(name="C", deliver_subject="deliver.up"),
5586+
)
5587+
],
5588+
)
5589+
consumer = info.config.sources[0].consumer
5590+
assert isinstance(consumer, nats.js.api.StreamConsumerSource)
5591+
assert consumer.name == "C"
5592+
assert consumer.deliver_subject == "deliver.up"
5593+
5594+
for i in range(3):
5595+
await js.publish("up", f"msg-{i}".encode())
5596+
5597+
for _ in range(50):
5598+
info = await js.stream_info("DOWN")
5599+
if info.state.messages == 3:
5600+
break
5601+
await asyncio.sleep(0.1)
5602+
assert info.state.messages == 3
5603+
assert info.sources[0].error is None
5604+
5605+
await nc.close()
5606+
5607+
55565608
class PubAckBatchTest(unittest.TestCase):
55575609
"""Unit tests for ADR-50 atomic batch publish fields on PubAck."""
55585610

0 commit comments

Comments
 (0)