Skip to content

--token-store-firestore: blind overwrite races during Cloud Run instance overlap #406

Description

@shigechika

Context

`--token-store-firestore`'s own `--help` text documents "no lock against two processes sharing one document -- safe ONLY when exactly one serve process ever writes to a given document at a time." A caller can approximate that with Cloud Run's `min/max-instances=1`, but that setting only bounds concurrent instances of a single revision -- it does not prevent the outgoing and incoming instance from running simultaneously during Cloud Run's normal instance lifecycle (a redeploy's revision cutover, or ordinary instance recycling with `min-instances=1`, both start the replacement before terminating the outgoing one). There is no "drain fully, then start" mode on Cloud Run to close this from the caller's side.

Found via ai-review while wiring this flag into a real Cloud Run deployment (jquants-mcp#575).

Impact

`_write_snapshot_locked()` does a blind `.set(snapshot)` of the full 6-store snapshot. If two processes race, the later write silently discards whatever the earlier write added (e.g. a token issued or refreshed on the other instance in the overlap window) -- no error, no merge, just data loss for that specific token. The affected client's next request fails and it must re-authenticate. Bounded and non-catastrophic (no worse than today's in-memory-only baseline, which invalidates every token on every restart), but real.

Proposed fix

Firestore supports transactions and precondition-on-generation writes. A read-modify-write transaction (or an explicit version/generation check before overwrite, aborting/retrying on conflict) would make concurrent writers safe rather than merely discouraged, closing the gap the `--help` text currently just warns about.

Scope

This affects only `--token-store-firestore`; the local-file `--token-store` path already refuses concurrent writers outright via its sidecar `.lock` file, so it is unaffected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions