ITADN

ChangeFeedProcessor: Regression in PR #5617 breaks AllVersionsAndDeletes push processor on cold start

#5846Openalexander-stetsenco 创建于 2026-05-07
needs-investigationcustomer-reported
## Describe the bug `GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes` fails on the first feed read after `StartAsync()` with HTTP 400: ``` BadRequest: Start from beginning is not supported with 'All Versions and Deletes' mode. ``` Affected SDK versions: `3.59.0` (stable) and `3.60.0-preview.0`. Same code on `3.57.0-preview.1` works. ## Bisect PR #5617 / commit `4bec24059`, file `Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorCore.cs`, lines 62–69 of `StartAsync()`: ```csharp if (!this.changeFeedProcessorOptions.StartFromBeginning && this.changeFeedProcessorOptions.StartTime == null && string.IsNullOrEmpty(this.changeFeedProcessorOptions.StartContinuation)) { // StartTime is serialized as RFC1123 (seconds precision) and interpreted as exclusive. // Back off by one second so writes occurring immediately after StartAsync are not missed. this.changeFeedProcessorOptions.StartTime = DateTime.UtcNow.AddSeconds(-1); } ``` The pre-flight that backfills `StartTime = DateTime.UtcNow.AddSeconds(-1)` (to mitigate the first-change skip reported in #5268) is unconditional on `ChangeFeedMode`. AVAD processors that don't pass an explicit start hint hit this path; the SDK frames the first feed read as `StartFromTime`, and the AVAD endpoint rejects any explicit `StartTime` — the server surfaces it as `Start from beginning is not supported with 'All Versions and Deletes' mode`. ## Repro ```csharp ChangeFeedProcessor processor = container .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes<JObject>( processorName: "repro", onChangesDelegate: (_, changes, ct) => Task.CompletedTask) .WithInstanceName($"repro-{Guid.NewGuid():N}") .WithLeaseContainer(leaseContainer) .Build(); await processor.StartAsync(); ``` Conditions: - Monitored container has `ChangeFeedPolicy` retention enabled (or the account is on Continuous backup, which auto-manages AVAD retention). - Lease container is empty (fresh deployment, no prior leases for this processor name). - No `WithStartTime` / `WithStartFromBeginning` calls (AVAD builder throws on either). The first feed read returns 400. On `3.57.0-preview.1` the same code starts cleanly from "now". ## Lease state is the same in both versions The lease fields that drive the SDK's start-position decision are identical between the working (`3.57.0-preview.1`) and broken (`3.59.0` / `3.60.0-preview.0`) versions for a freshly bootstrapped lease: ```jsonc { "LeaseToken": "3", "FeedRange": { "Range": { "min": "...", "max": "..." } }, "ContinuationToken": null, "Mode": "Full-Fidelity Feed", "Owner": null, "version": 0, "properties": {} } ``` `Owner` later differs by run state (set after a successful acquire on `3.57.0-preview.1`; null on `3.60.0-preview.0` because the processor releases on the 400). `id`, `_etag`, `_ts`, `_rid` differ by document identity. The values that determine the start position — `ContinuationToken` and `Mode` — are the same. The regression is purely in the `StartAsync` pre-flight, not in lease bootstrap. ## Suggested fix Gate the `StartTime` backfill on `ChangeFeedMode != AllVersionsAndDeletes`. AVAD has its own server-side semantics for null-continuation leases (anchor to "now"), and the −1s mitigation from #5268 isn't valid in that mode. If first-change-skip is a real concern for AVAD too, it needs a different mitigation — e.g. probe the change feed for a "now" continuation before lease creation and persist it into the lease's `ContinuationToken`. ## Test gap PR #5617 added three unit tests in `ChangeFeedProcessorCoreTests.cs` and an integration test in `DynamicTests.cs`. All cover LatestVersion only. The AVAD code path has no coverage for `StartAsync`'s start-position logic, which is why this regression shipped. ## Workaround Pin to `Microsoft.Azure.Cosmos 3.57.0-preview.1` until the regression is fixed. ## Environment - SDK Version: `3.59.0` (stable) and `3.60.0-preview.0` (both reproduce); `3.57.0-preview.1` is the last known good - OS: Linux (x64), macOS (arm64) - .NET: 8.0 - Cosmos account mode: Continuous backup (Continuous7Days), preview feature "All versions and deletes change feed mode" enabled at the account level ## Related - #5268 — the first-change-skip issue that PR #5617 set out to fix (LatestVersion only) - PR #5617 — the change that introduced this regression for AVAD
1 条评论