File tree 6 files changed +77
-18
lines changed
src/Symfony/Component/Lock
6 files changed +77
-18
lines changed Original file line number Diff line number Diff line change @@ -83,6 +83,11 @@ public function acquire($blocking = false)
83
83
}
84
84
85
85
if ($ this ->key ->isExpired ()) {
86
+ try {
87
+ $ this ->release ();
88
+ } catch (\Exception $ e ) {
89
+ // swallow exception to not hide the original issue
90
+ }
86
91
throw new LockExpiredException (sprintf ('Failed to store the "%s" lock. ' , $ this ->key ));
87
92
}
88
93
@@ -117,6 +122,11 @@ public function refresh()
117
122
$ this ->dirty = true ;
118
123
119
124
if ($ this ->key ->isExpired ()) {
125
+ try {
126
+ $ this ->release ();
127
+ } catch (\Exception $ e ) {
128
+ // swallow exception to not hide the original issue
129
+ }
120
130
throw new LockExpiredException (sprintf ('Failed to put off the expiration of the "%s" lock within the specified time. ' , $ this ->key ));
121
131
}
122
132
Original file line number Diff line number Diff line change 16
16
use Psr \Log \NullLogger ;
17
17
use Symfony \Component \Lock \Exception \InvalidArgumentException ;
18
18
use Symfony \Component \Lock \Exception \LockConflictedException ;
19
- use Symfony \Component \Lock \Exception \LockExpiredException ;
20
19
use Symfony \Component \Lock \Exception \NotSupportedException ;
21
20
use Symfony \Component \Lock \Key ;
22
21
use Symfony \Component \Lock \StoreInterface ;
30
29
class CombinedStore implements StoreInterface, LoggerAwareInterface
31
30
{
32
31
use LoggerAwareTrait;
32
+ use ExpiringStoreTrait;
33
33
34
34
/** @var StoreInterface[] */
35
35
private $ stores ;
@@ -78,6 +78,8 @@ public function save(Key $key)
78
78
}
79
79
}
80
80
81
+ $ this ->checkNotExpired ($ key );
82
+
81
83
if ($ this ->strategy ->isMet ($ successCount , $ storesCount )) {
82
84
return ;
83
85
}
@@ -125,9 +127,7 @@ public function putOffExpiration(Key $key, $ttl)
125
127
}
126
128
}
127
129
128
- if ($ key ->isExpired ()) {
129
- throw new LockExpiredException (sprintf ('Failed to put off the expiration of the "%s" lock within the specified time. ' , $ key ));
130
- }
130
+ $ this ->checkNotExpired ($ key );
131
131
132
132
if ($ this ->strategy ->isMet ($ successCount , $ storesCount )) {
133
133
return ;
Original file line number Diff line number Diff line change
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of the Symfony package.
5
+ *
6
+ * (c) Fabien Potencier <fabien@symfony.com>
7
+ *
8
+ * For the full copyright and license information, please view the LICENSE
9
+ * file that was distributed with this source code.
10
+ */
11
+
12
+ namespace Symfony \Component \Lock \Store ;
13
+
14
+ use Symfony \Component \Lock \Exception \LockExpiredException ;
15
+ use Symfony \Component \Lock \Key ;
16
+
17
+ trait ExpiringStoreTrait
18
+ {
19
+ private function checkNotExpired (Key $ key )
20
+ {
21
+ if ($ key ->isExpired ()) {
22
+ try {
23
+ $ this ->delete ($ key );
24
+ } catch (\Exception $ e ) {
25
+ // swallow exception to not hide the original issue
26
+ }
27
+ throw new LockExpiredException (sprintf ('Failed to store the "%s" lock. ' , $ key ));
28
+ }
29
+ }
30
+ }
Original file line number Diff line number Diff line change 13
13
14
14
use Symfony \Component \Lock \Exception \InvalidArgumentException ;
15
15
use Symfony \Component \Lock \Exception \LockConflictedException ;
16
- use Symfony \Component \Lock \Exception \LockExpiredException ;
17
16
use Symfony \Component \Lock \Key ;
18
17
use Symfony \Component \Lock \StoreInterface ;
19
18
24
23
*/
25
24
class MemcachedStore implements StoreInterface
26
25
{
26
+ use ExpiringStoreTrait;
27
+
27
28
private $ memcached ;
28
29
private $ initialTtl ;
29
30
/** @var bool */
@@ -64,9 +65,7 @@ public function save(Key $key)
64
65
$ this ->putOffExpiration ($ key , $ this ->initialTtl );
65
66
}
66
67
67
- if ($ key ->isExpired ()) {
68
- throw new LockExpiredException (sprintf ('Failed to store the "%s" lock. ' , $ key ));
69
- }
68
+ $ this ->checkNotExpired ($ key );
70
69
}
71
70
72
71
public function waitAndSave (Key $ key )
@@ -110,9 +109,7 @@ public function putOffExpiration(Key $key, $ttl)
110
109
throw new LockConflictedException ();
111
110
}
112
111
113
- if ($ key ->isExpired ()) {
114
- throw new LockExpiredException (sprintf ('Failed to put off the expiration of the "%s" lock within the specified time. ' , $ key ));
115
- }
112
+ $ this ->checkNotExpired ($ key );
116
113
}
117
114
118
115
/**
Original file line number Diff line number Diff line change 14
14
use Symfony \Component \Cache \Traits \RedisProxy ;
15
15
use Symfony \Component \Lock \Exception \InvalidArgumentException ;
16
16
use Symfony \Component \Lock \Exception \LockConflictedException ;
17
- use Symfony \Component \Lock \Exception \LockExpiredException ;
18
17
use Symfony \Component \Lock \Key ;
19
18
use Symfony \Component \Lock \StoreInterface ;
20
19
25
24
*/
26
25
class RedisStore implements StoreInterface
27
26
{
27
+ use ExpiringStoreTrait;
28
+
28
29
private $ redis ;
29
30
private $ initialTtl ;
30
31
@@ -66,9 +67,7 @@ public function save(Key $key)
66
67
throw new LockConflictedException ();
67
68
}
68
69
69
- if ($ key ->isExpired ()) {
70
- throw new LockExpiredException (sprintf ('Failed to store the "%s" lock. ' , $ key ));
71
- }
70
+ $ this ->checkNotExpired ($ key );
72
71
}
73
72
74
73
public function waitAndSave (Key $ key )
@@ -94,9 +93,7 @@ public function putOffExpiration(Key $key, $ttl)
94
93
throw new LockConflictedException ();
95
94
}
96
95
97
- if ($ key ->isExpired ()) {
98
- throw new LockExpiredException (sprintf ('Failed to put off the expiration of the "%s" lock within the specified time. ' , $ key ));
99
- }
96
+ $ this ->checkNotExpired ($ key );
100
97
}
101
98
102
99
/**
Original file line number Diff line number Diff line change 11
11
12
12
namespace Symfony \Component \Lock \Tests \Store ;
13
13
14
+ use Symfony \Component \Lock \Exception \LockExpiredException ;
14
15
use Symfony \Component \Lock \Key ;
15
16
use Symfony \Component \Lock \StoreInterface ;
16
17
@@ -105,4 +106,28 @@ public function testSetExpiration()
105
106
$ this ->assertGreaterThanOrEqual (0 , $ key ->getRemainingLifetime ());
106
107
$ this ->assertLessThanOrEqual (1 , $ key ->getRemainingLifetime ());
107
108
}
109
+
110
+ public function testExpiredLockCleaned ()
111
+ {
112
+ $ resource = uniqid (__METHOD__ , true );
113
+
114
+ $ key1 = new Key ($ resource );
115
+ $ key2 = new Key ($ resource );
116
+
117
+ /** @var StoreInterface $store */
118
+ $ store = $ this ->getStore ();
119
+ $ key1 ->reduceLifetime (0 );
120
+
121
+ $ this ->assertTrue ($ key1 ->isExpired ());
122
+ try {
123
+ $ store ->save ($ key1 );
124
+ $ this ->fail ('The store shouldn \'t have save an expired key ' );
125
+ } catch (LockExpiredException $ e ) {
126
+ }
127
+
128
+ $ this ->assertFalse ($ store ->exists ($ key1 ));
129
+
130
+ $ store ->save ($ key2 );
131
+ $ this ->assertTrue ($ store ->exists ($ key2 ));
132
+ }
108
133
}
You can’t perform that action at this time.
0 commit comments