@@ -29,6 +29,9 @@ class MysqlStore implements PersistingStoreInterface
29
29
30
30
private array $ options ;
31
31
32
+ /** @var bool[] */
33
+ private static array $ locksAcquired = [];
34
+
32
35
public function __construct (\PDO |string $ connOrDsn , array $ options = [])
33
36
{
34
37
if ($ connOrDsn instanceof \PDO ) {
@@ -46,22 +49,20 @@ public function __construct(\PDO|string $connOrDsn, array $options = [])
46
49
47
50
public function save (Key $ key ): void
48
51
{
49
- if ($ key ->hasState (__CLASS__ )) {
52
+ $ id = $ this ->getLockId ($ key );
53
+
54
+ if (self ::$ locksAcquired [$ id ] ?? false ) {
50
55
return ;
51
56
}
52
57
53
- // mysql limits lock name length to 64 chars
54
- $ name = (string ) $ key ;
55
- $ name = \strlen ($ name ) > 64 ? hash ('xxh128 ' , $ name ) : $ name ;
56
-
57
58
$ stmt = $ this ->conn ->prepare ('SELECT IF(IS_USED_LOCK(:name) = CONNECTION_ID(), -1, GET_LOCK(:name, 0)) ' );
58
- $ stmt ->bindValue (':name ' , $ name , \PDO ::PARAM_STR );
59
+ $ stmt ->bindValue (':name ' , self :: getLockName ( $ key ) , \PDO ::PARAM_STR );
59
60
$ stmt ->execute ();
60
61
$ result = $ stmt ->fetchColumn ();
61
62
62
63
// lock acquired
63
64
if (1 === $ result ) {
64
- $ key -> setState ( __CLASS__ , $ name ) ;
65
+ self :: $ locksAcquired [ $ this -> getLockId ( $ key )] = true ;
65
66
66
67
return ;
67
68
}
@@ -84,28 +85,16 @@ public function putOffExpiration(Key $key, float $ttl): void
84
85
85
86
public function delete (Key $ key ): void
86
87
{
87
- if (!$ key ->hasState (__CLASS__ )) {
88
- return ;
89
- }
90
-
91
88
$ stmt = $ this ->conn ->prepare ('DO RELEASE_LOCK(:name) ' );
92
- $ stmt ->bindValue (':name ' , $ key-> getState ( __CLASS__ ), \PDO ::PARAM_STR );
89
+ $ stmt ->bindValue (':name ' , self :: getLockName ( $ key ), \PDO ::PARAM_STR );
93
90
$ stmt ->execute ();
94
91
95
- $ key -> removeState ( __CLASS__ );
92
+ unset( self :: $ locksAcquired [ $ this -> getLockId ( $ key )] );
96
93
}
97
94
98
95
public function exists (Key $ key ): bool
99
96
{
100
- if (!$ key ->hasState (__CLASS__ )) {
101
- return false ;
102
- }
103
-
104
- $ stmt = $ this ->conn ->prepare ('SELECT IF(IS_USED_LOCK(:name) = CONNECTION_ID(), 1, 0) ' );
105
- $ stmt ->bindValue (':name ' , $ key ->getState (__CLASS__ ), \PDO ::PARAM_STR );
106
- $ stmt ->execute ();
107
-
108
- return 1 === $ stmt ->fetchColumn ();
97
+ return self ::$ locksAcquired [$ this ->getLockId ($ key )] ?? false ;
109
98
}
110
99
111
100
private function getConnection (): \PDO
@@ -130,4 +119,17 @@ private function assertMysqlDriver(): void
130
119
throw new InvalidArgumentException (sprintf ('The adapter "%s" does not support the "%s" driver. ' , __CLASS__ , $ driver ));
131
120
}
132
121
}
122
+
123
+ private function getLockId (Key $ key ): string
124
+ {
125
+ return spl_object_id ($ this ->getConnection ()).'_ ' .spl_object_id ($ key );
126
+ }
127
+
128
+ private static function getLockName (Key $ key ): string
129
+ {
130
+ // mysql limits lock name length to 64 chars
131
+ $ name = (string ) $ key ;
132
+
133
+ return \strlen ($ name ) > 64 ? hash ('xxh128 ' , $ name ) : $ name ;
134
+ }
133
135
}
0 commit comments