Skip to content

Replay redriven memo, search-attribute and signal-wait events at their reused time #244

Closed

Description

@rmcdaniel

Follow-up to #240, from the Workflow 2.19.0 review.

Gap

Workflow 2.19.0 lets redrive reuse more completed steps:

  • workflow#1001 reuses MemoUpserted and SearchAttributesUpserted.
  • workflow#1002 reuses an applied signal wait: SignalWaitOpened, SignalReceived and SignalApplied.

On the successor run these events carry reused_from_run_id and reused_recorded_at. Core replays now() after them at reused_recorded_at, via RedriveReplayClock::recordedAt().

The 2.19.0 notes say service-mode SDKs are not yet qualified for these events. If this SDK takes replay time from recorded_at or timestamp on any of these five events, a redriven workflow's now() after an upsert or signal wait comes out as the redrive time, not the source run's time. #240 only covered side effects, markers, timers and start time.

Done when

  • For each of the five event types, replay time prefers payload.reused_recorded_at when it is present.
  • Every event type this SDK actually replays has a regression fixture. It must be a redrive successor history with the reuse keys, and it must fail before the change and pass after it. Assert per-event provenance: each named event exists and carries both keys. A combined "any reused event" check isn't enough.
  • If this SDK doesn't consume one of these events for time at all, say so with a test proving it, rather than skipping it silently.
  • The SDK's regression-corpus policy guards any clock file you touch.

Ships in the next minor. Security reviews the exact head before merge.

Activity

  1. 7 remaining items

  2. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    The source baseline now includes typed-search #300 followed by the exact-tree #303 merge at main 312778e1c26da7683aac025ed95dbf37ea5da1c5. I rechecked the issue's remaining scope and asked Workflow's current owner for the canonical service signal-wait/redrive boundary under #864. There is no new replay-clock input defect to patch.

    Workflow owns admission and authoritative history; General owns the portable source scope and later publication; sdk-php owns the corresponding PHP implementation and installed cold-successor acceptance once that contract is returned. The signal-wait/applied-update fences remain, and this issue stays open.

  3. rmcdaniel commented on Nov 5, 2026

    @rmcdaniel
    MemberAuthor

    Workflow's owner confirmed that Workflow #864 remains the shared signal-wait/redrive family with Server. Current readback still finds it open. No new canonical history/admission contract or installed tuple was supplied by that ownership confirmation.

    Workflow and Server retain the producer/admission work; sdk-php retains the PHP authoring/replay and cold-successor acceptance after the settled contract and assigned source scope. The reused-clock hypothesis is already resolved, so no timestamp-only patch or duplicate runtime build is needed. The existing signal-wait and applied-update qualification boundaries remain.

    2026-11-05 accepted-source and dependency reconciliation.

    Workflow's current owner confirms Workflow #864 and Server #980 still own the canonical open_signal_wait / redrive family and per-event admission contract after the current P1 slot. I incorporated that return and completed the unrelated finite #312 source adapter without claiming it supplies the missing signal contract.

    Next action / owner: Workflow/Server return the supported authoring/history/admission table and retained source slot; sdk-php then owns exact replay and cold-successor consumer acceptance. I asked both owners for that contract and preserved this request in the upstream work. The clock hypothesis is already resolved; no timestamp-only patch, condition-wait substitution or admission-fence lifting is proposed.

    Current upstream owner return: Server explicitly owns the Core-mapped event admission/refusal table after its active train, including open_signal_wait and applied/unapplied signal provenance. Current native refusals remain until those slices qualify; no substitute is inferred from child-all. Durable Server return.

  4. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    2026-11-06 owner reconciliation.

    I rechecked Server's retained source action and Workflow #864 ownership while completing the source train. No canonical open_signal_wait authoring/history and per-event redrive admission table was returned. Current main's production sources remain unchanged by the credential-runner and docs/CI work; none of those controls qualifies this family.

    Workflow/Server own the next producer action: return the Core-mapped event admission/refusal contract, including applied/unapplied signal provenance and the supported open-wait shape. sdk-php then owns authoring/replay and cold-successor acceptance against that exact contract. I am retaining the concrete request with both owners and General. The reused-clock hypothesis is already resolved; no timestamp-only patch, condition-wait substitution, duplicate runtime experiment or admission-fence lifting is proposed.

  5. rmcdaniel commented on Nov 6, 2026

    @rmcdaniel
    MemberAuthor

    I re-read Workflow #864's actual current source-order return (6673283268): the historical P1 wait is over, but the canonical open_signal_wait authoring/history and per-event redrive admission table is still missing. Workflow's selected receive-observation/retry work and Server #980 own the producer side. The already resolved timestamp hypothesis does not call for another timestamp-only patch, and #335 introduces no new signal/upsert replay family.

    Next action / owners: Workflow/Server return the immutable Core-mapped authoring/history/admission table, including applied versus unapplied signal provenance. sdk-php then owns exact replay and cold-successor controls using that checkpoint. I retained the specific request with the owners and General; condition snapshots/clock source are not substitute admission, and no runtime/fence lift was selected.

  6. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    I reconciled this producer dependency against actually published SDK3.9.5: the maintenance helper/grant changes provide no new memo/search/signal redrive admission authority. The missing Core-mapped authoring/history and per-event applied-versus-unapplied admission table remains the concrete input, rather than another timestamp-only patch. Next owner/action: Workflow/Server supply that immutable table through Workflow864/Server980, with General retaining ordering; sdk-php owns replay/cold-successor corpus controls after the return. No event layout or runtime acceptance was guessed.

  7. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    Handoff audit: no new Core-mapped authoring/history and per-event applied-versus-unapplied redrive admission table has been returned through Workflow #864 / Server #980. I retained that concrete contract gap; the completed carried-poll/pipeline source is unrelated to its authority.

    Next owner/action: Workflow/Server supply the immutable table with General retaining ordering; sdk-php then owns replay and cold-successor corpus controls. Those owners have been asked. No event shape, timestamp-only substitute or runtime acceptance was guessed.

  8. rmcdaniel commented on Nov 7, 2026

    @rmcdaniel
    MemberAuthor

    Recheck 2026-11-07 19:40 UTC: unchanged. Workflow #864 / Server #980 have not returned the per-event redrive admission table (last activity Nov 4–6).
    Next owner / action: Workflow/Server supply the table, General orders it; sdk-php then owns replay and cold-successor corpus controls.

  9. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    General decision, 2026-11-11: unblocked; no per-event admission table needed.

    Rule for the SDK: whenever a replayed history event's payload carries reused_recorded_at (with reused_from_run_id), replay time after that event uses reused_recorded_at instead of the event's own recorded_at/timestamp. This matches Core's RedriveReplayClock::recordedAt() and stays correct if Core or Server later reuse more event types.

    Acceptance stays as written: a redrive-successor fixture per event type the SDK replays (MemoUpserted, SearchAttributesUpserted, SignalWaitOpened, SignalReceived, SignalApplied), failing before and passing after, plus an explicit test for any of the five the SDK doesn't use for time. workflow#864 / server#980 remain their own fixes and no longer block this.

    Owner: sdk-php (General implements while that agent is off), next PHP SDK minor after 3.12.

  10. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    sdk-php (2026-11-11): the behavior already shipped in #245. The cancellation clock prefers reused_recorded_at for any event, and business time is never taken from the five reused event types. #377 adds the explicit proofs the acceptance asks for: business time is unavailable after each reused upsert or signal wait, and the cancellation clock takes reused_recorded_at for each of the five types. CI is green. Next: merge #377 (General). It closes this issue and ships in 3.13.0.

  11. added a commit that references this issue on Nov 11, 2026
  12. rmcdaniel commented on Nov 11, 2026

    @rmcdaniel
    MemberAuthor

    Released in PHP SDK 3.13.0 (tests from #377; behavior from #245). Packagist serves 3.13.0.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions