11
11
12
12
namespace Symfony \Component \Semaphore \Store ;
13
13
14
+ use Predis \Response \ServerException ;
14
15
use Symfony \Component \Cache \Traits \RedisClusterProxy ;
15
16
use Symfony \Component \Cache \Traits \RedisProxy ;
16
17
use Symfony \Component \Semaphore \Exception \InvalidArgumentException ;
18
+ use Symfony \Component \Semaphore \Exception \RuntimeException ;
17
19
use Symfony \Component \Semaphore \Exception \SemaphoreAcquiringException ;
18
20
use Symfony \Component \Semaphore \Exception \SemaphoreExpiredException ;
19
21
use Symfony \Component \Semaphore \Key ;
@@ -60,8 +62,12 @@ public function save(Key $key, float $ttlInSecond)
60
62
$ key ->getWeight (),
61
63
];
62
64
63
- if (!$ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), $ args )) {
64
- throw new SemaphoreAcquiringException ($ key , 'the script return false ' );
65
+ try {
66
+ if (!$ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), $ args )) {
67
+ throw new SemaphoreAcquiringException ($ key , 'the script return false ' );
68
+ }
69
+ } catch (\Exception $ e ) {
70
+ throw new SemaphoreAcquiringException ($ key , 'the script failed ' , $ e );
65
71
}
66
72
}
67
73
@@ -76,7 +82,11 @@ public function putOffExpiration(Key $key, float $ttlInSecond)
76
82
77
83
$ script = file_get_contents (__DIR__ .'/Resources/redis_put_off_expiration.lua ' );
78
84
79
- $ ret = $ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), [time () + $ ttlInSecond , $ this ->getUniqueToken ($ key )]);
85
+ try {
86
+ $ ret = $ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), [time () + $ ttlInSecond , $ this ->getUniqueToken ($ key )]);
87
+ } catch (\Exception $ e ) {
88
+ throw new SemaphoreAcquiringException ($ key , 'the script failed ' , $ e );
89
+ }
80
90
81
91
// Occurs when redis has been reset
82
92
if (false === $ ret ) {
@@ -96,7 +106,11 @@ public function delete(Key $key)
96
106
{
97
107
$ script = file_get_contents (__DIR__ .'/Resources/redis_delete.lua ' );
98
108
99
- $ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), [$ this ->getUniqueToken ($ key )]);
109
+ try {
110
+ $ this ->evaluate ($ script , sprintf ('{%s} ' , $ key ), [$ this ->getUniqueToken ($ key )]);
111
+ } catch (\Exception $ e ) {
112
+ throw new SemaphoreAcquiringException ($ key , 'the script failed ' , $ e );
113
+ }
100
114
}
101
115
102
116
/**
@@ -114,21 +128,49 @@ public function exists(Key $key): bool
114
128
*/
115
129
private function evaluate (string $ script , string $ resource , array $ args )
116
130
{
117
- if (
118
- $ this ->redis instanceof \Redis ||
119
- $ this ->redis instanceof \RedisCluster ||
120
- $ this ->redis instanceof RedisProxy ||
121
- $ this ->redis instanceof RedisClusterProxy
122
- ) {
123
- return $ this ->redis ->eval ($ script , array_merge ([$ resource ], $ args ), 1 );
124
- }
131
+ $ sha = sha1 ($ script );
125
132
126
133
if ($ this ->redis instanceof \RedisArray) {
127
- return $ this ->redis ->_instance ($ this ->redis ->_target ($ resource ))->eval ($ script , array_merge ([$ resource ], $ args ), 1 );
134
+ $ client = $ this ->redis ->_instance ($ this ->redis ->_target ($ resource ));
135
+ } else {
136
+ $ client = $ this ->redis ;
137
+ }
138
+
139
+ if (
140
+ $ client instanceof \Redis ||
141
+ $ client instanceof \RedisCluster ||
142
+ $ client instanceof RedisProxy ||
143
+ $ client instanceof RedisClusterProxy
144
+ ) {
145
+ $ client ->clearLastError ();
146
+ $ result = $ client ->evalSha ($ sha , array_merge ([$ resource ], $ args ), 1 );
147
+ $ err = $ client ->getLastError ();
148
+ if (false === $ result && 0 === strpos ($ err , 'NOSCRIPT ' )) {
149
+ $ client ->clearLastError ();
150
+ $ result = $ client ->eval ($ script , array_merge ([$ resource ], $ args ), 1 );
151
+ $ err = $ client ->getLastError ();
152
+ }
153
+
154
+ if (null !== $ err ) {
155
+ throw new RuntimeException ($ err );
156
+ }
157
+
158
+ return $ result ;
128
159
}
129
160
130
- if ($ this ->redis instanceof \Predis \ClientInterface) {
131
- return $ this ->redis ->eval (...array_merge ([$ script , 1 , $ resource ], $ args ));
161
+ if ($ client instanceof \Predis \ClientInterface) {
162
+ try {
163
+ return $ client ->evalSha ($ sha , 1 , $ resource , ...$ args );
164
+ } catch (ServerException $ e ) {
165
+ if (0 !== strpos ($ e ->getMessage (), 'NOSCRIPT ' )) {
166
+ throw new RuntimeException ($ e ->getMessage (), $ e ->getCode (), $ e );
167
+ }
168
+ }
169
+ try {
170
+ return $ client ->eval ($ script , 1 , $ resource , ...$ args );
171
+ } catch (ServerException $ e ) {
172
+ throw new RuntimeException ($ e ->getMessage (), $ e ->getCode (), $ e );
173
+ }
132
174
}
133
175
134
176
throw new InvalidArgumentException (sprintf ('"%s()" expects being initialized with a Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given. ' , __METHOD__ , \is_object ($ this ->redis ) ? \get_class ($ this ->redis ) : \gettype ($ this ->redis )));
0 commit comments