Br atomic idempotency
Skill Lonsdale201/wp-agent-skills/better-route/br-atomic-idempotency
A community-maintained collection of agent skills for WordPress plugin and theme development.
npx -y skills add Lonsdale201/wp-agent-skills --skill br-atomic-idempotencyAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Configure better-route 1.1 AtomicIdempotencyMiddleware for side-effectful POST, PUT, PATCH, or DELETE routes where concurrent duplicate execution must be prevented. Use for WpdbAtomicIdempotencyStore, lease-aware reservations, reservation_token schema migration, Idempotency-Key validation, idempotency_in_progress/conflict/replay behavior, safe stored responses, releaseOnThrowable, Woo write idempotency, or retry-safe payment/order/subscription/account operations.
SKILL.md
5.4 KB, as published. Nobody here has run it
better-route: atomic idempotency
Use atomic idempotency for writes whose side effect must not execute twice under concurrent retries. It reserves before invoking the handler; classic IdempotencyMiddleware only stores after completion.
Production setup
use BetterRoute\Middleware\Write\AtomicIdempotencyMiddleware;
use BetterRoute\Middleware\Write\WpdbAtomicIdempotencyStore;
register_activation_hook(__FILE__, static function (): void {
(new WpdbAtomicIdempotencyStore())->installSchema();
});
$atomic = new AtomicIdempotencyMiddleware(
store: new WpdbAtomicIdempotencyStore(),
ttlSeconds: 86400,
requireKey: true,
);
$router->post('/payments', $handler)
->protectedByMiddleware('bearerAuth')
->middleware([$auth, $atomic]);
Run installSchema() for both new installs and 1.0 upgrades. The 1.1 table has a per-reservation reservation_token; the installer creates or migrates that column.
Use ArrayAtomicIdempotencyStore only in tests or non-WordPress single-process checks.
Behavior
- First request reserves the canonical route + identity + client key and runs the handler.
- Same key and fingerprint while reserved returns
409 idempotency_in_progress. - Same key with a different fingerprint returns
409 idempotency_conflict. - Completed identical retry replays status/body/headers and adds
Idempotency-Replayed: true. - Missing key returns
400 idempotency_key_requiredwhen required. - Invalid, non-printable, or overlong keys return
400 idempotency_key_invalid; default maximum length is 200.
The default fingerprint deeply canonicalizes route, method, identity, and request params. Associative key order does not change it; list order remains meaningful. Native logged-in WordPress users, auth middleware identities, and HMAC key identities scope defaults safely.
Failure semantics
In 1.1 releaseOnThrowable defaults to false. A thrown exception can occur after an irreversible external side effect but before the response is recorded, so the reservation remains in_progress until TTL rather than allowing a dangerous automatic retry.
Set releaseOnThrowable: true only if the complete operation is transactional/rollback-safe or the handler is known to fail before any side effect:
new AtomicIdempotencyMiddleware(
store: $store,
releaseOnThrowable: true,
);
Returned WP_Error values are not serialized and leave the reservation uncertain. They are normalized after the middleware pipeline.
Stored response contract
The wpdb store serializes a data-only envelope with allowed_classes => false:
- arrays, scalars, and null are supported;
BetterRoute\Http\Responseis decomposed into body/status/string headers;WP_REST_Responseis normalized into the same safe Response form;- arbitrary objects/resources inside the body are rejected.
Do not return domain objects from idempotent handlers; map them to data first.
Lease-aware completion and release include the unpredictable reservation token. A stale request therefore cannot complete or delete a newer reservation that reused the same key after expiry.
WooCommerce registrar
When Woo idempotency is enabled in WordPress, WooRouteRegistrar uses atomic idempotency across orders, products, customers, and coupons. Without a custom store it installs/migrates the wpdb store once per schema version. Installation failure is surfaced; it does not silently degrade to an array store.
'idempotency' => [
'enabled' => true,
'requireKey' => true,
'ttlSeconds' => 86400,
// 'store' => $customAtomicStore,
],
Any custom Woo store must implement AtomicIdempotencyStoreInterface.
Review checklist
- Put authentication before atomic idempotency.
- Install/migrate the wpdb schema before serving traffic.
- Choose TTL for the longest realistic uncertain/retry window.
- Keep the default fail-closed
releaseOnThrowable: falseunless retry safety is proven. - Return data-only responses.
- Load-test two simultaneous identical requests; exactly one handler may run.
- Test same key with a changed body and verify
idempotency_conflict. - Use a custom key/fingerprint resolver only when tenant/domain scope cannot be expressed by the default identity-aware canonical form.
Related skills
- Use
br-idempotencyfor lower-risk replay-cache semantics. - Use
br-woo-routesfor registrar integration. - Use
br-error-contractfor 400/409 response shapes.
References
- Verified source paths:
src/Middleware/Write/AtomicIdempotencyMiddleware.phpsrc/Middleware/Write/WpdbAtomicIdempotencyStore.phpsrc/Middleware/Write/LeaseAwareAtomicIdempotencyStoreInterface.phpsrc/Middleware/Write/StoredResponseCodec.php