20
20
final class PostgresAdvisoryLocker
21
21
{
22
22
/**
23
- * Acquire an advisory lock with configurable scope, mode and behavior .
23
+ * Acquire a transaction-level advisory lock with a configurable acquisition type and mode .
24
24
*/
25
- public function acquireLock (
25
+ public function acquireTransactionLevelLock (
26
26
PDO $ dbConnection ,
27
27
PostgresLockId $ postgresLockId ,
28
- PostgresAdvisoryLockScopeEnum $ scope = PostgresAdvisoryLockScopeEnum::Transaction,
29
28
PostgresAdvisoryLockTypeEnum $ type = PostgresAdvisoryLockTypeEnum::NonBlocking,
30
29
PostgresLockModeEnum $ mode = PostgresLockModeEnum::Exclusive,
31
30
): bool {
32
- if ($ scope === PostgresAdvisoryLockScopeEnum::Transaction && $ dbConnection ->inTransaction () === false ) {
31
+ return $ this ->acquireLock (
32
+ $ dbConnection ,
33
+ $ postgresLockId ,
34
+ PostgresAdvisoryLockLevelEnum::Transaction,
35
+ $ type ,
36
+ $ mode ,
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Acquire a session-level advisory lock with a configurable acquisition type and mode.
42
+ *
43
+ * TODO: Write that transaction-level is recommended.
44
+ */
45
+ public function acquireSessionLevelLock (
46
+ PDO $ dbConnection ,
47
+ PostgresLockId $ postgresLockId ,
48
+ PostgresAdvisoryLockTypeEnum $ type = PostgresAdvisoryLockTypeEnum::NonBlocking,
49
+ PostgresLockModeEnum $ mode = PostgresLockModeEnum::Exclusive,
50
+ ): bool {
51
+ return $ this ->acquireLock (
52
+ $ dbConnection ,
53
+ $ postgresLockId ,
54
+ PostgresAdvisoryLockLevelEnum::Session,
55
+ $ type ,
56
+ $ mode ,
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Release session level advisory lock.
62
+ */
63
+ public function releaseSessionLevelLock (
64
+ PDO $ dbConnection ,
65
+ PostgresLockId $ postgresLockId ,
66
+ PostgresAdvisoryLockLevelEnum $ level = PostgresAdvisoryLockLevelEnum::Session,
67
+ PostgresLockModeEnum $ mode = PostgresLockModeEnum::Exclusive,
68
+ ): bool {
69
+ if ($ level === PostgresAdvisoryLockLevelEnum::Transaction) {
70
+ throw new \InvalidArgumentException ('Transaction-level advisory lock cannot be released ' );
71
+ }
72
+
73
+ $ sql = match ($ mode ) {
74
+ PostgresLockModeEnum::Exclusive => 'SELECT PG_ADVISORY_UNLOCK(:class_id, :object_id); ' ,
75
+ PostgresLockModeEnum::Share => 'SELECT PG_ADVISORY_UNLOCK_SHARED(:class_id, :object_id); ' ,
76
+ };
77
+ $ sql .= " -- $ postgresLockId ->humanReadableValue " ;
78
+
79
+ $ statement = $ dbConnection ->prepare ($ sql );
80
+ $ statement ->execute (
81
+ [
82
+ 'class_id ' => $ postgresLockId ->classId ,
83
+ 'object_id ' => $ postgresLockId ->objectId ,
84
+ ],
85
+ );
86
+
87
+ return $ statement ->fetchColumn (0 );
88
+ }
89
+
90
+ /**
91
+ * Release all session level advisory locks held by the current session.
92
+ */
93
+ public function releaseAllSessionLevelLocks (
94
+ PDO $ dbConnection ,
95
+ PostgresAdvisoryLockLevelEnum $ level = PostgresAdvisoryLockLevelEnum::Session,
96
+ ): void {
97
+ if ($ level === PostgresAdvisoryLockLevelEnum::Transaction) {
98
+ throw new \InvalidArgumentException ('Transaction-level advisory lock cannot be released ' );
99
+ }
100
+
101
+ $ statement = $ dbConnection ->prepare (
102
+ <<<'SQL'
103
+ SELECT PG_ADVISORY_UNLOCK_ALL();
104
+ SQL,
105
+ );
106
+ $ statement ->execute ();
107
+ }
108
+
109
+ private function acquireLock (
110
+ PDO $ dbConnection ,
111
+ PostgresLockId $ postgresLockId ,
112
+ PostgresAdvisoryLockLevelEnum $ level ,
113
+ PostgresAdvisoryLockTypeEnum $ type = PostgresAdvisoryLockTypeEnum::NonBlocking,
114
+ PostgresLockModeEnum $ mode = PostgresLockModeEnum::Exclusive,
115
+ ): bool {
116
+ if ($ level === PostgresAdvisoryLockLevelEnum::Transaction && $ dbConnection ->inTransaction () === false ) {
33
117
throw new LogicException (
34
118
"Transaction-level advisory lock ` $ postgresLockId ->humanReadableValue ` cannot be acquired outside of transaction " ,
35
119
);
36
120
}
37
121
38
- $ sql = match ([$ scope , $ type , $ mode ]) {
122
+ $ sql = match ([$ level , $ type , $ mode ]) {
39
123
[
40
- PostgresAdvisoryLockScopeEnum ::Transaction,
124
+ PostgresAdvisoryLockLevelEnum ::Transaction,
41
125
PostgresAdvisoryLockTypeEnum::NonBlocking,
42
126
PostgresLockModeEnum::Exclusive,
43
127
] => 'SELECT PG_TRY_ADVISORY_XACT_LOCK(:class_id, :object_id); ' ,
44
128
[
45
- PostgresAdvisoryLockScopeEnum ::Transaction,
129
+ PostgresAdvisoryLockLevelEnum ::Transaction,
46
130
PostgresAdvisoryLockTypeEnum::Blocking,
47
131
PostgresLockModeEnum::Exclusive,
48
132
] => 'SELECT PG_ADVISORY_XACT_LOCK(:class_id, :object_id); ' ,
49
133
[
50
- PostgresAdvisoryLockScopeEnum ::Transaction,
134
+ PostgresAdvisoryLockLevelEnum ::Transaction,
51
135
PostgresAdvisoryLockTypeEnum::NonBlocking,
52
136
PostgresLockModeEnum::Share,
53
137
] => 'SELECT PG_TRY_ADVISORY_XACT_LOCK_SHARED(:class_id, :object_id); ' ,
54
138
[
55
- PostgresAdvisoryLockScopeEnum ::Transaction,
139
+ PostgresAdvisoryLockLevelEnum ::Transaction,
56
140
PostgresAdvisoryLockTypeEnum::Blocking,
57
141
PostgresLockModeEnum::Share,
58
142
] => 'SELECT PG_ADVISORY_XACT_LOCK_SHARED(:class_id, :object_id); ' ,
59
143
[
60
- PostgresAdvisoryLockScopeEnum ::Session,
144
+ PostgresAdvisoryLockLevelEnum ::Session,
61
145
PostgresAdvisoryLockTypeEnum::NonBlocking,
62
146
PostgresLockModeEnum::Exclusive,
63
147
] => 'SELECT PG_TRY_ADVISORY_LOCK(:class_id, :object_id); ' ,
64
148
[
65
- PostgresAdvisoryLockScopeEnum ::Session,
149
+ PostgresAdvisoryLockLevelEnum ::Session,
66
150
PostgresAdvisoryLockTypeEnum::Blocking,
67
151
PostgresLockModeEnum::Exclusive,
68
152
] => 'SELECT PG_ADVISORY_LOCK(:class_id, :object_id); ' ,
69
153
[
70
- PostgresAdvisoryLockScopeEnum ::Session,
154
+ PostgresAdvisoryLockLevelEnum ::Session,
71
155
PostgresAdvisoryLockTypeEnum::NonBlocking,
72
156
PostgresLockModeEnum::Share,
73
157
] => 'SELECT PG_TRY_ADVISORY_LOCK_SHARED(:class_id, :object_id); ' ,
74
158
[
75
- PostgresAdvisoryLockScopeEnum ::Session,
159
+ PostgresAdvisoryLockLevelEnum ::Session,
76
160
PostgresAdvisoryLockTypeEnum::Blocking,
77
161
PostgresLockModeEnum::Share,
78
162
] => 'SELECT PG_ADVISORY_LOCK_SHARED(:class_id, :object_id); ' ,
@@ -89,53 +173,4 @@ public function acquireLock(
89
173
90
174
return $ statement ->fetchColumn (0 );
91
175
}
92
-
93
- /**
94
- * Release session level advisory lock.
95
- */
96
- public function releaseLock (
97
- PDO $ dbConnection ,
98
- PostgresLockId $ postgresLockId ,
99
- PostgresAdvisoryLockScopeEnum $ scope = PostgresAdvisoryLockScopeEnum::Session,
100
- PostgresLockModeEnum $ mode = PostgresLockModeEnum::Exclusive,
101
- ): bool {
102
- if ($ scope === PostgresAdvisoryLockScopeEnum::Transaction) {
103
- throw new \InvalidArgumentException ('Transaction-level advisory lock cannot be released ' );
104
- }
105
-
106
- $ sql = match ($ mode ) {
107
- PostgresLockModeEnum::Exclusive => 'SELECT PG_ADVISORY_UNLOCK(:class_id, :object_id); ' ,
108
- PostgresLockModeEnum::Share => 'SELECT PG_ADVISORY_UNLOCK_SHARED(:class_id, :object_id); ' ,
109
- };
110
- $ sql .= " -- $ postgresLockId ->humanReadableValue " ;
111
-
112
- $ statement = $ dbConnection ->prepare ($ sql );
113
- $ statement ->execute (
114
- [
115
- 'class_id ' => $ postgresLockId ->classId ,
116
- 'object_id ' => $ postgresLockId ->objectId ,
117
- ],
118
- );
119
-
120
- return $ statement ->fetchColumn (0 );
121
- }
122
-
123
- /**
124
- * Release all session level advisory locks held by the current session.
125
- */
126
- public function releaseAllLocks (
127
- PDO $ dbConnection ,
128
- PostgresAdvisoryLockScopeEnum $ scope = PostgresAdvisoryLockScopeEnum::Session,
129
- ): void {
130
- if ($ scope === PostgresAdvisoryLockScopeEnum::Transaction) {
131
- throw new \InvalidArgumentException ('Transaction-level advisory lock cannot be released ' );
132
- }
133
-
134
- $ statement = $ dbConnection ->prepare (
135
- <<<'SQL'
136
- SELECT PG_ADVISORY_UNLOCK_ALL();
137
- SQL,
138
- );
139
- $ statement ->execute ();
140
- }
141
176
}
0 commit comments