Idempotent package provides idempotency for your laravel package. However, in its current state, maybe not extendable to different requirements and can be used as a sample of doing so. Moreover, this package will be updated, in attempt to giving more control over various aspects of it.
To get started, install the Idempotent package via the Composer package manager:
$ composer require sobhanatar/idempotent
Idempotent service provider registers its own config, language, and database migration file, so you need to export them
$ php artisan vendor:publish --provider="Sobhanatar\Idempotent\IdempotentServiceProvider"
Note: If you don't want to use mysql database as shared memory, you can publish config, and language file using following command:
$ php artisan vendor:publish --tag=idempotent-config --tag=idempotent-language
To use idempotent package, you need set the options as per the need of your service in configuration and language files. The configuration file is self-documented so that you can find your way through.
The next step is deciding on how you want to control the idempotency of your service. Idempotent package provides two
middlewares that can help you achieve the idempotency; IdempotentHeader
, and VerifyIdempotent
. Don't forget to
register the middleware in Kernel.php
.
IdempotentHeader
makes an idempotent key/hash based on the entity's configurations and put it in the header of
request. The assumption in this middleware is that the developer will remain responsible for the logic of using the
idempotent header.
VerifyIdempotent
handles all the required steps for making an endpoint idempotent. The steps are as follows:
- Get the
entity
configuration - Create an idempotent key/hash based on the entity's configurations.
- Check if the idempotent key/hash exists in the selected
storage
. - If it doesn't exist:
- A new record with the status of
progress
be created with the entity'stimeout,
and it continues to the logic of the service - When code execution has finished, the response to the client updates the
status
andresponse
of the cache.
- A new record with the status of
- If it exists:
- If the
status
isdone
orfail
, then theresponse
will be read from storage and replied to the user. - If the
status
isprogress
, the message inidempotent
language file for thatentity
will be return as response to the user.
- If the
Note: Make sure to use any of two middlewares to only those routes that you want to be idempotent, and not all the routes.
If you use mysql
as the storage, it's important to purge the expired keys/hashes. Idempotent included
idempotent:purge
Artisan command can do this for you.
# Purge expired keys/hashes
$ php artisan idempotent:purge --entity=my-idempotent-endpoint
You may also configure a scheduled job in your application's App\Console\Kernel
class to automatically prune your
tokens on a schedule:
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('idempotent:purge')->hourly();
}
This package is relied on php-lock/lock for locking mechanism and also spatie/async for testing the locking mechanism.
$ composer test
Thank you for considering contributing to Idempotent! You can read the contribution guide here.
If you discover any security-related issues, please email sobhanattar@gmail.com instead of using the issue tracker.
Idempotent is open-sourced software licensed under the MIT license.