@@ -34,7 +34,7 @@ public function get(string $key, callable $callback, float $beta = null)
34
34
return $ this ->doGet ($ this , $ key , $ callback , $ beta ?? 1.0 );
35
35
}
36
36
37
- private function doGet (CacheItemPoolInterface $ pool , string $ key , callable $ callback , float $ beta )
37
+ private function doGet (CacheItemPoolInterface $ pool , string $ key , callable $ callback , float $ beta, string $ lockId = null )
38
38
{
39
39
$ t = 0 ;
40
40
$ item = $ pool ->getItem ($ key );
@@ -64,6 +64,7 @@ private function doGet(CacheItemPoolInterface $pool, string $key, callable $call
64
64
}
65
65
66
66
static $ save = null ;
67
+ static $ useApcu = null ;
67
68
68
69
if (null === $ save ) {
69
70
$ save = \Closure::bind (
@@ -81,6 +82,26 @@ function (CacheItemPoolInterface $pool, CacheItemInterface $item, $value, float
81
82
);
82
83
}
83
84
84
- return $ save ($ pool , $ item , $ callback ($ item ), $ t );
85
+ if (null === $ lockId || !$ useApcu = $ useApcu ?? \function_exists ('apcu_entry ' ) && ini_get ('apc.enabled ' ) && ('cli ' !== \PHP_SAPI || ini_get ('apc.enable_cli ' ))) {
86
+ return $ save ($ pool , $ item , $ callback ($ item ), $ t );
87
+ }
88
+
89
+ $ t = $ t ?: microtime (true );
90
+ $ lockId = ': ' .$ lockId ;
91
+ $ isHit = true ;
92
+ $ value = apcu_entry ($ lockId , function () use ($ callback , $ item , &$ isHit ) {
93
+ $ isHit = false ;
94
+
95
+ return $ callback ($ item );
96
+ }, 2 );
97
+
98
+ if (!$ isHit ) {
99
+ $ save ($ pool , $ item , $ value , $ t );
100
+ // give some time to concurrent processes to get the value from APCu
101
+ usleep (min (300000 , (microtime (true ) - $ t ) * 150000 ));
102
+ apcu_delete ($ lockId );
103
+ }
104
+
105
+ return $ value ;
85
106
}
86
107
}
0 commit comments