feat(order): wait for colleague callback before settling wallet
Keep cover orders pending until colleague sts 2/4/6 via callback or 35s poll. Nightly prices:prune also drops old log tables. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Log;
|
||||
use App\Models\PargarSyncLog;
|
||||
use App\Models\PriceSyncLog;
|
||||
use App\Models\PriceSyncLogItem;
|
||||
use App\Models\Tahesab;
|
||||
use App\Models\Zarin;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* پاکسازی شبانهٔ لاگهای حجیم — همان سقف نگهداری جدول prices (۳۱ روز).
|
||||
*/
|
||||
class DatabaseLogPruneService
|
||||
{
|
||||
/** همراستا با حذف قطعی در PriceSnapshotService::pruneHistory */
|
||||
public const RETENTION_DAYS = 31;
|
||||
|
||||
private const CHUNK = 500;
|
||||
|
||||
public function pruneHistory(?Carbon $now = null): array
|
||||
{
|
||||
$cutoff = ($now ?? now())->copy()->subDays(self::RETENTION_DAYS);
|
||||
|
||||
return [
|
||||
'retention_days' => self::RETENTION_DAYS,
|
||||
'cutoff' => $cutoff->toDateTimeString(),
|
||||
'price_sync_logs' => $this->prunePriceSyncLogs($cutoff),
|
||||
'logs' => $this->pruneGenericLogs($cutoff),
|
||||
'pargar_sync_logs' => $this->pruneSuccessfulRows(
|
||||
PargarSyncLog::query(),
|
||||
'pargar_sync_logs',
|
||||
PargarSyncService::STATUS_SUCCESS,
|
||||
$cutoff
|
||||
),
|
||||
'zarin' => $this->pruneSuccessfulRows(
|
||||
Zarin::query(),
|
||||
'zarin',
|
||||
ZarinSyncService::STATUS_SUCCESS,
|
||||
$cutoff
|
||||
),
|
||||
'tahesab' => $this->pruneSuccessfulRows(
|
||||
Tahesab::query(),
|
||||
'tahesab',
|
||||
TahesabSyncService::STATUS_SUCCESS,
|
||||
$cutoff
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array{deleted: int, items_deleted: int} */
|
||||
private function prunePriceSyncLogs(Carbon $cutoff): array
|
||||
{
|
||||
if (! Schema::hasTable('price_sync_logs')) {
|
||||
return ['deleted' => 0, 'items_deleted' => 0];
|
||||
}
|
||||
|
||||
$deleted = 0;
|
||||
$itemsDeleted = 0;
|
||||
$hasItems = Schema::hasTable('price_sync_log_items');
|
||||
|
||||
PriceSyncLog::query()
|
||||
->where('created_at', '<', $cutoff)
|
||||
->orderBy('id')
|
||||
->select(['id'])
|
||||
->chunkById(self::CHUNK, function ($rows) use (&$deleted, &$itemsDeleted, $hasItems) {
|
||||
$ids = $rows->pluck('id')->all();
|
||||
if ($ids === []) {
|
||||
return;
|
||||
}
|
||||
if ($hasItems) {
|
||||
$itemsDeleted += (int) PriceSyncLogItem::query()->whereIn('log_id', $ids)->delete();
|
||||
}
|
||||
$deleted += (int) PriceSyncLog::query()->whereIn('id', $ids)->delete();
|
||||
});
|
||||
|
||||
return ['deleted' => $deleted, 'items_deleted' => $itemsDeleted];
|
||||
}
|
||||
|
||||
/** @return array{deleted: int} */
|
||||
private function pruneGenericLogs(Carbon $cutoff): array
|
||||
{
|
||||
if (! Schema::hasTable('logs')) {
|
||||
return ['deleted' => 0];
|
||||
}
|
||||
|
||||
$deleted = 0;
|
||||
|
||||
Log::query()
|
||||
->where('created_at', '<', $cutoff)
|
||||
->orderBy('id')
|
||||
->select(['id'])
|
||||
->chunkById(self::CHUNK, function ($rows) use (&$deleted) {
|
||||
$ids = $rows->pluck('id')->all();
|
||||
if ($ids === []) {
|
||||
return;
|
||||
}
|
||||
$deleted += (int) Log::query()->whereIn('id', $ids)->delete();
|
||||
});
|
||||
|
||||
return ['deleted' => $deleted];
|
||||
}
|
||||
|
||||
/**
|
||||
* فقط ردیفهای موفق حسابداری — pending/failed برای retry میمانند.
|
||||
*
|
||||
* @return array{deleted: int, skipped: bool}
|
||||
*/
|
||||
private function pruneSuccessfulRows(Builder $query, string $table, string $successStatus, Carbon $cutoff): array
|
||||
{
|
||||
if (! Schema::hasTable($table) || ! Schema::hasColumn($table, 'sync_status')) {
|
||||
return ['deleted' => 0, 'skipped' => true];
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn($table, 'created_at')) {
|
||||
return ['deleted' => 0, 'skipped' => true];
|
||||
}
|
||||
|
||||
$deleted = 0;
|
||||
|
||||
(clone $query)
|
||||
->where('sync_status', $successStatus)
|
||||
->where('created_at', '<', $cutoff)
|
||||
->orderBy('id')
|
||||
->select(['id'])
|
||||
->chunkById(self::CHUNK, function ($rows) use (&$deleted, $query) {
|
||||
$ids = $rows->pluck('id')->all();
|
||||
if ($ids === []) {
|
||||
return;
|
||||
}
|
||||
$deleted += (int) (clone $query)->whereIn('id', $ids)->delete();
|
||||
});
|
||||
|
||||
return ['deleted' => $deleted, 'skipped' => false];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user