24
24
*
25
25
* Lock metadata are stored in a table. You can use createTable() to initialize
26
26
* a correctly defined table.
27
-
27
+ *
28
28
* CAUTION: This store relies on all client and server nodes to have
29
29
* synchronized clocks for lock expiry to occur at the correct time.
30
30
* To ensure locks don't expire prematurely; the TTLs should be set with enough
@@ -115,7 +115,7 @@ public function save(Key $key)
115
115
try {
116
116
$ stmt = $ conn ->prepare ($ sql );
117
117
} catch (\PDOException $ e ) {
118
- if (!$ conn ->inTransaction () || \in_array ($ this ->driver , ['pgsql ' , 'sqlite ' , 'sqlsrv ' ], true )) {
118
+ if ($ this -> isTableMissing ( $ e ) && ( !$ conn ->inTransaction () || \in_array ($ this ->driver , ['pgsql ' , 'sqlite ' , 'sqlsrv ' ], true ) )) {
119
119
$ this ->createTable ();
120
120
}
121
121
$ stmt = $ conn ->prepare ($ sql );
@@ -127,8 +127,19 @@ public function save(Key $key)
127
127
try {
128
128
$ stmt ->execute ();
129
129
} catch (\PDOException $ e ) {
130
- // the lock is already acquired. It could be us. Let's try to put off.
131
- $ this ->putOffExpiration ($ key , $ this ->initialTtl );
130
+ if ($ this ->isTableMissing ($ e ) && (!$ conn ->inTransaction () || \in_array ($ this ->driver , ['pgsql ' , 'sqlite ' , 'sqlsrv ' ], true ))) {
131
+ $ this ->createTable ();
132
+
133
+ try {
134
+ $ stmt ->execute ();
135
+ } catch (\PDOException $ e ) {
136
+ // the lock is already acquired. It could be us. Let's try to put off.
137
+ $ this ->putOffExpiration ($ key , $ this ->initialTtl );
138
+ }
139
+ } else {
140
+ // the lock is already acquired. It could be us. Let's try to put off.
141
+ $ this ->putOffExpiration ($ key , $ this ->initialTtl );
142
+ }
132
143
}
133
144
134
145
$ this ->randomlyPrune ();
@@ -316,4 +327,21 @@ private function getCurrentTimestampStatement(): string
316
327
return (string ) time ();
317
328
}
318
329
}
330
+
331
+ private function isTableMissing (\PDOException $ exception ): bool
332
+ {
333
+ $ driver = $ this ->getDriver ();
334
+ $ code = $ exception ->getCode ();
335
+
336
+ switch (true ) {
337
+ case 'pgsql ' === $ driver && '42P01 ' === $ code :
338
+ case 'sqlite ' === $ driver && str_contains ($ exception ->getMessage (), 'no such table: ' ):
339
+ case 'oci ' === $ driver && 942 === $ code :
340
+ case 'sqlsrv ' === $ driver && 208 === $ code :
341
+ case 'mysql ' === $ driver && 1146 === $ code :
342
+ return true ;
343
+ default :
344
+ return false ;
345
+ }
346
+ }
319
347
}
0 commit comments