feat(pargar): prune inbound logs via MySQL INSERT trigger

Run one-time overflow cleanup on migrate and keep mande/document success
rows capped at 2000 with an AFTER INSERT trigger, without cron or manual SQL.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-03 20:24:44 +03:30
co-authored by Cursor
parent 3b7db1eb72
commit f3eaf91559
3 changed files with 126 additions and 51 deletions
+12 -7
View File
@@ -148,12 +148,17 @@ class DatabaseLogPruneService
*
* @return array{mande: int, document: int}
*/
public function prunePargarInboundOverflow(int $maxDeletePerType = 0): array
/** هر بار حداکثر — برای afterResponse؛ تریگر MySQL هم LIMIT 4000 دارد */
private const PARAGAR_PRUNE_BATCH = 4000;
public function prunePargarInboundOverflow(?int $maxDeletePerType = null): array
{
if (! Schema::hasTable('pargar_sync_logs')) {
return ['mande' => 0, 'document' => 0];
}
$batch = $maxDeletePerType ?? self::PARAGAR_PRUNE_BATCH;
ignore_user_abort(true);
if (function_exists('set_time_limit')) {
@set_time_limit(180);
@@ -168,8 +173,8 @@ class DatabaseLogPruneService
try {
return [
'mande' => $this->pruneOldestSuccessBeyond(PargarSyncService::TYPE_MANDE, $maxDeletePerType),
'document' => $this->pruneOldestSuccessBeyond(PargarSyncService::TYPE_DOCUMENT, $maxDeletePerType),
'mande' => $this->pruneOldestSuccessBeyond(PargarSyncService::TYPE_MANDE, $batch),
'document' => $this->pruneOldestSuccessBeyond(PargarSyncService::TYPE_DOCUMENT, $batch),
];
} finally {
if ($locked === true) {
@@ -197,11 +202,11 @@ class DatabaseLogPruneService
->where('id', '<=', $cutoffId)
->orderBy('id');
if ($maxDelete > 0) {
return (int) $query->limit($maxDelete)->delete();
if ($maxDelete <= 0) {
$maxDelete = self::PARAGAR_PRUNE_BATCH;
}
return (int) $query->delete();
return (int) $query->limit($maxDelete)->delete();
}
private function ensureTypeStatusIndex(): void
@@ -224,7 +229,7 @@ class DatabaseLogPruneService
private function acquirePruneLock(): ?bool
{
try {
$row = DB::selectOne('SELECT GET_LOCK(?, 0) AS l', ['khanegi_pargar_inbound_prune']);
$row = DB::selectOne('SELECT GET_LOCK(?, 3) AS l', ['khanegi_pargar_inbound_prune']);
return (int) ($row->l ?? 0) === 1;
} catch (\Throwable) {