Repository navigation
🐛 fix(memory): avoid redundant lifecycle events and feed replay - #99
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
36559a8 to
87b11ec
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 87b11ec08e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /** Opaque keyset cursor returned by the previous page. */ | ||
| cursor: z.string().min(1).max(2048).optional(), | ||
| /** First sweep only. Omission replays from the beginning. */ | ||
| startAt: z.enum(["beginning", "head"]).optional(), |
There was a problem hiding this comment.
Reject head starts when an older server ignores them
When this SDK is used against a server from before this commit, that server's Zod request schema strips the unknown startAt field and silently performs a beginning replay. Because the new response schema explicitly accepts an absent checkpointCursor, queryChangeFeed({ startAt: "head" }) succeeds and returns historical events even though the caller requested future-only changes, potentially replaying old notifications or actions. Detect the missing capability for startAt: "head" and fail rather than returning the replayed page.
Useful? React with 👍 / 👎.
Repeated lifecycle recomputation rewrites unchanged claims, producing redundant change-feed events. Completed feed consumers also have no durable cursor, so polling starts over. This change skips unchanged lifecycle writes, including deadlines removed by a later message, and adds an opaque
checkpointCursorfor incremental polling.Consumers can opt into
startAt: "head"to observe future changes without importing historical events. Existing pagination keepsnextCursor: nullat completion; existing callers retain their starting behavior. User, partition, epoch, and frozen-sweep checks remain enforced.Recent-change responses also expose the change timestamps already used for sorting. Consumers can distinguish an old memory changed today from its original authored date. The SDK keeps the added fields optional for older servers.
Validation: 101 focused tests passed against isolated PostgreSQL, including unchanged row/event counts, deadline chronology and source removal, writes during pagination, empty and subsequent polls, scope isolation, HTTP validation, and SDK parsing. Full type/schema check, lint, SDK and production builds, changed-file formatting, and
git diff --checkpassed. Read-only review findings were resolved and re-reviewed. Coverage percentage was not measured.No migration or data cleanup. No deployment or SDK publication was performed.