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

fix: issues with caching #16

Merged
merged 8 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions src/Concerns/InteractsWithWallet.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@

use Exception;
use Flavorly\LaravelHelpers\Helpers\Math\Math;
use Flavorly\Wallet\Exceptions\WalletLockedException;
use Flavorly\Wallet\Models\Transaction;
use Flavorly\Wallet\Services\BalanceService;
use Flavorly\Wallet\Wallet;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Throwable;

/**
* @mixin Model
Expand Down Expand Up @@ -77,38 +75,4 @@ public function balance(): BalanceService
{
return $this->wallet()->balance();
}

/**
* Alias for Credit
*
*
* @throws WalletLockedException
* @throws Throwable
*/
public function credit(float|int|string $amount, array $meta = [], ?string $endpoint = null, bool $throw = false): bool
{
return $this->wallet()->credit(
amount: $amount,
meta: $meta,
endpoint: $endpoint,
throw: $throw
);
}

/**
* Alias for debit
*
*
* @throws WalletLockedException
* @throws Throwable
*/
public function debit(float|int|string $amount, array $meta = [], ?string $endpoint = null, bool $throw = false): bool
{
return $this->wallet()->debit(
amount: $amount,
meta: $meta,
endpoint: $endpoint,
throw: $throw
);
}
}
14 changes: 0 additions & 14 deletions src/Contracts/HasWallet.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,6 @@ public function getBalanceAttribute(): Math;
*/
public function getBalanceFormattedAttribute(): string;

/**
* Credits the user or model with the given amount
*
* @param array<string,mixed> $meta
*/
public function credit(float|int|string $amount, array $meta = [], ?string $endpoint = null, bool $throw = false): bool;

/**
* Debits the user or model with the given amount
*
* @param array<string,mixed> $meta
*/
public function debit(float|int|string $amount, array $meta = [], ?string $endpoint = null, bool $throw = false): bool;

/**
* Get the balance service instance
*/
Expand Down
2 changes: 1 addition & 1 deletion src/Data/WalletOperationData.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ final class WalletOperationData extends Data
public function __construct(
public bool $credit,
public float|int|string $amount,
public string $endpoint,
public ?Model $owner = null,
public ?Model $subject = null,
public ?string $endpoint = null,
/** @var array<string,mixed> */
public array $meta = [],
) {}
Expand Down
2 changes: 1 addition & 1 deletion src/Models/Transaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* @property int|null $subject_id
* @property bool $credit
* @property int|string|float $amount
* @property string|null $endpoint
* @property string $endpoint
* @property array|null $meta
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
Expand Down
10 changes: 6 additions & 4 deletions src/Services/BalanceService.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function __construct(
* the cache()->isWithin() will return true if we are currently performing
* a transaction and so we have already applied a lock inside it.
*/
protected function refresh(): void
public function refresh(): BalanceService
{
$closure = function () {
// Sum all the balance
Expand All @@ -58,18 +58,20 @@ protected function refresh(): void
if ($this->cache->isWithin()) {
$closure();

return;
return $this;
}

$this->cache->blockAndWrapInTransaction($closure);

return $this;
}

/**
* Returns the balance without any formatting or casting
*/
public function raw(bool $cached = true): int|float|string|null
{
if (! $cached) {
if (! $cached || $this->localCachedRawBalance === null) {
$this->refresh();
}

Expand Down Expand Up @@ -118,11 +120,11 @@ public function hasEnoughFor(float|int|string $amount): bool
{
try {
(new OperationService(
credit: false,
model: $this->model,
cache: $this->cache,
configuration: $this->configuration,
balance: $this,
credit: false,
))
->debit($amount)
->throw(false)
Expand Down
4 changes: 3 additions & 1 deletion src/Services/CacheService.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ public function locked(): bool
/** @var CacheManager $lockConnection */
$lockConnection = $store->lockConnection();

return $lockConnection->get(Cache::getPrefix().$this->blockPrefix()) !== null;
$prefix = Cache::getPrefix() ?? config('cache.prefix', 'redis__');

return $lockConnection->get($prefix.$this->blockPrefix()) !== null;
}

/**
Expand Down
28 changes: 22 additions & 6 deletions src/Services/OperationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ final class OperationService
/**
* Stores the endpoint
*/
protected ?string $endpoint = null;
protected string $endpoint = 'default';

/**
* How much times to retry before failing
Expand All @@ -103,19 +103,19 @@ final class OperationService
/**
* Stores the transaction if it was successful
*/
protected ?Transaction $transaction = null;
public ?Transaction $transaction = null;

/**
* Related Model of the transaction
*/
protected ?Model $subject = null;

public function __construct(
bool $credit,
public readonly WalletInterface $model,
public readonly CacheService $cache,
public readonly ConfigurationService $configuration,
public readonly BalanceService $balance,
bool $credit = false,
) {
$this->credit = $credit;
}
Expand Down Expand Up @@ -397,11 +397,15 @@ protected function compileDefaultCallbacks(): OperationService
];

if ($this->subject) {
$morphClass = method_exists($this->subject, 'getMorphClass') ? $this->subject->getMorphClass() : get_class($this->subject);
$payload['subject_id'] = $this->subject->getKey();
$payload['subject_type'] = get_class($this->subject);
$payload['subject_type'] = $morphClass;
}

$this->transaction = $this->model->transactions()->create($payload);
$this->transaction = $this
->model
->transactions()
->create($payload);

// Dispatch Transaction Created Event
event(new TransactionCreatedEvent(
Expand Down Expand Up @@ -474,6 +478,18 @@ protected function callback(?callable $callback, bool $shift = false): Operation
return $this;
}

/**
* Instructs the amount of the transaction
*
* @return $this
*/
public function amount(float|int|string $amount): OperationService
{
$this->amount = $amount;

return $this;
}

/**
* Instructs that a credit should be made
*
Expand Down Expand Up @@ -545,7 +561,7 @@ public function throw(bool|Closure $condition = true): OperationService
*
* @return $this
*/
public function endpoint(?string $endpoint = null): OperationService
public function endpoint(string $endpoint = 'default'): OperationService
{
$this->endpoint = $endpoint;

Expand Down
72 changes: 41 additions & 31 deletions src/Wallet.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use Flavorly\Wallet\Contracts\HasWallet as WalletInterface;
use Flavorly\Wallet\Exceptions\InvalidOperationArgumentsException;
use Flavorly\Wallet\Exceptions\WalletLockedException;
use Flavorly\Wallet\Services\BalanceService;
use Flavorly\Wallet\Services\CacheService;
Expand Down Expand Up @@ -43,6 +44,10 @@ final class Wallet
*/
public function __construct(public readonly WalletInterface $model)
{
$key = $model->getKey();
if (! $key) {
throw new InvalidOperationArgumentsException('Model must have a primary key');
}
$this->configuration = app(ConfigurationService::class, ['model' => $model]);
$this->cache = app(CacheService::class, ['prefix' => $model->getKey()]);
$this->balance = app(BalanceService::class, [
Expand All @@ -62,22 +67,21 @@ public function __construct(public readonly WalletInterface $model)
*/
public function credit(
float|int|string $amount,
string $endpoint = 'default',
array $meta = [],
?string $endpoint = null,
bool $throw = false,
?Closure $after = null,
?Model $subject = null,
): bool {
): OperationService {
return $this
->operation(true)
->meta($meta)
->operation()
->credit($amount)
->meta($meta)
->throw($throw)
->after($after)
->subject($subject)
->endpoint($endpoint)
->dispatch()
->ok();
->dispatch();
}

/**
Expand All @@ -90,40 +94,45 @@ public function credit(
*/
public function debit(
float|int|string $amount,
string $endpoint = 'default',
array $meta = [],
?string $endpoint = null,
bool $throw = false,
?Closure $after = null,
?Model $subject = null,
): bool {
): OperationService {
return $this
->operation(false)
->meta($meta)
->operation()
->debit($amount)
->meta($meta)
->throw($throw)
->after($after)
->subject($subject)
->endpoint($endpoint)
->dispatch()
->ok();
->dispatch();
}

/**
* Credit the user quietly without exceptions
*
* @param array<string,mixed> $meta
*/
public function creditQuietly(float|int|string $amount, array $meta = [], ?string $endpoint = null): bool
{
public function creditQuietly(
float|int|string $amount,
string $endpoint = 'default',
?Model $subject = null,
array $meta = []
): OperationService {
$operation = $this
->operation()
->credit($amount)
->meta($meta)
->throw(false)
->subject($subject)
->endpoint($endpoint);
try {
return $this->credit(
amount: $amount,
meta: $meta,
endpoint: $endpoint,
throw: true
);
return $operation->dispatch();
} catch (Throwable $e) {
return false;
return $operation;
}
}

Expand All @@ -132,17 +141,19 @@ public function creditQuietly(float|int|string $amount, array $meta = [], ?strin
*
* @param array<string,mixed> $meta
*/
public function debitQuietly(float|int|string $amount, array $meta = [], ?string $endpoint = null): bool
public function debitQuietly(float|int|string $amount, string $endpoint = 'default', ?Model $subject = null, array $meta = []): OperationService
{
$operation = $this
->operation()
->debit($amount)
->meta($meta)
->throw(false)
->subject($subject)
->endpoint($endpoint);
try {
return $this->debit(
amount: $amount,
meta: $meta,
endpoint: $endpoint,
throw: true
);
return $operation->dispatch();
} catch (Throwable $e) {
return false;
return $operation;
}
}

Expand All @@ -151,10 +162,9 @@ public function debitQuietly(float|int|string $amount, array $meta = [], ?string
* This is the main entry point to create transaction
* Wallet class is just an API for the actual underlying operation object
*/
public function operation(bool $credit): OperationService
public function operation(): OperationService
{
return new OperationService(
$credit,
$this->model,
$this->cache,
$this->configuration,
Expand Down
Loading