|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace Cog\DbLocker; |
| 6 | + |
| 7 | +/** |
| 8 | + * Minimal connection abstraction for PostgreSQL advisory lock operations. |
| 9 | + * |
| 10 | + * This interface defines only the operations required by PostgresAdvisoryLocker. |
| 11 | + * It is NOT a general-purpose database abstraction layer. |
| 12 | + * |
| 13 | + * Exception Handling Contract: |
| 14 | + * - Implementations MUST throw the original database exception unwrapped. |
| 15 | + * - For PDO: throw \PDOException with SQLSTATE in getCode() |
| 16 | + * - For ORMs: throw their native exceptions (Doctrine\DBAL\Exception, etc.) |
| 17 | + * - The locker will inspect exceptions for SQLSTATE '55P03' (lock_not_available) |
| 18 | + */ |
| 19 | +interface ConnectionAdapterInterface |
| 20 | +{ |
| 21 | + /** |
| 22 | + * Execute a parameterized query and return the first column of the first row. |
| 23 | + * |
| 24 | + * Used for lock acquisition functions that return boolean results: |
| 25 | + * - SELECT PG_TRY_ADVISORY_LOCK(:class_id, :object_id) |
| 26 | + * - SELECT PG_ADVISORY_UNLOCK(:class_id, :object_id) |
| 27 | + * - SHOW lock_timeout |
| 28 | + * |
| 29 | + * @param string $sql SQL query with named parameters (e.g., :class_id) |
| 30 | + * @param array<string, mixed> $params Named parameters (e.g., ['class_id' => 1, 'object_id' => 2]) |
| 31 | + * @return mixed The value of the first column (typically bool or string) |
| 32 | + * @throws \Throwable Database-specific exception on error |
| 33 | + */ |
| 34 | + public function fetchColumn(string $sql, array $params = []): mixed; |
| 35 | + |
| 36 | + /** |
| 37 | + * Execute a statement without returning results. |
| 38 | + * |
| 39 | + * Used for: |
| 40 | + * - Blocking lock acquisition: SELECT PG_ADVISORY_LOCK(:class_id, :object_id) |
| 41 | + * - Transaction control: SAVEPOINT, RELEASE SAVEPOINT, ROLLBACK TO SAVEPOINT |
| 42 | + * - Configuration: SET [LOCAL] lock_timeout = '...' |
| 43 | + * - Cleanup: SELECT PG_ADVISORY_UNLOCK_ALL() |
| 44 | + * |
| 45 | + * @param string $sql SQL statement with optional named parameters |
| 46 | + * @param array<string, mixed> $params Named parameters (e.g., ['class_id' => 1]) |
| 47 | + * @throws \Throwable Database-specific exception on error |
| 48 | + */ |
| 49 | + public function execute(string $sql, array $params = []): void; |
| 50 | + |
| 51 | + /** |
| 52 | + * Check whether a transaction is currently active on this connection. |
| 53 | + * |
| 54 | + * Used to validate that transaction-level locks are only acquired within a transaction. |
| 55 | + * |
| 56 | + * @return bool True if a transaction is active, false otherwise |
| 57 | + */ |
| 58 | + public function isTransactionActive(): bool; |
| 59 | + |
| 60 | + /** |
| 61 | + * Check if an exception indicates a PostgreSQL lock_not_available error (SQLSTATE 55P03). |
| 62 | + * |
| 63 | + * Different database adapters throw different exception types: |
| 64 | + * - PDO: \PDOException with SQLSTATE in getCode() |
| 65 | + * - Doctrine DBAL: Doctrine\DBAL\Exception with getSQLState() method |
| 66 | + * - Cycle ORM: wraps \PDOException in its own exception |
| 67 | + * |
| 68 | + * @param \Throwable $exception Exception to inspect |
| 69 | + * @return bool True if the exception indicates a lock timeout (SQLSTATE 55P03) |
| 70 | + */ |
| 71 | + public function isLockNotAvailable(\Throwable $exception): bool; |
| 72 | +} |
0 commit comments