idempotency: docs table, pitfall 9, changelog; lock scan fix

This commit is contained in:
CRTkafa 2026-10-12 04:03:23 +08:00
parent 8f41ed4c02
commit d5bc7b8889
4 changed files with 54 additions and 2 deletions

View file

@ -1,6 +1,6 @@
---
name: store-pitfalls
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins. Read it before any store task, and when a store command does something you did not expect.
description: Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins, duplicates from retries, re-runs and parallel runs. Read it before any store task, and when a store command does something you did not expect.
---
# Store pitfalls
@ -67,6 +67,22 @@ Each entry: **symptom** → cause → what to do → what guards it now. The ful
- **Do:** run `scan` from the project root; check that the stack line lists the plugins.
- **Guard:** `storebound scan` and `privacy-manifest` resolve packages through workspace folders too.
## 9. A second run (or a retry) creates a duplicate
- **Symptom:** two in-app purchases or subscription groups with the same name, a screenshot twice in a set, an
offer code campaign or a custom product page twice, after a timeout, a crash, a re-run a minute later, or two runs
at once.
- **Cause:** a POST create retried after a timeout or a 5xx may have been applied the first time; the store's lists lag
right after a create, so a re-run does not see what the last run made; two writers race; a Play edit redone after
a commit whose answer was lost.
- **Do:** just run the command again: every write command is an upsert and converges (`docs/idempotency.md`). Never
retry a create by hand (`storebound api`) without a GET first. If a run says another storebound run holds the lock,
wait for it; use `--force-unlock` only when that run is really gone. Never run two write commands for the same app
in parallel.
- **Guard:** `cli/lib/upsert.ts` (findOrCreate: fresh re-check + journal `.storebound/created.json`; createOnce: 409
= found, an unclear answer is looked up, never re-sent blindly), retries only for requests that are safe twice,
Play edits deleted on every error and never redone after an unclear commit, screenshot / preview sets keep the
matching prefix in order, `.storebound/locks/` per app and store. `tests/idempotency.test.ts`.
## Adding a lesson
Every bug found in real use gets an entry in `docs/pitfalls.md` and here, and, where possible, a check or a test
that fails without the fix (see CONTRIBUTING.md).