feat(list_reservations): add expires_*/finalized_* fields + finalized_at_ms (0.2.6)#41
Merged
amavashev merged 2 commits intoMay 22, 2026
Merged
Conversation
…_at_ms (0.2.6) Client-side companion to cycles-protocol-v0.yaml revision 2026-05-22 (runcycles/cycles-protocol#98) and runcycles/cycles-server#163. Closes the Rust-client side of issue #162. Follow-up to v0.2.5 with the same shape, just four more params on the request side plus one new optional response-side field. ListReservationsParams (request): Four new Option<String> fields, each with skip_serializing_if: expires_from, expires_to, finalized_from, finalized_to. Each pair binds to its target field independent of from/to and any sort_by. finalized_* excludes ACTIVE and EXPIRED rows (finalized_at_ms absent on those rows per the spec). ReservationSummary (response): New Option<u64> field finalized_at_ms with #[serde(default)]. Populated by servers on COMMITTED and RELEASED rows only; absent (None) on ACTIVE/EXPIRED rows and on pre-v0.1.25.21 servers regardless of status. Back-compat preserved both ways by Option + serde default. Regression tests in tests/client_test.rs: * list_reservations_forwards_expires_and_finalized_windows: wiremock query_param matchers assert all four request-side fields land on the wire under the spec names. * list_reservations_deserializes_finalized_at_ms_on_summary: server emits finalized_at_ms on a COMMITTED row, client deserializes to Some(value). * list_reservations_deserializes_absent_finalized_at_ms_as_none: server emits the row WITHOUT finalized_at_ms (pre-revision server or ACTIVE row), client deserializes to None. Locks the back-compat path. No protocol or wire-format change beyond the optional response field; servers older than v0.1.25.21 silently ignore the new request params and don't emit the new response field. 134 tests pass across integration + unit suites; doc-tests + clippy clean. Out of scope (intentionally narrow, same as v0.2.5): pre-existing drift on ListReservationsParams (missing workspace / workflow / toolset / sort_by / sort_dir / idempotency_key fields relative to full v0.1.25 spec parity) is not addressed here. Worth a follow-up. Bumped to 0.2.6, refreshed Cargo.lock, updated AUDIT.md and CHANGELOG.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Client-side companion to cycles-protocol-v0.yaml revision 2026-05-22 and cycles-server#163. Closes the Rust-client side of runcycles/cycles-server#162. Follow-up to v0.2.5 with the same shape — four more params on the request side, plus one new optional field on the response side.
What this PR does
Request side:
ListReservationsParamsFour new
Option<String>fields withskip_serializing_if:Each pair binds to its target field (
expires_at_ms,finalized_at_ms) independent offrom/toand anysort_by. The three windows compose with AND.finalized_*excludes ACTIVE and EXPIRED rows per the spec (the field is absent on those rows; predicate fails).Response side:
ReservationSummaryNew
Option<u64>field with#[serde(default)]:Populated on COMMITTED and RELEASED rows; absent (
None) on ACTIVE/EXPIRED rows and on pre-v0.1.25.21 servers. Back-compat preserved both ways viaOption+#[serde(default)].ReservationSummaryis#[non_exhaustive]andDeserialize-only, so callers can't construct it directly — the new field is fully transparent to downstream code.Regression tests
Three new tests in
tests/client_test.rs:list_reservations_forwards_expires_and_finalized_windows— wiremockquery_parammatchers assert all four request-side fields land on the wire under spec names.list_reservations_deserializes_finalized_at_ms_on_summary— server emits the field on a COMMITTED row, client deserializes toSome(value).list_reservations_deserializes_absent_finalized_at_ms_as_none— server omits the field (pre-revision server or ACTIVE row), client deserializes toNone. Locks the back-compat path.Backward compatibility
ListReservationsParams: pure additive for callers using..Default::default(). Exhaustive constructors break (need to add 4 moreNoneinitializers) — same as v0.2.5, not new to this PR.ListReservationsParamslacks#[non_exhaustive]per the existing repo convention.ReservationSummary:#[non_exhaustive]+Deserialize-only, so the new optional field is transparent.Verification
cargo test(full suite): 134 tests pass, 12 ignored (live-server, by design).cargo clippy -- -W clippy::all: clean.Out of scope (intentionally narrow)
ListReservationsParamshas accumulated drift relative to the full v0.1.25 spec (missingworkspace/workflow/toolset/sort_by/sort_dir/idempotency_key). Same out-of-scope note as v0.2.5. Worth a separate follow-up to bring the struct to full spec parity.Test plan
Closes the Rust-client side of runcycles/cycles-server#162.