Skip to content

Commit a34ae39

Browse files
committed
bugs fix
1 parent ff55230 commit a34ae39

File tree

8 files changed

+71
-39
lines changed

8 files changed

+71
-39
lines changed

src/Internal/Decorator/StorageServiceLockDecorator.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ public function missing(string $uuid): bool
3333

3434
public function get(string $uuid): string
3535
{
36-
return $this->stateService->get($uuid) ?? $this->storageService->get($uuid);
36+
if ($this->lockService->isBlocked($uuid)) {
37+
return $this->stateService->get($uuid) ?? $this->storageService->get($uuid);
38+
}
39+
40+
return $this->storageService->get($uuid);
3741
}
3842

3943
public function sync(string $uuid, float|int|string $value): bool

src/Internal/Service/LockService.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,27 @@ public function __construct(CacheFactory $cacheFactory)
3434
*/
3535
public function block(string $key, callable $callback): mixed
3636
{
37-
$lockKey = self::PREFIX . $key;
38-
39-
if (array_key_exists($lockKey, $this->lockedKeys)) {
37+
if ($this->isBlocked($key)) {
4038
return $callback();
4139
}
4240

43-
$this->lockedKeys[$lockKey] = true;
41+
$this->lockedKeys[$key] = true;
4442

4543
try {
4644
return $this->getLockProvider()
47-
->lock($lockKey)
45+
->lock(self::PREFIX . $key)
4846
->block($this->seconds, $callback)
4947
;
5048
} finally {
51-
unset($this->lockedKeys[$lockKey]);
49+
unset($this->lockedKeys[$key]);
5250
}
5351
}
5452

53+
public function isBlocked(string $key): bool
54+
{
55+
return $this->lockedKeys[$key] ?? false;
56+
}
57+
5558
/**
5659
* @throws LockProviderNotFoundException
5760
* @codeCoverageIgnore

src/Internal/Service/LockServiceInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ interface LockServiceInterface
1717
* @throws LockProviderNotFoundException
1818
*/
1919
public function block(string $key, callable $callback): mixed;
20+
21+
public function isBlocked(string $key): bool;
2022
}

src/Internal/Service/StateService.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ final class StateService implements StateServiceInterface
1313

1414
public function fork(string $uuid, string $value): void
1515
{
16-
$this->forks[$uuid] = $value;
16+
$this->forks[$uuid] ??= $value;
1717
}
1818

1919
public function get(string $uuid): ?string

src/Services/AtomicService.php

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
final class AtomicService implements AtomicServiceInterface
2020
{
2121
public function __construct(
22+
private BookkeeperServiceInterface $bookkeeperService,
2223
private DatabaseServiceInterface $databaseService,
2324
private StateServiceInterface $stateService,
2425
private LockServiceInterface $lockService,
@@ -36,23 +37,35 @@ public function __construct(
3637
*/
3738
public function blocks(array $objects, callable $callback): mixed
3839
{
39-
$callable = fn () => $this->databaseService->transaction($callback);
40+
$blockObjects = [];
4041
foreach ($objects as $object) {
4142
$wallet = $this->castService->getWallet($object);
42-
$callable = fn () => $this->lockService->block(
43-
$wallet->uuid,
44-
function () use ($wallet, $callable) {
45-
try {
46-
$this->stateService->fork($wallet->uuid, $wallet->balance);
47-
return $callable();
48-
} finally {
49-
$this->stateService->drop($wallet->uuid);
50-
}
51-
}
52-
);
43+
if (! $this->lockService->isBlocked($wallet->uuid)) {
44+
$blockObjects[] = $object;
45+
}
5346
}
5447

55-
return $callable();
48+
$callable = function () use ($blockObjects, $callback) {
49+
foreach ($blockObjects as $object) {
50+
$wallet = $this->castService->getWallet($object);
51+
$this->stateService->fork($wallet->uuid, $this->bookkeeperService->amount($wallet));
52+
}
53+
return $this->databaseService->transaction($callback);
54+
};
55+
56+
foreach ($blockObjects as $object) {
57+
$wallet = $this->castService->getWallet($object);
58+
$callable = fn () => $this->lockService->block($wallet->uuid, $callable);
59+
}
60+
61+
try {
62+
return $callable();
63+
} finally {
64+
foreach ($blockObjects as $object) {
65+
$wallet = $this->castService->getWallet($object);
66+
$this->stateService->drop($wallet->uuid);
67+
}
68+
}
5669
}
5770

5871
/**

src/Traits/CanConfirm.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,16 @@ trait CanConfirm
4040
*/
4141
public function confirm(Transaction $transaction): bool
4242
{
43-
if ($transaction->type === Transaction::TYPE_WITHDRAW) {
44-
app(ConsistencyServiceInterface::class)->checkPotential(
45-
app(CastServiceInterface::class)->getWallet($this),
46-
app(MathServiceInterface::class)->negative($transaction->amount)
47-
);
48-
}
43+
return app(AtomicServiceInterface::class)->block($this, function () use ($transaction): bool {
44+
if ($transaction->type === Transaction::TYPE_WITHDRAW) {
45+
app(ConsistencyServiceInterface::class)->checkPotential(
46+
app(CastServiceInterface::class)->getWallet($this),
47+
app(MathServiceInterface::class)->negative($transaction->amount)
48+
);
49+
}
4950

50-
return $this->forceConfirm($transaction);
51+
return $this->forceConfirm($transaction);
52+
});
5153
}
5254

5355
public function safeConfirm(Transaction $transaction): bool

src/Traits/CanExchange.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ trait CanExchange
4141
*/
4242
public function exchange(Wallet $to, int|string $amount, ExtraDtoInterface|array|null $meta = null): Transfer
4343
{
44-
$wallet = app(CastServiceInterface::class)->getWallet($this);
45-
46-
app(ConsistencyServiceInterface::class)->checkPotential($wallet, $amount);
44+
return app(AtomicServiceInterface::class)->block($this, function () use ($to, $amount, $meta): Transfer {
45+
app(ConsistencyServiceInterface::class)->checkPotential($this, $amount);
4746

48-
return $this->forceExchange($to, $amount, $meta);
47+
return $this->forceExchange($to, $amount, $meta);
48+
});
4949
}
5050

5151
public function safeExchange(Wallet $to, int|string $amount, ExtraDtoInterface|array|null $meta = null): ?Transfer

src/Traits/HasWallet.php

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,12 @@ public function safeTransfer(
125125
*/
126126
public function transfer(Wallet $wallet, int|string $amount, ExtraDtoInterface|array|null $meta = null): Transfer
127127
{
128-
/** @var Wallet $this */
129-
app(ConsistencyServiceInterface::class)->checkPotential($this, $amount);
128+
return app(AtomicServiceInterface::class)->block($this, function () use ($wallet, $amount, $meta): Transfer {
129+
/** @var Wallet $this */
130+
app(ConsistencyServiceInterface::class)->checkPotential($this, $amount);
130131

131-
return $this->forceTransfer($wallet, $amount, $meta);
132+
return $this->forceTransfer($wallet, $amount, $meta);
133+
});
132134
}
133135

134136
/**
@@ -144,10 +146,16 @@ public function transfer(Wallet $wallet, int|string $amount, ExtraDtoInterface|a
144146
*/
145147
public function withdraw(int|string $amount, ?array $meta = null, bool $confirmed = true): Transaction
146148
{
147-
/** @var Wallet $this */
148-
app(ConsistencyServiceInterface::class)->checkPotential($this, $amount);
149-
150-
return $this->forceWithdraw($amount, $meta, $confirmed);
149+
return app(AtomicServiceInterface::class)->block($this, function () use (
150+
$amount,
151+
$meta,
152+
$confirmed
153+
): Transaction {
154+
/** @var Wallet $this */
155+
app(ConsistencyServiceInterface::class)->checkPotential($this, $amount);
156+
157+
return $this->forceWithdraw($amount, $meta, $confirmed);
158+
});
151159
}
152160

153161
/**

0 commit comments

Comments
 (0)