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

This package is auto-updated.

Last update: 2025-11-01 19:18:33 UTC


README

English | 中文

Build Status PHP Version Require License Latest Version Total Downloads Code Coverage

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

  1. 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
  2. Idempotency Check: Returns cached result if available and cache key is set

  3. Lock Acquisition: Acquires distributed lock using LockService.blockingRun()

  4. Execution: Runs the actual procedure logic via parent::__invoke()

  5. Result Caching: Stores result for 60 seconds (if idempotent cache key is provided)

  6. 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

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and add tests
  4. Ensure tests pass (./vendor/bin/phpunit)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

This bundle is released under the MIT License. See the LICENSE file for details.