Download the PHP package rasuvaeff/yii3-idempotency-db without Composer

On this page you can find all versions of the php package rasuvaeff/yii3-idempotency-db. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package yii3-idempotency-db

rasuvaeff/yii3-idempotency-db

Stable Version Total Downloads Build Static analysis License Русская версия

Database-backed idempotency storage for Yii3 APIs. Implements IdempotencyStorage from rasuvaeff/yii3-idempotency with atomic claim via INSERT (unique PK), response replay, and TTL-based expiration.

Using an AI coding assistant? llms.txt contains a compact API reference you can paste into your prompt.

Requirements

Installation

Usage

Basic setup

Run migration

Register the bundled migration by namespace — no vendor paths:

The package ships two migrations, and both are required: M260611000000CreateIdempotencyKeysTable creates the table, and M260822000000AddBodyEncodingColumn adds the body_encoding column that every claim writes. An installation created before that column existed must run migrate:up before deploying this version — see UPGRADE.md. Reverting the second one needs a driver that implements DROP COLUMN, which yiisoft/db-sqlite does not.

yiisoft/db-migration resolves the migration through Injector::make(), so it picks up the table-name value object from the container the same way the storage does — no manual wiring needed beyond setSourceNamespaces() above.

Set the table name in params — config/di.php turns it into an IdempotencyKeysTableName that reaches the migration and DbIdempotencyStorage:

Index names follow the table name (idx_my_idempotency_keys_expires_at), so two installations can share one PostgreSQL schema — index names are unique per schema there, not per table.

Do not configure the migration through the DI container. M...::class => ['__construct()' => ['table' => ...]] does not work: the migration is built by Injector::make(), which resolves arguments by type and never reads a container definition keyed by the migration's own class. Worse, adding that definition makes the container fatal at build time in every request, because the class is not autoloadable until the migration runner requires it. That recipe was documented in 1.x; it never worked.

Table schema

Column Type Description
key VARCHAR(255) PK Idempotency key value
fingerprint VARCHAR(64) SHA-256 hash of method + path + query + body
status_code SMALLINT HTTP response status code
headers TEXT JSON-encoded response headers (array<string, list<string>>)
body TEXT Response body (base64 when body_encoding says so)
body_encoding VARCHAR(16) plain or base64 — how body is stored
expires_at VARCHAR(30) Expiration timestamp (UTC, Y-m-d H:i:s)
claimed BOOLEAN Whether the key is claimed (in-progress)

headers and body deliberately carry no column DEFAULT: MySQL rejects a literal DEFAULT on a TEXT column (error 1101), and nothing needs one — every INSERT this package issues writes both columns explicitly.

Yii3 integration

The package provides config/di.php and config/params.php for yiisoft/config.

Default params:

DI wiring binds IdempotencyStorage::class to DbIdempotencyStorage.

How it works

  1. Claim: INSERT with unique PK on key and expires_at = now + claimTtlSeconds. If the insert succeeds, the key is claimed atomically. A duplicate key raises a DB integrity error, which claim() converts to false; any other DB error propagates.
  2. Store: After the handler completes, the response is written only into the claim this instance owns: a conditional UPDATE matching the key, claimed = 1 and the exact expires_at this instance's claim wrote. If that row is gone — a takeover deleted it after the deadline passed — the record is inserted only when the key is absent; losing the duplicate-key race to a competitor's newer claim leaves their row untouched. claimed ends at 0 and expires_at becomes the record TTL deadline.
  3. Load: On a subsequent request with the same key, load() reads the row. An active claim (claimed = 1, deadline not reached) returns null without deleting the row — the middleware then fails its own claim() and asks claimedFingerprint(): the same payload answers 409, a different one 422 (the retry could never succeed). A stale claim (deadline passed — crashed process) is deleted and may be re-claimed. A completed record is rehydrated via IdempotencyRecord::restore() and checked against its TTL; expired records are deleted.
  4. Release: If the handler throws (or returns 5xx), release() deletes the claim row — but only the claim this storage instance took. The expires_at it wrote is the ownership token: a takeover after the claim went stale necessarily wrote a later deadline, so a late release from the previous owner matches no row and cannot delete either the competitor's claim or the response it has already stored.
  5. Cleanup: deleteExpired() removes all rows past expires_at (uses the expiration index — idx_idempotency_expires_at on the default table, idx_<table>_expires_at for a custom one). Roughly one successful claim in gcDivisor runs it in-band, so the table does not grow without a cron job; set gcDivisor: 0 to turn that off and drive the sweep yourself.

Every delete this package issues besides deleteExpired() matches an ownership predicate, but the two kinds differ:

Operation Condition
Expiration cleanup (load(), stale-claim reclaim) The claimed flag the caller read plus expires_at <= now — the row must still be the expired one it judged
Claim release (release()) The exact expires_at this instance's own claim() wrote — the ownership token; a takeover necessarily wrote a later one
Response store (store()) The same exact-deadline token on the UPDATE; the fallback INSERT only into an absent key

An unconditional DELETE WHERE key = :k cannot tell the row the caller judged from a fresh one a competitor created in between, so at the TTL boundary two requests could each delete the other's claim and both run the handler.

Security

Examples

See examples/ for runnable scripts.

Development

License

BSD-3-Clause. See LICENSE.md.


All versions of yii3-idempotency-db with dependencies

PHP Build Version
Package Version
Requires php Version 8.3 - 8.5
psr/clock Version ^1.0
rasuvaeff/yii3-idempotency Version ^2.1
yiisoft/db Version ^2.0
yiisoft/db-migration Version ^2.1
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package rasuvaeff/yii3-idempotency-db contains the following files

Loading the files please wait ...