Skip to content

Signals and other streams advance a shared message cursor and hide pending stream messages #1011

Closed

Description

@rmcdaniel

Problem

A run has one message cursor (workflow_runs.message_cursor_position), shared by every stream and by signals. MessageService::peekMessages and the pending-count helpers only return inbound messages with sequence > MessageStreamCursor::positionForRun($run), whatever their stream.

All of the following draw from one per-instance sequence (MessageStreamCursor::reserveNextSequence):

  • delivering a signal;
  • consuming on stream A;
  • consuming any later sequence.

Each of these moves the shared cursor past older messages that are still pending on other streams. Those messages stay pending but are never returned by inbox()->peek() / receive() / pendingCount() again.

Reproduction (main 7a758480, embedded, SQLite)

The workflow waits for a ping signal, then calls $this->inbox('chat')->receiveOne().

  1. Send m1 to the chat stream with MessageService::sendMessage.
  2. Signal ping.
  3. Run the workflow task.

Result: receiveOne() returns null, because the signal's sequence is above m1's, and m1 stays pending forever. If the signal is sent before m1, m1 is received.

Found while fixing #1010. The #1010 tests send each turn's signal before its messages so they test replay behavior only.

Expected

A message on one stream should stay receivable until it is consumed or expires, whatever happens on other streams or with signals. Either the cursor is kept per stream, or reads filter on consume_state alone and keep the sequence only for ordering.

Notes

  • Changing the cursor model affects MessageCursorAdvanced history, continue-as-new cursor transfer and redrive cursor transfer, so it needs its own design and review. It is not part of the Workflow-code outbox()->sendReference() writes new messages on every replay #1010 patch.
  • Until it's fixed, the Message Streams guide should say that a signal or a receive on another stream can hide older pending messages.

Activity

  1. added
    kind:defectA public product behavior is incorrect
    priority:P2Normal-priority product work
    status:triageAwaiting maintainer classification
    on Nov 3, 2026
  2. added
    status:in-progressApproved work is actively being implemented or validated
    and removed
    status:triageAwaiting maintainer classification
    on Nov 4, 2026
  3. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    The source fix is merged as #1017, commit a806a83ad5dff56adb9e166fa0d9a4be1d9db130, after independent review and verification that the merge tree equals the cleared head.

    It is not in a published stable package yet. Release draft #1025 targets 2.20.3 and retains the related query limitation #1024 plus the kept-stream downgrade warning. Security review, release qualification and an explicit tag go remain before publication. Published-package and downstream evidence will be linked here after delivery.

  4. rmcdaniel commented on Nov 4, 2026

    @rmcdaniel
    MemberAuthor

    Delivered in accepted stable Workflow 2.20.3, immutable commit 4cfa985b0aff1cef9b0f3df518b1d6c20023fa5c; Packagist source and dist match. The sole published verifier passed its package contract and all 12 supported PHP/Laravel upgrade cells. Installed-package acceptance passed stream authoring, all 18 stream-replay cases and the 25-case replay corpus against actual Composer-installed 2.20.3, with all runtime blobs/origins verified. Final Security acceptance is recorded.

    The kept-stream downgrade warning remains in the published notes. The related query-handler replay defect #1024 remains open and is the next narrow investigation; this receipt does not claim that query bug is fixed. Consumer delivery gaps remain explicit: Sample App and documentation source adoption are assigned to their owners, and Waterline returns a plan preserving frozen 2.15.0 evidence. Consumer merge/release/deployment decisions remain separate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:defectA public product behavior is incorrectpriority:P2Normal-priority product workstatus:in-progressApproved work is actively being implemented or validated

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions