Skip to content

Commit

Permalink
Subscribe to laravel events
Browse files Browse the repository at this point in the history
  • Loading branch information
rez1dent3 committed Oct 19, 2022
1 parent e7a8726 commit 696dbb7
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 61 deletions.
2 changes: 2 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Bavix\Wallet\Internal\Repository\TransferRepository;
use Bavix\Wallet\Internal\Repository\WalletRepository;
use Bavix\Wallet\Internal\Service\ClockService;
use Bavix\Wallet\Internal\Service\ConnectionService;
use Bavix\Wallet\Internal\Service\DatabaseService;
use Bavix\Wallet\Internal\Service\DispatcherService;
use Bavix\Wallet\Internal\Service\JsonService;
Expand Down Expand Up @@ -82,6 +83,7 @@
*/
'internal' => [
'clock' => ClockService::class,
'connection' => ConnectionService::class,
'database' => DatabaseService::class,
'dispatcher' => DispatcherService::class,
'json' => JsonService::class,
Expand Down
3 changes: 3 additions & 0 deletions src/Internal/Exceptions/ExceptionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@ interface ExceptionInterface extends Throwable

public const MODEL_NOT_FOUND = 1 << 11;

/**
* @deprecated no longer used
*/
public const TRANSACTION_START = 1 << 12;
}
21 changes: 21 additions & 0 deletions src/Internal/Exceptions/TransactionRollbackException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Exceptions;

use InvalidArgumentException;

final class TransactionRollbackException extends InvalidArgumentException implements ExceptionInterface
{
public function __construct(
private mixed $result
) {
parent::__construct();
}

public function getResult(): mixed
{
return $this->result;
}
}
4 changes: 4 additions & 0 deletions src/Internal/Exceptions/TransactionStartException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

use LogicException;

/**
* @deprecated no longer used
* @codeCoverageIgnore
*/
final class TransactionStartException extends LogicException implements LogicExceptionInterface
{
}
24 changes: 24 additions & 0 deletions src/Internal/Listeners/TransactionBeginningListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Listeners;

use Bavix\Wallet\Internal\Service\ConnectionServiceInterface;
use Bavix\Wallet\Services\RegulatorServiceInterface;

final class TransactionBeginningListener
{
public function __construct(
private ConnectionServiceInterface $connectionService,
private RegulatorServiceInterface $regulatorService
) {
}

public function __invoke(): void
{
if ($this->connectionService->get()->transactionLevel() === 1) {
$this->regulatorService->purge();
}
}
}
20 changes: 20 additions & 0 deletions src/Internal/Listeners/TransactionCommittedListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Listeners;

use Bavix\Wallet\Services\RegulatorServiceInterface;

final class TransactionCommittedListener
{
public function __construct(
private RegulatorServiceInterface $regulatorService
) {
}

public function __invoke(): void
{
$this->regulatorService->approve();
}
}
20 changes: 20 additions & 0 deletions src/Internal/Listeners/TransactionRolledBackListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Listeners;

use Bavix\Wallet\Services\RegulatorServiceInterface;

final class TransactionRolledBackListener
{
public function __construct(
private RegulatorServiceInterface $regulatorService
) {
}

public function __invoke(): void
{
$this->regulatorService->purge();
}
}
26 changes: 26 additions & 0 deletions src/Internal/Service/ConnectionService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Service;

use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\ConnectionResolverInterface;

/**
* @internal
*/
final class ConnectionService implements ConnectionServiceInterface
{
private ConnectionInterface $connection;

public function __construct(ConnectionResolverInterface $connectionResolver)
{
$this->connection = $connectionResolver->connection(config('wallet.database.connection'));
}

public function get(): ConnectionInterface
{
return $this->connection;
}
}
12 changes: 12 additions & 0 deletions src/Internal/Service/ConnectionServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Bavix\Wallet\Internal\Service;

use Illuminate\Database\ConnectionInterface;

interface ConnectionServiceInterface
{
public function get(): ConnectionInterface;
}
42 changes: 9 additions & 33 deletions src/Internal/Service/DatabaseService.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@

use Bavix\Wallet\Internal\Exceptions\ExceptionInterface;
use Bavix\Wallet\Internal\Exceptions\TransactionFailedException;
use Bavix\Wallet\Internal\Exceptions\TransactionStartException;
use Bavix\Wallet\Internal\Exceptions\TransactionRollbackException;
use Bavix\Wallet\Services\RegulatorServiceInterface;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Database\RecordsNotFoundException;
use Throwable;

final class DatabaseService implements DatabaseServiceInterface
{
private ConnectionInterface $connection;

private bool $init = false;

public function __construct(
ConnectionResolverInterface $connectionResolver,
private ConnectionServiceInterface $connectionService,
private RegulatorServiceInterface $regulatorService
) {
$this->connection = $connectionResolver->connection(config('wallet.database.connection'));
}

/**
Expand All @@ -33,39 +26,25 @@ public function __construct(
*/
public function transaction(callable $callback): mixed
{
$level = $this->connection->transactionLevel();
if ($level > 0 && ! $this->init) {
throw new TransactionStartException(
'Working inside an embedded transaction is not possible. https://bavix.github.io/laravel-wallet/#/transaction',
ExceptionInterface::TRANSACTION_START,
);
}

if ($level > 0) {
$connection = $this->connectionService->get();
if ($connection->transactionLevel() > 0) {
return $callback();
}

$this->init = true;

try {
$this->regulatorService->purge();

return $this->connection->transaction(function () use ($callback) {
return $connection->transaction(function () use ($callback) {
$result = $callback();
$this->init = false;

if ($result === false) {
return false;
}

if (is_countable($result) && count($result) === 0) {
return $result;
if ($result === false || (is_countable($result) && count($result) === 0)) {
throw new TransactionRollbackException($result);
}

$this->regulatorService->approve();

return $result;
});
} catch (TransactionRollbackException $rollbackException) {
return $rollbackException->getResult();
} catch (RecordsNotFoundException|ExceptionInterface $exception) {
throw $exception;
} catch (Throwable $throwable) {
Expand All @@ -74,9 +53,6 @@ public function transaction(callable $callback): mixed
ExceptionInterface::TRANSACTION_FAILED,
$throwable
);
} finally {
$this->regulatorService->purge();
$this->init = false;
}
}
}
11 changes: 11 additions & 0 deletions src/WalletServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
use Bavix\Wallet\Internal\Repository\WalletRepositoryInterface;
use Bavix\Wallet\Internal\Service\ClockService;
use Bavix\Wallet\Internal\Service\ClockServiceInterface;
use Bavix\Wallet\Internal\Service\ConnectionService;
use Bavix\Wallet\Internal\Service\ConnectionServiceInterface;
use Bavix\Wallet\Internal\Service\DatabaseService;
use Bavix\Wallet\Internal\Service\DatabaseServiceInterface;
use Bavix\Wallet\Internal\Service\DispatcherService;
Expand Down Expand Up @@ -109,6 +111,10 @@
use function dirname;
use function function_exists;
use Illuminate\Contracts\Cache\Factory as CacheFactory;
use Illuminate\Database\Events\TransactionBeginning;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Database\Events\TransactionRolledBack;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

final class WalletServiceProvider extends ServiceProvider
Expand All @@ -122,6 +128,10 @@ public function boot(): void
{
$this->loadTranslationsFrom(dirname(__DIR__) . '/resources/lang', 'wallet');

Event::listen(TransactionBeginning::class, Internal\Listeners\TransactionBeginningListener::class);
Event::listen(TransactionCommitted::class, Internal\Listeners\TransactionCommittedListener::class);
Event::listen(TransactionRolledBack::class, Internal\Listeners\TransactionRolledBackListener::class);

if (! $this->app->runningInConsole()) {
return;
}
Expand Down Expand Up @@ -213,6 +223,7 @@ private function internal(array $configure): void
->giveConfig('wallet.cache.ttl');

$this->app->singleton(ClockServiceInterface::class, $configure['clock'] ?? ClockService::class);
$this->app->singleton(ConnectionServiceInterface::class, $configure['connection'] ?? ConnectionService::class);
$this->app->singleton(DatabaseServiceInterface::class, $configure['database'] ?? DatabaseService::class);
$this->app->singleton(DispatcherServiceInterface::class, $configure['dispatcher'] ?? DispatcherService::class);
$this->app->singleton(JsonServiceInterface::class, $configure['json'] ?? JsonService::class);
Expand Down
1 change: 0 additions & 1 deletion tests/Units/Domain/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ public function testBalanceUpdatedThrowDateListener(): void

// unit
$this->expectException(UnknownEventException::class);
$this->expectExceptionMessage(ClockFakeService::FAKE_DATETIME);
$this->expectExceptionCode(789);

$buyer->deposit(789);
Expand Down
27 changes: 0 additions & 27 deletions tests/Units/Service/DatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

use Bavix\Wallet\Internal\Exceptions\ExceptionInterface;
use Bavix\Wallet\Internal\Exceptions\TransactionFailedException;
use Bavix\Wallet\Internal\Exceptions\TransactionStartException;
use Bavix\Wallet\Internal\Service\DatabaseServiceInterface;
use Bavix\Wallet\Test\Infra\TestCase;
use Illuminate\Support\Facades\DB;

/**
* @internal
Expand All @@ -29,29 +27,4 @@ public function testCheckCode(): void
throw new \RuntimeException('hello');
});
}

/**
* @throws ExceptionInterface
*/
public function testCheckInTransaction(): void
{
$this->expectException(TransactionStartException::class);
$this->expectExceptionCode(ExceptionInterface::TRANSACTION_START);

DB::beginTransaction();
app(DatabaseServiceInterface::class)->transaction(static fn (): int => 42);
}

public function testInterceptionErrorStartTransaction(): void
{
try {
DB::beginTransaction();
app(DatabaseServiceInterface::class)->transaction(static fn (): int => 42);
self::fail(__METHOD__);
} catch (TransactionStartException) {
DB::rollBack(0); // for success
$result = app(DatabaseServiceInterface::class)->transaction(static fn (): int => 42);
self::assertSame(42, $result);
}
}
}

0 comments on commit 696dbb7

Please sign in to comment.