lock = $factory->createLock(self::key($tasktype, $taskname, $taskid), self::TTL); $this->connection = $connection; } public static function fromPdo(PDO $connection, string $tasktype, string $taskname, int $taskid) : self { $store = self::withExceptionMode( $connection, static fn () : PdoStore => new PdoStore($connection, ['db_table' => self::TABLE], 0.01, self::TTL) ); return new self(new LockFactory($store), $tasktype, $taskname, $taskid, $connection); } public static function key(string $tasktype, string $taskname, int $taskid) : string { return 'cacti.process.' . hash('sha256', serialize([$tasktype, $taskname, $taskid])); } public function acquire() : bool { return $this->runWithRequiredMode(fn () : bool => $this->lock->acquire()); } public function release() : void { $this->runWithRequiredMode(function () : void { $this->lock->release(); }); } private function runWithRequiredMode(callable $operation) : mixed { if ($this->connection === null) { return $operation(); } return self::withExceptionMode($this->connection, $operation); } private static function withExceptionMode(PDO $connection, callable $operation) : mixed { $original = $connection->getAttribute(PDO::ATTR_ERRMODE); if ($original !== PDO::ERRMODE_EXCEPTION) { $connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } try { return $operation(); } finally { if ($original !== PDO::ERRMODE_EXCEPTION) { $connection->setAttribute(PDO::ATTR_ERRMODE, $original); } } } }