Хроники Yii3
623 subscribers
43 photos
1.7K links
Описание процесса разработки фреймворка из первых рук 😎

Обсуждение:
https://yangx.top/yii3ru

Сводка по всем пакетам:
https://www.yiiframework.com/status/3.0

Поддержать разработчиков:
https://opencollective.com/yiisoft
加入频道
⚡️ #yiisoftMutex #yiisoftMutexFile #yiisoftMutexPdoMysql #yiisoftMutexPdoPgsql #yiisoftMutexPdoOracle

Полностью переосмыслен и переписан код пакета Yii Mutex (PR, PR, PR), обеспечивающий взаимное исключение исполнения критических участков кода в «состоянии гонки».

—————

Основные интерфейсы и классы

Пакет предоставляет интерфейсы и классы, которые уже используются в конкретных реализациях.

MutexInterface — интерфейс мьютекс-объекта с методами acquire() (включает блокировку) и release() (отключает блокировку).

MutexFactoryInterface — интерфейс фабрики, создающей экземпляр мьютекс-объекта с двумя методами:

- create() — создание мьютекс-объекта;

- createAndAcquire() — создание мьютекс-объекта и включение блокировки. При неудачном включении блокировки будет брошено исключение.

MutexFactory — абстрактный класс фабрики, реализующй интерфейс MutexFactoryInterface, с уже реализованным методом createAndAcquire().

RetryAcquireTrait — трейт, позволяющий выполнить несколько попыток блокировки в течение заданного времени.

В общем случае есть два варианта использования:

$mutexFactory = new MyMutexFactory();

$mutex = $mutexFactory->create('critical_logic');

if (!$mutex->acquire(1000)) {
throw new \RuntimeException('Unable to acquire "critical_logic" mutex.');
}

// business logic execution

$mutex->release();

и

$mutexFactory = new MyMutexFactory();

// При неудачной блокировке будет
// брошено исключение
$mutex = $mutexFactory->createAndAcquire('critical_logic', 1000);

// business logic execution

$mutex->release();

—————

Класс SimpleMutex

Предоставляет альтернативный вариант работы с мьютексами. Пример:

$mutex = new SimpleMutex(new MyMutexFactory());

if (!$mutex->acquire('critical_logic', 1000)) {
throw new \RuntimeException('Unable to acquire "critical_logic" mutex.');
}

// business logic execution

$mutex->release();

—————

Класс Synchronizer

Позволяет запускать callback-функции в синхронизированном режиме (в один момент времени выполняется только один экземпляр callback-функции). Пример:

$synchronizer = new Synchronizer(new MyMutexFactory());

$newCount = $synchronizer->execute('critical_logic', function () {
return $counter->increase();
}, 10);

—————

Соответствующие изменение внесены в мьютекс-драйверы:

- File Driver (PR),
- MySQL PDO Driver (PR),
- Postgres PDO Driver (PR),
- Oracle PDO Driver (PR).
⚡️ #yiisoftMutex

В пакете Yii Mutex добавлены тесты для Mutex и MutexFactory (PR).
⚡️ #yiisoftMutex

Реализована обработка ошибок в пользовательском коде при использовании класса Synchronizer из пакета Yii Mutex (PR).

• В мьютексе всегда будет снята блокировка, даже если во время выполнения callback-функции было брошено исключение.

• Если во время выполнения пользовательского кода произошла ошибка (не исключение, например E_WARNING), то такая ошибка будет преобразована в исключение ErrorException, что позволит перехватить её.

Спасибо Антону @faqphp за обнаруженную проблему 👍
⚡️ #yiisoftMutex

В документации к Yii Mutex добавлено предупреждение об особенностях использования деструкторов и shutdown-функций (PR).

—————

Выдержки из документации PHP

register_shutdown_function(): "Возможна регистрация нескольких подобных функций с помощью register_shutdown_function(), при этом функции будут выполняться в том порядке, в каком они были зарегистрированы. Если вы вызовете exit() в одной из зарегистрированных завершающих функций, процесс будет полностью остановлен и последующие завершающие функции не будут вызваны."

__destruct(): "Деструктор будет вызываться даже в том случае, если скрипт был остановлен с помощью функции exit(). Вызов exit() в деструкторе предотвратит запуск всех последующих функций завершения."

—————

Если в пользовательском коде или в других пакетах внутри деструктора или shutdown-функции работа скрипта будет остановлена с помощью die() или exit(), то автоматическое снятие блокировки в мьютексе может не сработать.
⚡️ #yiisoftMutex

В классе SimpleMutex из Yii Mutex реализовано автоматические удаление объекта мьютекса после снятия блокировки (PR).
⚡️ #yiisoftMutex

Небольшой рефакторинг тестов в Yii Mutex: удалён трейт MutexTestTrait, а все тесты из него перенесены в сам класс с тестами (PR).
⚡️ #yiisoftMutex

В пакете Yii Mutex добавлен абстрактный класс Mutex (реализует MutexInterface), предоставляющий базовый функционал для создания драйверов (PR).
⚡️ #yiisoftMutex

В абстрактном классе Mutex (пакет Yii Mutex) финализирован деструктор (PR).
🎁 #yiisoftMutex #yiisoftMutexFile #yiisoftMutexPdoMysql #yiisoftMutexPdoPgsql #yiisoftMutexPdoOracle #yiisoftMutexRedis #Релиз #ПервыйРелиз

Первый релиз Yii Mutex 1.0.0 (новость на yiiframework.com).

Этот пакет, используя механизм блокировки, обеспечивает взаимное исключение исполнения критических участков кода в «состоянии гонки». Доступны несколько вариантов использования.

1) Запуск callback-функции в синхронизированном режиме (в один момент времени выполняется только один экземпляр callback-функции) с помощью класса Synchronizer:

/** @var \Yiisoft\Mutex\Synchronizer $synchronizer */
$newCount = $synchronizer->execute('critical_logic', function () {
return $counter->increase();
}, 10);

2) Установка и снятие блокировки вручную с помощью класса SimpleMutex:

/** @var \Yiisoft\Mutex\SimpleMutex $simpleMutex */
if (!$simpleMutex->acquire('critical_logic', 1000)) {
throw new \RuntimeException('Unable to acquire "critical_logic" mutex.');
}
$newCount = $counter->increase();
$simpleMutex->release();

3) Ручное создание мьютекса и управление им:

/** @var \Yiisoft\Mutex\MutexFactoryInterface $mutexFactory */
$mutex = $mutexFactory->createAndAcquire('critical', 10);
$newCount = $counter->increase();
$mutex->release();

или вариант с полным контролем:

/** @var \Yiisoft\Mutex\MutexFactoryInterface $mutexFactory */
$mutex = $mutexFactory->create('critical');
if (!$mutex->acquire(10)) {
throw new \RuntimeException('Unable to acquire mutex "critical".');
}
$newCount = $counter->increase();
$mutex->release();

Вместе с основным пакетом зарелизены мьютекс-драйвера:

- File Driver 1.0.0
- MySQL PDO Driver 1.0.0
- Postgres PDO Driver 1.0.0
- Oracle PDO Driver 1.0.0
- Redis Driver 1.0.0
⚡️ #yiisoftMutex

В пакете Yii Mutex исправлены описания опциональных зависимостей в composer.json (PR).