Sitelet https://github.com/feldera/feldera/pull/6930
Skip to content

[adapters] Add the set of running syncs to CheckpointSyncStatus. - #6930

Open
blp wants to merge 1 commit into
mainfrom
checkpoint-running-syncs
Open

[adapters] Add the set of running syncs to CheckpointSyncStatus.#6930
blp wants to merge 1 commit into
mainfrom
checkpoint-running-syncs

Conversation

@blp

@blp blp commented Aug 25, 2026

Copy link
Copy Markdown
Member

CheckpointSyncStatus reports the status of checkpoint sync activity, but it didn't give enough information to tell what syncs were currently in progress. This adds a new field running to track that.

Describe Manual Test Plan

This is just unit tests so far.

Checklist

  • Unit tests added/updated
  • Integration tests added/updated
  • Documentation updated
  • Changelog updated

Breaking Changes?

No, it's careful to avoid them.

@blp
blp requested a review from swanandx August 25, 2026 15:18
@blp blp self-assigned this Aug 25, 2026
@blp blp added ft Fault tolerant, distributed, and scale-out implementation API Distributed system APIs connectors Issues related to the adapters/connectors crate storage Persistence for internal state in DBSP operators rust Pull requests that update Rust code python Pull requests that update python code enterprise Issue related to Feldera Enterprise features. labels Aug 25, 2026
Comment thread python/tests/platform/test_checkpoint_sync.py Outdated
Comment thread crates/adapters/src/server.rs Outdated
Comment thread crates/adapters/src/server.rs
Comment thread crates/feldera-types/src/checkpoint.rs Outdated
@mythical-fred-oss

Copy link
Copy Markdown

Ran locally: cargo check --locked -p feldera-types and -p dbsp_adapters (both clean), uv run --locked pytest tests/unit in python/ (89 passed), and drove Pipeline.sync_checkpoint_status directly against synthetic responses — the new-server, old-server, UUID-object and re-sync-of-a-previous-success cases all classify correctly, and the last one is a genuine improvement over the old uuid > success heuristic. The CheckpointSyncGuard shape is right: RAII release means an aborted or panicking sync task still frees its slot, and #[serde(default)] keeps a new manager readable against an old pipeline. Three things to fix, detailed inline:

# Gate Issue
1 Flaky tests (zero tolerance) _drain_sync breaks on the sticky success/failure record, so the second call in test_sync_status_running_after_failure returns on sync #1's leftover failure and then asserts running == [] while sync #2 is still in flight
2 Docs for user-visible changes docs.feldera.com/docs/pipelines/checkpoint-sync.md documents the response field-by-field with four literal example bodies; running is in none of them
3 Correctness unreachable!() fires while the MutexGuard is held, poisoning the mutex and permanently 500-ing all three checkpoint-sync endpoints

Uncovered cases worth adding, in rough priority order: (a) saw_running is only printed, never asserted, so no test deterministically proves running is ever populated — a server that never implemented the field passes both tests whenever the poll misses the window; (b) the de-duplication path (try_new returning None) has no test at all, even though it is the only new behavioural change on the REST surface; (c) Pipeline.sync_checkpoint_status is pure response-parsing and belongs in python/tests/unit with a mocked client — the running-present, running-absent and stale-success branches are all cheap to pin there and would not need a live instance; (d) nothing exercises two distinct UUIDs in running concurrently, which is the case the BTreeSet exists for. python/tests/platform needs a live Feldera instance, so I read those rather than running them. Commit message is good — imperative subject, body explains the why.

@blp
blp marked this pull request as draft August 25, 2026 15:39
@blp
blp force-pushed the checkpoint-running-syncs branch from 921ef20 to 9667106 Compare August 25, 2026 16:51
@blp
blp marked this pull request as ready for review August 25, 2026 16:52
Comment thread python/tests/platform/test_checkpoint_sync.py Outdated
Comment thread crates/adapters/src/server.rs Outdated
uuid = self.pipeline.sync_checkpoint()
self.assertEqual(str(uuid), str(chk_uuid))

status, _ = self._drain_sync(uuid)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw_running is discarded here, so the happy-path test never asserts that running is ever non-empty — it only checks the invariant "visible in running or in a terminal slot", which an implementation that never populates running at all would also satisfy (success gets set either way). Combined with the race in test_sync_status_running_after_failure, no test reliably exercises the feature this PR adds. Deleting CheckpointSyncGuard::try_new's insert would still leave both integration tests green.

Comment thread crates/adapters/src/server.rs
@mythical-fred-oss

Copy link
Copy Markdown

Reviewed against feldera-pr-checks. Design is sound — running is inserted under the same lock that later moves the UUID to success/failure, and it happens before the 202 is written, so a client polling after the request can't see the UUID vanish. #[serde(default)] plus the manager forwarding the pipeline's body verbatim (forward_http_request_to_pipeline_by_name) means the "field absent = old pipeline" contract the SDK relies on really does hold end to end. Docs, openapi regeneration and the commit message are all in good shape.

What I ran

Check Result
cargo check --locked -p dbsp_adapters -p feldera-types pass
cargo fmt -p dbsp_adapters -p feldera-types -- --check pass
uv run --locked pytest tests/unit 103 pass (14 new)
pre-commit run --files <changed> ruff / ruff-format / cargo-doc pass; one hook died fetching postgresql_embedded (sandbox network, not this PR)
python/tests/platform/* read only — no Feldera instance here

Gates

  • Flaky tests — fails. test_sync_status_running_after_failure's 5-attempt saw_running loop is a race against a local MinIO 403, and it self.fail()s when it loses. Details inline.
  • Unit tests — weak. The Python classifier is well covered, but the Rust guard (coalescing, Drop) has no test at all, and the happy-path integration test discards saw_running, so removing the running bookkeeping entirely would leave both integration tests green.

Uncovered cases I found

  1. success and failure both naming the same UUID — the SDK reports Success for a re-sync that failed (verified locally); inline suggestion clears the stale slot server-side.
  2. Multihost / coordination_checkpoint_push coalescing — both new tests are @single_host_only.
  3. Guard dropped without completed() (task cancelled at shutdown): UUID leaves running with no terminal record, so sync_checkpoint(wait=True) polls to timeout.
  4. periodic and running interacting — docs say periodic syncs never appear in running; nothing asserts it.
  5. running non-empty for a different UUID is covered in the unit table, but not running: [OTHER] combined with an old-pipeline response shape.

@blp
blp marked this pull request as draft August 25, 2026 17:22

@swanandx swanandx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i didn't click approve in case we decide to make those changes mentioned in comments, PR looks good to me otherwise

Comment thread crates/feldera-types/src/checkpoint.rs
Comment thread crates/adapters/src/server.rs
@blp
blp force-pushed the checkpoint-running-syncs branch 2 times, most recently from 69c0524 to 81d51d0 Compare August 25, 2026 18:57
@blp
blp marked this pull request as ready for review August 25, 2026 18:58
Comment thread crates/adapters/src/server.rs
Comment thread docs.feldera.com/docs/pipelines/checkpoint-sync.md
Comment thread python/tests/platform/test_checkpoint_sync.py Outdated
Comment thread python/feldera/pipeline.py Outdated
@mythical-fred-oss

Copy link
Copy Markdown

Ran cargo check --locked -p feldera-types -p dbsp_adapters (clean), uv run --locked pytest tests/unit in python/ (104 passed, including the 15 new ones), and pre-commit run --files <changed> (all hooks pass, Update OpenAPI confirms the spec is in sync). Read python/tests/platform/test_checkpoint_sync.py rather than running it. The design is nice — registering in running before answering the 202 closes the observation window, and the guard makes the release-on-drop path hard to get wrong. Two things to resolve before merge, both inline: the success = None on a later failure of the same UUID is a user-visible regression (last_successful_checkpoint_sync() starts raising "no checkpoints have been synced yet" for a checkpoint that is sitting in the bucket), and BLACKHOLE_ENDPOINT bakes in a runner-network assumption that turns into a red test elsewhere. One gate to call out: the changed server behaviour — coalescing, and clearing the opposite outcome — has no Rust unit test, and its only coverage is @enterprise_only platform tests that are skipped in the OSS run; the new unit tests cover the SDK classifier, not sync_checkpoint().

Cases the tests do not reach:

case note
success, then a failed re-sync of the same UUID the status.success = None branch — never executed by any test
failure, then a successful re-sync the failure.take_if(...) branch — same
two different checkpoints syncing at once running is a set but is only ever exercised with one element
coalescing on /coordination/checkpoint/push only /checkpoint/sync is tested; the multihost path shares sync_checkpoint()
running non-empty while the status query also updates periodic untested interaction

Two smaller notes, no action needed if intentional: (1) OpenAPI gives running "default": [], so generated clients coerce absent to empty and cannot make the absent-vs-empty distinction the docs tell readers to rely on — only the hand-written Python path preserves it; worth a sentence in the docs saying the distinction is SDK-level. (2) A wedged sync now blocks every future sync request for that checkpoint for the life of the process, with no timeout and no cancel — your own test_sync_status_in_flight has to stop(force=True) to get out. Also, the commit subject is fine for the size, but a short body explaining why coalescing and outcome-clearing were chosen would be worth having in the history, since neither is evident from the diff.

CheckpointSyncStatus reports the status of checkpoint sync activity, but
it didn't give enough information to tell what syncs were currently in
progress.  This adds a new field `running` to track that.

Signed-off-by: Ben Pfaff <blp@feldera.com>
@blp
blp force-pushed the checkpoint-running-syncs branch from 81d51d0 to c69c33f Compare August 25, 2026 23:45
@blp

blp commented Aug 25, 2026

Copy link
Copy Markdown
Member Author

I think I've fixed all the substantive feedback here.

@swanandx

swanandx commented Aug 26, 2026

Copy link
Copy Markdown
Member

you might need to rebase on main and regenerate openapi.json for pre merge queue tasks to pass

@swanandx swanandx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't have anything blocking, just code organization nitpick :P

thanks for the PR! 🚀

Comment on lines +2222 to +2228
fn sync_checkpoint(state: WebData<ServerState>, controller: Controller, uuid: Uuid) {
/// Tracks state for an ongoing checkpoint sync.
struct CheckpointSyncGuard {
state: WebData<ServerState>,
uuid: Option<Uuid>,
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we just moved the struct inside this method?

by inline implementation i meant getting rid of CheckpointSyncGuard

but as you replied in other comment, i'm fine either way, whether we keep it or inline implementation.

but putting it under fn defination doesn't make much sense to me

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

Labels

API Distributed system APIs connectors Issues related to the adapters/connectors crate enterprise Issue related to Feldera Enterprise features. ft Fault tolerant, distributed, and scale-out implementation python Pull requests that update python code rust Pull requests that update Rust code storage Persistence for internal state in DBSP operators

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants