tourze/doctrine-entity-lock-bundle 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

tourze/doctrine-entity-lock-bundle

最新稳定版本:1.0.1

Composer 安装命令:

composer require tourze/doctrine-entity-lock-bundle

包简介

为 Doctrine 实体提供自动锁定和刷新机制

README 文档

README

PHP Version License Build Status Coverage Status

English | 中文

This Symfony Bundle provides a simple way to apply distributed locking mechanisms to Doctrine entities for handling concurrent operations.

Table of Contents

Features

  • Apply distributed locks to single entities
  • Apply distributed locks to multiple entities at once
  • Automatically refresh entity data from database after acquiring lock, ensuring data consistency

Installation

composer require tourze/doctrine-entity-lock-bundle

Add to your Symfony application's config/bundles.php:

Tourze\DoctrineEntityLockBundle\DoctrineEntityLockBundle::class => ['all' => true],

Usage

Prerequisites

Ensure your entity classes implement the Tourze\LockServiceBundle\Model\LockEntity interface:

use Tourze\LockServiceBundle\Model\LockEntity;

class User implements LockEntity
{
    // ...

    public function retrieveLockResource(): string
    {
        return 'user:' . $this->id;
    }
}

Locking Single Entity

use Tourze\DoctrineEntityLockBundle\Service\EntityLockService;

class UserService
{
    public function __construct(private readonly EntityLockService $entityLockService)
    {
    }

    public function updateUser(User $user, array $data): void
    {
        $this->entityLockService->lockEntity($user, function () use ($user, $data) {
            // Code here executes after acquiring the lock
            // Entity has been automatically refreshed to ensure data consistency
            $user->setName($data['name']);
            // ...
            return $result;
        });
    }
}

Locking Multiple Entities

use Tourze\DoctrineEntityLockBundle\Service\EntityLockService;

class TransferService
{
    public function __construct(private readonly EntityLockService $entityLockService)
    {
    }

    public function transfer(Account $from, Account $to, float $amount): void
    {
        $this->entityLockService->lockEntities([$from, $to], function () use ($from, $to, $amount) {
            // Code here executes after acquiring all locks
            // All entities have been automatically refreshed to ensure data consistency
            $from->debit($amount);
            $to->credit($amount);
            // ...
            return $result;
        });
    }
}

Testing

Run tests:

./vendor/bin/phpunit packages/doctrine-entity-lock-bundle/tests

Configuration

This Bundle uses default configuration, but you can customize lock behavior through the following methods:

Custom Lock Timeout

You can customize lock timeout by configuring the LockService in your service definitions:

# config/services.yaml
services:
    Tourze\LockServiceBundle\Service\LockService:
        arguments:
            $defaultTtl: 300 # Default lock time (seconds)
            $maxRetries: 3   # Maximum retry count

Custom Lock Store

By default, locks use Symfony's default lock store. You can configure different storage backends:

# config/packages/lock.yaml
framework:
    lock:
        default: redis
        resources:
            redis:
                redis: 'redis://localhost:6379'

Dependencies

This Bundle depends on the following components:

  • doctrine/orm: ^3.0
  • doctrine/doctrine-bundle: ^2.13
  • symfony/framework-bundle: ^7.3
  • symfony/lock: ^7.3
  • tourze/lock-service-bundle: Provides distributed locking base services
  • tourze/bundle-dependency: Automatically manages Bundle dependencies

Development dependencies:

  • phpunit/phpunit: ^11.5
  • phpstan/phpstan: ^2.1

Advanced Usage

Handling Lock Timeout

When unable to acquire a lock, the service will throw an exception. You can handle this by catching the exception:

use Tourze\LockServiceBundle\Exception\LockAcquisitionException;

try {
    $this->entityLockService->lockEntity($user, function () use ($user) {
        // Handle business logic
    });
} catch (LockAcquisitionException $e) {
    // Handle lock conflict
    throw new \RuntimeException('User is being modified by another process, please try again later');
}

Nested Locking

Support for nested locking of different entities:

$this->entityLockService->lockEntity($order, function () use ($order) {
    // Process order
    
    $this->entityLockService->lockEntity($order->getUser(), function () use ($order) {
        // Process user data simultaneously
    });
});

Custom Lock Resource Key

By implementing the retrieveLockResource() method of the LockEntity interface, you can customize the lock key:

class Order implements LockEntity
{
    public function retrieveLockResource(): string
    {
        // Use order number as lock key to ensure uniqueness
        return sprintf('order:%s:%s', $this->getOrderNumber(), $this->getId());
    }
}

License

MIT

统计信息

  • 总下载量: 862
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 3
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-04-15