Skip to content

Commit 9f38225

Browse files
committed
added locking
1 parent 2cdf655 commit 9f38225

File tree

1 file changed

+87
-11
lines changed

1 file changed

+87
-11
lines changed

Diff for: src/models/Storage.php

+87-11
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
namespace hiqdev\assetpackagist\models;
44

5+
use Exception;
56
use Yii;
67
use yii\helpers\Json;
78

89
class Storage
910
{
1011
protected static $_instance;
12+
protected static $_lockHandle;
13+
protected static $_lockCount = 0;
1114

1215
protected function __construct()
1316
{
@@ -24,7 +27,70 @@ static public function getInstance()
2427

2528
public function getNextID()
2629
{
27-
return rand(1000000, 2000000);
30+
$this->getLock();
31+
$nextID = $this->readLastID() + 1;
32+
$this->writeLastID($nextID);
33+
$this->releaseLock();
34+
35+
return $nextID;
36+
}
37+
38+
protected function readLastId()
39+
{
40+
$path = $this->getLastIDPath();
41+
42+
return file_exists($path) ? (int)file_get_contents($path) : 1000000;
43+
}
44+
45+
protected function writeLastId($value)
46+
{
47+
file_put_contents($this->getLastIDPath(), $value);
48+
}
49+
50+
protected function getLastIDPath()
51+
{
52+
return Yii::getAlias('@web/lastid');
53+
}
54+
55+
protected function getLockHandle()
56+
{
57+
if (static::$_lockHandle === null) {
58+
$path = Yii::getAlias('@web/lock');
59+
if (!file_exists($path)) {
60+
file_put_contents($path, 'lock');
61+
}
62+
static::$_lockHandle = fopen($path, 'r+');
63+
}
64+
65+
return static::$_lockHandle;
66+
}
67+
68+
public function hasLock()
69+
{
70+
return (bool)static::$_lockCount;
71+
}
72+
73+
protected function getLock()
74+
{
75+
if (!$this->hasLock()) {
76+
if (!flock($this->getLockHandle(), LOCK_EX)) {
77+
throw new Exception('failed get lock');
78+
}
79+
}
80+
++$this->_lockCount;
81+
}
82+
83+
protected function releaseLock()
84+
{
85+
if ($this->_lockCount<1) {
86+
throw new Exception('no lock to release');
87+
}
88+
if ($this->_lockCount === 1) {
89+
if (!flock($this->getLockHandle(), LOCK_UN)) {
90+
throw new Exception('failed release lock');
91+
}
92+
}
93+
--$this->_lockCount;
2894
}
2995

3096
public function writePackage(AssetPackage $package)
@@ -39,10 +105,14 @@ public function writePackage(AssetPackage $package)
39105
$hash = hash('sha256', $json);
40106
$path = static::buildPath($name, $hash);
41107
if (!file_exists($path)) {
42-
static::mkdir(dirname($path));
43-
file_put_contents($path, $json);
44-
file_put_contents(static::buildPath($name), $json);
45-
$this->writeProviderLatest($name, $hash);
108+
$this->getLock();
109+
{
110+
static::mkdir(dirname($path));
111+
file_put_contents($path, $json);
112+
file_put_contents(static::buildPath($name), $json);
113+
$this->writeProviderLatest($name, $hash);
114+
}
115+
$this->releaseLock();
46116
}
47117

48118
return $hash;
@@ -85,10 +155,13 @@ protected function writeProviderLatest($name, $hash)
85155
$hash = hash('sha256', $json);
86156
$path = Yii::getAlias("@web/p/provider-latest$$hash.json");
87157
if (!file_exists($path)) {
88-
file_put_contents($path, $json);
89-
/// TODO lock
90-
file_put_contents($latest_path, Json::encode($data));
91-
$this->writePackagesJson($hash);
158+
$this->getLock();
159+
{
160+
file_put_contents($path, $json);
161+
file_put_contents($latest_path, Json::encode($data));
162+
$this->writePackagesJson($hash);
163+
}
164+
$this->releaseLock();
92165
}
93166

94167
return $hash;
@@ -105,8 +178,11 @@ protected function writePackagesJson($hash)
105178
],
106179
],
107180
];
108-
/// TODO lock
109-
file_put_contents(Yii::getAlias('@web/packages.json'), Json::encode($data));
181+
$this->getLock();
182+
{
183+
file_put_contents(Yii::getAlias('@web/packages.json'), Json::encode($data));
184+
}
185+
$this->releaseLock();
110186
}
111187

112188
public static function mkdir($dir)

0 commit comments

Comments
 (0)