Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.1] Transaction State #412

Merged
merged 32 commits into from
Dec 3, 2021
Merged

[7.1] Transaction State #412

merged 32 commits into from
Dec 3, 2021

Conversation

rez1dent3
Copy link
Member

@rez1dent3 rez1dent3 commented Nov 28, 2021

I would like to add atomicity to the project. Sometimes it is necessary to work with a package within a transaction, and this MR must solve your problem.

Let's take an example. You start the transaction by debiting the wallet money, and then you start to raise an ad in the search. Suddenly your service for working with raising an ad has crashed and it returns any exception. So, the transaction will fail and all operations will be rolled back, but not the storage. If you are using redis, then the balance will already be changed and this must be dealt with.

$user->balanceInt; // 40,000
app(DatabaseServiceInterface::class)->transaction(static function () use ($user) {
    $user->withdraw(10000); // There are already 30,000

    throw new RuntimeException('hello world'); // Failed
}); // close transaction. rollback

$user->balanceInt; // 30,000;
$user->refreshBalance();
$user->balanceInt; // 40,000

It turns out that in two databases there is no way to start one transaction. We have to resort to such solutions.

So let's get back to this solution. We create a second store, an array. Inside the transaction, we work with the new storage and, if successful, we update the wallet balance. In case of failure, we delete the data from the temporary storage.

What happens with two running transactions? It's simple, the second storage stores only the difference between the transaction data and the current state of the wallet. If the first transaction completes work faster, then in the second transaction we will work with the current balance.

$redisStore = 500; // actual balance
$transStore = -70; // diff balance in transaction
$tmpStore = $redisStore + $transStore; // 430 -- This data will be available only within the current transaction, and upon completion it will be available to everyone.

Let's go back to the example above. We should be able to rollback all changes within a transaction.

$user->balanceInt; // 40,000
app(DatabaseServiceInterface::class)->transaction(static function () use ($user) {
    $user->withdraw(10000); // There are already 30,000

    throw new RuntimeException('hello world'); // Failed
}); // close transaction. rollback

$user->balanceInt; // 40,000;
$user->refreshBalance();
$user->balanceInt; // 40,000

Now the transaction also looks at the result from the callback function.

$user->balanceInt; // 40,000
app(DatabaseServiceInterface::class)->transaction(static function () use ($user) {
    $user->withdraw(10000); // There are already 30,000
    return false; // close transaction. rollback
});

$user->balanceInt; // 40,000;
$user->refreshBalance();
$user->balanceInt; // 40,000

@rez1dent3 rez1dent3 added enhancement New feature or request 7.x-dev labels Nov 28, 2021
@rez1dent3 rez1dent3 self-assigned this Nov 28, 2021
@cloudflare-pages
Copy link

cloudflare-pages bot commented Nov 28, 2021

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: b59ffa6
Status: ✅  Deploy successful!
Preview URL: https://13d1a264.laravel-wallet.pages.dev

View logs

@rez1dent3 rez1dent3 marked this pull request as draft November 28, 2021 08:56
@rez1dent3 rez1dent3 marked this pull request as ready for review November 28, 2021 11:30
@codecov
Copy link

codecov bot commented Nov 28, 2021

Codecov Report

Merging #412 (b59ffa6) into master (4a0cea9) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@             Coverage Diff             @@
##              master      #412   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
- Complexity       320       332   +12     
===========================================
  Files             54        54           
  Lines           1117      1145   +28     
===========================================
+ Hits            1117      1145   +28     
Impacted Files Coverage Δ
src/Internal/Service/DatabaseService.php 100.00% <100.00%> (ø)
src/Internal/Service/StorageService.php 100.00% <100.00%> (ø)
src/Models/Wallet.php 100.00% <100.00%> (ø)
src/Services/CastService.php 100.00% <100.00%> (ø)
src/Services/CommonServiceLegacy.php 100.00% <100.00%> (ø)
src/Services/RegulatorService.php 100.00% <100.00%> (ø)
src/Traits/CanConfirm.php 100.00% <100.00%> (ø)
src/Traits/HasWallet.php 100.00% <100.00%> (ø)
src/WalletServiceProvider.php 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4a0cea9...b59ffa6. Read the comment docs.

@rez1dent3
Copy link
Member Author

In vain did the regulator split the service with the state service. It's easy to get new bugs that I brought in with the 7.1.0-RC1 release. I will think about combining services.

@rez1dent3
Copy link
Member Author

This MR is bold enough for internal optimization. Expect better performance within transactions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant