{"id":19070046,"url":"https://github.com/pyaesoneaungrgn/atomic-locks-middleware","last_synced_at":"2025-04-28T14:13:16.286Z","repository":{"id":190289340,"uuid":"682322117","full_name":"PyaeSoneAungRgn/atomic-locks-middleware","owner":"PyaeSoneAungRgn","description":"A package designed to ensure that only one request is processed at a time.","archived":false,"fork":false,"pushed_at":"2025-02-03T22:06:36.000Z","size":65,"stargazers_count":34,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-28T14:13:09.855Z","etag":null,"topics":["double-click","hacktoberfest","laravel","middleware"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PyaeSoneAungRgn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-23T23:37:19.000Z","updated_at":"2025-02-03T22:06:33.000Z","dependencies_parsed_at":"2024-03-05T03:45:00.191Z","dependency_job_id":"c08aac11-292c-4b37-a4ed-a7382e440a31","html_url":"https://github.com/PyaeSoneAungRgn/atomic-locks-middleware","commit_stats":null,"previous_names":["pyaesoneaungrgn/atomic-locks-middleware"],"tags_count":7,"template":false,"template_full_name":"spatie/package-skeleton-laravel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyaeSoneAungRgn%2Fatomic-locks-middleware","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyaeSoneAungRgn%2Fatomic-locks-middleware/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyaeSoneAungRgn%2Fatomic-locks-middleware/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PyaeSoneAungRgn%2Fatomic-locks-middleware/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PyaeSoneAungRgn","download_url":"https://codeload.github.com/PyaeSoneAungRgn/atomic-locks-middleware/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251326851,"owners_count":21571636,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["double-click","hacktoberfest","laravel","middleware"],"created_at":"2024-11-09T01:16:41.346Z","updated_at":"2025-04-28T14:13:16.265Z","avatar_url":"https://github.com/PyaeSoneAungRgn.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Atomic Locks Middleware\n\nA package designed to ensure that only one request is processed at a time.\n\n## Installation\n\n```bash\ncomposer require pyaesoneaung/atomic-locks-middleware\n```\n\n## Usage\n\nBy default, the atomic-locks-middleware uses `$request-\u003euser()?-\u003eid ?: $request-\u003eip()` within atomic locks.\n\n```php\nRoute::post('/order', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware');\n```\n\nIf you prefer to implement IP-based locking, you can use `atomic-locks-middleware:ip`.\n\n```php\nRoute::post('/order', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware:ip');\n```\n\nHowever, you have the flexibility to define `atomic-locks-middleware:{anything}` to customize the locking mechanism according to your preferences.\n\n```php\nRoute::post('/order', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware:{anything}');\n```\n\nYou can also pass additional parameters to the middleware for more customization. The available parameters are:\n- `{anything} (string)` : Your custom locking mechanism.\n- `{lockDuration} (int)` : Duration for which the lock will be held.\n- `{canBlock} (bool)` : Whether the request can wait for the lock or not.\n- `{blockDuration} (int)` : If waiting is allowed, the maximum duration to wait for the lock.\n\n\u003e If no additional parameters are provided, the default values from the config file will be used.\n\n```php\nRoute::post('/order', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware:{anything}');\n\n\nRoute::post('/purchase', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware:{anything},60,true,60');\n\n\nRoute::post('/payment/process', function () {\n    // ...\n})-\u003emiddleware('atomic-locks-middleware:{anything},60,false');\n```\n\n## How Does It Work?\n\n```php\n// AtomicLocksMiddleware.php\n\n public function handle(Request $request, Closure $next, string $option = null, int $lockDuration = null, string $canBlock = null, int $blockDuration = null): Response\n{\n    if (! empty($canBlock)) {\n        $canBlock = filter_var($canBlock, FILTER_VALIDATE_BOOLEAN);\n    }\n\n    $name = match ($option) {\n        null =\u003e $request-\u003euser()?-\u003eid ?: $request-\u003eip(),\n        'ip' =\u003e $request-\u003eip(),\n        default =\u003e $option\n    };\n\n    $name = \"{$request-\u003epath()}_{$name}\";\n\n    $lock = Cache::lock(\n        config('atomic-locks-middleware.lock_prefix') . $name,\n        $lockDuration ?: config('atomic-locks-middleware.default_lock_duration')\n    );\n\n    if (! $lock-\u003eget()) {\n        if (! ($canBlock ?? config('atomic-locks-middleware.can_block'))) {\n            return response()-\u003ejson([\n                'message' =\u003e config('atomic-locks-middleware.message'),\n            ], 429);\n        }\n\n        try {\n            $lock-\u003eblock($blockDuration ?: config('atomic-locks-middleware.default_block_duration'));\n        } catch (LockTimeoutException) {\n            $lock-\u003erelease();\n\n            return response()-\u003ejson([\n                'message' =\u003e config('atomic-locks-middleware.block_timeout_error_message'),\n            ], 500);\n        } catch (Throwable $th) {\n            $lock-\u003erelease();\n\n            return response()-\u003ejson([\n                'message' =\u003e $th-\u003egetMessage(),\n            ], 500);\n        }\n    }\n\n    app()-\u003einstance(config('atomic-locks-middleware.instance'), $lock);\n\n    return $next($request);\n}\n\n/**\n * Handle tasks after the response has been sent to the browser.\n */\npublic function terminate(Request $request, Response $response): void\n{\n    $instanceName = config('atomic-locks-middleware.instance');\n\n    if (app()-\u003ebound($instanceName)) {\n        app($instanceName)-\u003erelease();\n    }\n}\n```\n\nThe Atomic Locks Middleware uses [Laravel Atomic Locks](https://laravel.com/docs/10.x/cache#atomic-locks) in the background. It initiates a lock at the beginning of the middleware's execution and releases the lock once the response is dispatched to the browser.\n\n## Publish Configuration\n\nPublish the configuration for customization\n\n```bash\nphp artisan vendor:publish --provider=\"PyaeSoneAung\\AtomicLocksMiddleware\\AtomicLocksMiddlewareServiceProvider\"\n```\n\n```php\nreturn [\n\n    'middleware_name' =\u003e 'atomic-locks-middleware',\n    'middleware_class' =\u003e PyaeSoneAung\\AtomicLocksMiddleware\\AtomicLocksMiddleware::class,\n\n    'instance' =\u003e 'AtomicLocksMiddleware',\n\n    'lock_prefix' =\u003e 'atomic_locks_middleware_',\n    'default_lock_duration' =\u003e 60,\n\n    'can_block' =\u003e false,\n    'default_block_duration' =\u003e 60, // It's generally recommended to set the block duration to be longer than the lock duration.\n    'block_timeout_error_message' =\u003e 'Timeout: Unable to acquire lock within the specified time.',\n\n    'message' =\u003e 'Too Many Attempts',\n];\n\n```\n\n## Testing\n\n```php\ncomposer test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyaesoneaungrgn%2Fatomic-locks-middleware","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpyaesoneaungrgn%2Fatomic-locks-middleware","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyaesoneaungrgn%2Fatomic-locks-middleware/lists"}