sbooker / persistent-sequences
Persistent sequences
Installs: 5 119
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
Requires
- php: ^7.4 || ^8.0
- sbooker/transaction-manager: ^2.0
Requires (Dev)
- phpunit/phpunit: ^9.0
Suggests
- doctrine/orm: If you want use DB persistence with Doctrine
- sbooker/doctrine-transaction-handler: If you want use DB persistence with Doctrine
README
Persistent Sequences (sbooker/persistent-sequences
)
Конкурентно-безопасная, транзакционная библиотека для создания и управления именованными персистентными последовательностями.
Назначение библиотеки
Эта библиотека является идеальным инструментом для построения единых центров генерации идентификаторов (ID) и бизнес-номеров.
В сложных системах стандартного AUTO_INCREMENT
бывает недостаточно. SequenceGenerator
решает следующие задачи:
- Централизованная генерация ID: В распределенных системах или при использовании подхода DDD, где ID сущности должен быть сгенерирован до ее сохранения,
SequenceGenerator
может выступать как надежный и транзакционный источник уникальных ID. - Именованные бизнес-последовательности: Создание независимых последовательностей для счетов (
INV-001
), заказов (ORD-002
) и т.д. - Атомарность: Гарантированное получение следующего значения в последовательности вместе с другими операциями в рамках одной транзакции.
- Надежность: Безопасная генерация в СУБД, где
AUTO_INCREMENT
имеет проблемы в кластерных конфигурациях.
Библиотека интегрирована с sbooker/transaction-manager, что гарантирует безопасность при одновременном доступе.
Ключевые особенности
- Централизованная генерация ID: Может использоваться как единый источник правды для генерации уникальных идентификаторов сущностей.
- Транзакционная безопасность: Генерация нового значения происходит внутри транзакции, управляемой
transaction-manager
. - Безопасность при конкурентном доступе: Использует
getLocked()
для предотвращения гонок данных. - Именованные последовательности: Неограниченное количество независимых последовательностей.
- Гибкие алгоритмы: Используйте встроенный
Increment
или создайте собственную реализацию интерфейсаAlgorithm
. - Разделение чтения и записи (CQRS):
SequenceGenerator
для изменения иSequenceReader
для безопасного чтения текущего значения.
Установка
composer require sbooker/persistent-sequences
Вам также понадобится sbooker/transaction-manager
и его адаптер для вашей ORM.
Быстрый старт
Шаг 1: Конечная цель — простое получение ID
Ваш прикладной код для генерации уникальных ID или бизнес-номеров будет выглядеть максимально просто:
// Генерируем следующий уникальный ID для нового пользователя $nextUserId = (int)$sequenceGenerator->next('users_pk', new Algorithm\Increment(1)); $user = new User($nextUserId, /* ... */); $transactionManager->persist($user); // Получаем следующий номер для счета $nextInvoiceNumber = $sequenceGenerator->next('invoices', new InvoiceAlgorithm()); // $nextInvoiceNumber будет "INV-2023-0001"
Шаг 2: Сборка зависимостей
Для работы SequenceGenerator
требуется TransactionManager
.
// bootstrap.php или ваш DI-контейнер /** @var Sbooker\TransactionManager\TransactionManager $transactionManager */ $sequenceGenerator = new Sbooker\PersistentSequences\SequenceGenerator($transactionManager);
Шаг 3: Чтение текущего значения без блокировки (опционально)
Если вам нужно просто узнать последнее сгенерированное значение, не увеличивая его, используйте SequenceReader
.
1. Реализуйте SequenceReadStorage
:
// src/Infrastructure/Persistence/DoctrineSequenceReadStorage.php use Doctrine\ORM\EntityManagerInterface; use Sbooker\PersistentSequences\Sequence; use Sbooker\PersistentSequences\SequenceReadStorage; final class DoctrineSequenceReadStorage implements SequenceReadStorage { /* ... */ }
2. Соберите и используйте SequenceReader
:
// bootstrap.php или ваш DI-контейнер /** @var DoctrineSequenceReadStorage $readStorage */ $sequenceReader = new Sbooker\PersistentSequences\SequenceReader($readStorage); // В вашем коде: $lastUserId = $sequenceReader->last('users_pk');
Продвинутое использование: собственный алгоритм
Вы можете легко создать свой алгоритм, реализовав интерфейс Algorithm
.
// src/Sequences/InvoiceAlgorithm.php use Sbooker\PersistentSequences\Algorithm; final class InvoiceAlgorithm implements Algorithm { public function first(): string { return "INV-2023-0000"; } public function next(string $currentValue): string { // Простая (но не идеальная) реализация для примера [$prefix, $year, $number] = explode('-', $currentValue); $nextNumber = str_pad((string)((int)$number + 1), 4, '0', STR_PAD_LEFT); return "$prefix-$year-$nextNumber"; } } // Использование: $nextInvoiceNumber = $sequenceGenerator->next('invoices', new InvoiceAlgorithm()); // вернет "INV-2023-0001"
License
See LICENSE file.