skip to content
szczecin 53.43N 14.55E ./start-project

symfony-nats-messenger 5.4: duplicate protection

(php, symfony, nats, release-notes) 1 min read by Bartosz Pachołek

A send that timed out may still have stored the message. 5.4 lets JetStream drop the copy, and 5.4.1 makes it work across transports.

A send() that times out may still have stored the message, so dispatching it again stores it twice. Symfony can do the same on its own: when a worker stops after a retry or failure-transport send that timed out, NATS redelivers the original. symfony-nats-messenger 5.4 closes that gap with JetStream's own deduplication.

Duplicate protection (5.4.0)

The new DeduplicationIdStamp sets the Nats-Msg-Id header that JetStream deduplicates by, within the stream's stream_duplicate_window.

  • With deduplicate: true, every message gets an id on its first send and the id travels with the message. A copy Symfony sends again is dropped, while each retry stays a message of its own.
  • An application can add its own stamp for a message it dispatches again itself:
php
$bus->dispatch($message, [new DeduplicationIdStamp('order-placed-42')]);

Both are off by default. 5.4.0 also makes getMessageCount() give up after one connection attempt, so messenger:stats against a server that is down waits 6 seconds instead of 12.

Across transports (5.4.1)

With deduplicate on, a message routed to two transports on one stream lost the second copy: JetStream deduplicates per stream, whatever the subject. The id now also holds the transport's subject, and failure-transport copies hold the transport the message failed on.

5.4.1 also fixes the connection check around pulls. A pull that got no answer was read as an empty batch, so a consumer on a half-open connection pulled empty batches for about 90 seconds. Now the next operation sends a PING first and moves to a new connection if it goes unanswered.

Quality

PHPStan at level max, 528 unit tests, 52 Behat scenarios against live NATS servers, and a mutation gate that now really runs the tests it scores: 826 of 858 mutants killed (96.3%), with the rest listed and explained. Details are in the changelog.