tourze / json-rpc-lock-bundle
JsonRPC锁定处理
Installs: 7 426
Dependents: 16
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/tourze/json-rpc-lock-bundle
Requires
- psr/log: ^3|^2|^1
- symfony/cache-contracts: ^3
- symfony/config: ^7.3
- symfony/dependency-injection: ^7.3
- symfony/framework-bundle: ^7.3
- symfony/http-kernel: ^7.3
- symfony/lock: ^7.3
- symfony/property-access: ^7.3
- symfony/security-bundle: ^7.3
- symfony/security-core: ^7.3
- symfony/service-contracts: ^3.6
- symfony/yaml: ^7.3
- tourze/backtrace-helper: 1.*
- tourze/bundle-dependency: 1.*
- tourze/json-rpc-core: 1.0.*
- tourze/lock-service-bundle: 1.0.*
Requires (Dev)
README
A Symfony Bundle that provides automatic locking functionality for JsonRPC interfaces to handle concurrent request control and idempotency.
Features
- Automatic concurrency control for JsonRPC requests
- User-based lock resource identification
- Request idempotency handling with caching
- Graceful exception handling and logging
- Support for custom lock resource strategies
- Fallback retry mechanism for lock failures
Dependencies
This bundle requires:
- PHP 8.1 or higher
- Symfony 7.3 or higher
- tourze/json-rpc-core
- tourze/lock-service-bundle
- tourze/backtrace-helper
- Symfony Security Bundle
Installation
Install via Composer:
composer require tourze/json-rpc-lock-bundle
Configuration
Register the bundle in your Symfony application:
// config/bundles.php return [ // ... Tourze\JsonRPCLockBundle\JsonRPCLockBundle::class => ['all' => true], ];
No additional configuration is required. The bundle works out of the box with sensible defaults.
Quick Start
Create a JsonRPC procedure by extending LockableProcedure:
<?php use Tourze\JsonRPCLockBundle\Procedure\LockableProcedure; use Tourze\JsonRPC\Core\Model\JsonRpcParams; class MySecureProcedure extends LockableProcedure { public function execute(): array { // Your business logic here $params = $this->getParams(); $userId = $params->get('user_id'); $amount = $params->get('amount'); // This will be automatically locked based on user identity return ['result' => $this->processPayment($userId, $amount)]; } private function processPayment(int $userId, float $amount): string { // Your payment processing logic return 'payment_processed'; } }
Advanced Usage
Custom Lock Resources
Override the getLockResource method to customize locking behavior:
public function getLockResource(JsonRpcParams $params): ?array { // Custom lock based on specific parameters $accountId = $params->get('account_id'); return ['account_lock_' . $accountId]; } // To skip locking entirely, return null public function getLockResource(JsonRpcParams $params): ?array { return null; // No locking applied }
Idempotency Support
Enable request caching for idempotent operations:
protected function getIdempotentCacheKey(JsonRpcRequest $request): ?string { $params = $request->getParams(); return 'payment_' . $params->get('user_id') . '_' . $params->get('transaction_id'); }
Cached results expire after 60 seconds by default. If a cached result exists, it will be returned immediately without acquiring locks or executing the procedure.
Fallback Retry
Enable automatic retry without locking for non-critical operations:
public function fallbackRetry(): bool { return true; // Enable fallback retry on lock failures }
How It Works
-
Lock Resource Preparation: Based on user identity or procedure name
- Authenticated users: Uses
user.getUserIdentifier() - Anonymous requests: Uses procedure class name
- Custom: Override
getLockResource()method
- Authenticated users: Uses
-
Idempotency Check: Returns cached result if available and cache key is set
-
Lock Acquisition: Acquires distributed lock using
LockService.blockingRun() -
Execution: Runs the actual procedure logic via
parent::__invoke() -
Result Caching: Stores result for 60 seconds (if idempotent cache key is provided)
-
Exception Handling:
- Lock conflicts: Returns cached result or throws "你手速太快了,请稍候" message
- General exceptions: Logs error and optionally retries without lock if
fallbackRetry()returns true
Environment Variables
JSON_RPC_RESPONSE_EXCEPTION_MESSAGE: Custom message for lock conflict exceptions (default: "你手速太快了,请稍候")
Testing
Run the test suite:
./vendor/bin/phpunit packages/json-rpc-lock-bundle/tests
For static analysis:
php -d memory_limit=2G ./vendor/bin/phpstan analyse packages/json-rpc-lock-bundle
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your changes and add tests
- Ensure tests pass (
./vendor/bin/phpunit) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This bundle is released under the MIT License. See the LICENSE file for details.