Skip to content

docs: draft v2 updater API design (RFC)#338

Closed
eseidel wants to merge 2 commits into
mainfrom
design/v2-api
Closed

docs: draft v2 updater API design (RFC)#338
eseidel wants to merge 2 commits into
mainfrom
design/v2-api

Conversation

@eseidel
Copy link
Copy Markdown
Contributor

@eseidel eseidel commented Apr 8, 2026

RFC / draft — not for merge. Requesting feedback on the shape.

What's here

  • docs/v2_api_design.md — motivation, goals/non-goals, proposed API, Rust C API changes, version-skew strategy, migration plan, open questions.
  • shorebird_code_push/lib/src/v2/shorebird_updater_v2.dart — illustrative Dart sketch (not wired up, not exported).

Key shape

  • One verb: checkAndInstall() returning an UpdateOperation handle with .done, .progress, .cancel().
  • Sealed UpdateOutcome result type: UpToDate | Installed | Deferred | Unavailable | Failed. No exceptions on the happy path or the "expected-but-didn't-happen" path.
  • Structured Failed with category, stable code string (metrics key), and retryable bool.
  • Unavailable is a result, not a separate isAvailable query.
  • Dart package major version bump (2.0.0); v1 stays available via `package:shorebird_code_push/v1.dart` for one release under deprecation.

What I'd most like feedback on

  1. The five-arm result taxonomy — does it carve the space the way you'd carve it?
  2. "Second caller joins the first operation" semantics (doc open question ci: add rust workflow #1).
  3. Whether `check()` should be a separate method or a parameter on `checkAndInstall()` (open question chore: add example from shorebirdtech/shorebird #4).
  4. Rust C API struct-return + progress callback + cancel token — any prior art in the codebase I should match?

Refs shorebirdtech/shorebird#3684

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@eseidel
Copy link
Copy Markdown
Contributor Author

eseidel commented Apr 21, 2026

From a claude session this morning:

One piece of real-world input for the track design (open question #2):

We hit a customer this week (on 2.0.5, mixed staging + stable users) where ~0.2%/min of their sessions were firing a post-update assertion: await updater.update() returns cleanly, but the immediate checkForUpdate() still reports updateAvailable instead of restartRequired. After walking every same-session code path, the cleanest theory that survives is track mismatch between the two call sitesupdate(track: staging) installs staging's patch N, then a wrapper like clientStatus() calls checkForUpdate() without forwarding the track, hits the default channel, gets stable's (different) patch number back, and should_install_patch returns PatchOkToInstall. Deterministic per affected code path, doesn't need any race or server activity to explain.

The current v2 sketch keeps track as a per-call default parameter on both checkAndInstall and check, so this failure mode is still representable — an app can call checkAndInstall(track: staging) and check() (default stable) and get the same asymmetry.

Suggestion: move track off the call sites entirely and onto the updater instance. Constructor-only is the strongest form — ShorebirdUpdater(track: UpdateTrack.staging), mismatch unrepresentable at the type level, "I need to query multiple tracks" = "make multiple instances." If live switching is a real need (QA flows, user-visible track selector), add an explicit switchTrack(UpdateTrack) method rather than letting individual calls override — keeps the invariant that at any given moment the updater has exactly one track, and all the read/write methods agree on which one.

Happy to prototype the Dart shape if useful.

eseidel added 2 commits May 1, 2026 10:32
Design doc + illustrative Dart sketch for a result-typed,
progress/cancel-aware, agent-friendly v2 of package:shorebird_code_push.
Not wired up; not exported; RFC only.

Refs shorebirdtech/shorebird#3684
@eseidel
Copy link
Copy Markdown
Contributor Author

eseidel commented May 18, 2026

I'm going to close this for now and pick it up from the PRD later.

@eseidel eseidel closed this May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant