diff --git a/app/Jobs/StatServerJob.php b/app/Jobs/StatServerJob.php index 6dfc793..ba567b0 100644 --- a/app/Jobs/StatServerJob.php +++ b/app/Jobs/StatServerJob.php @@ -10,6 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; class StatServerJob implements ShouldQueue { @@ -22,6 +23,15 @@ class StatServerJob implements ShouldQueue public $tries = 3; public $timeout = 60; + public $maxExceptions = 3; + + /** + * Calculate the number of seconds to wait before retrying the job. + */ + public function backoff(): array + { + return [1, 5, 10]; + } /** * Create a new job instance. @@ -40,7 +50,6 @@ class StatServerJob implements ShouldQueue */ public function handle(): void { - // Calculate record timestamp $recordAt = $this->recordType === 'm' ? strtotime(date('Y-m-01')) : strtotime(date('Y-m-d')); @@ -51,28 +60,33 @@ class StatServerJob implements ShouldQueue $u += $traffic[0]; $d += $traffic[1]; } - DB::transaction(function () use ($u, $d, $recordAt) { - $stat = StatServer::lockForUpdate() - ->where('record_at', $recordAt) - ->where('server_id', $this->server['id']) - ->where('server_type', $this->protocol) - ->where('record_type', $this->recordType) - ->first(); - if ($stat) { - $stat->u += $u; - $stat->d += $d; - $stat->save(); - } else { - StatServer::create([ + try { + DB::transaction(function () use ($u, $d, $recordAt) { + $affected = StatServer::where([ 'record_at' => $recordAt, 'server_id' => $this->server['id'], 'server_type' => $this->protocol, 'record_type' => $this->recordType, - 'u' => $u, - 'd' => $d, + ])->update([ + 'u' => DB::raw('u + ' . $u), + 'd' => DB::raw('d + ' . $d), ]); - } - }); + + if (!$affected) { + StatServer::create([ + 'record_at' => $recordAt, + 'server_id' => $this->server['id'], + 'server_type' => $this->protocol, + 'record_type' => $this->recordType, + 'u' => $u, + 'd' => $d, + ]); + } + }, 3); + } catch (\Exception $e) { + Log::error('StatServerJob failed for server ' . $this->server['id'] . ': ' . $e->getMessage()); + throw $e; + } } } diff --git a/app/Jobs/StatUserJob.php b/app/Jobs/StatUserJob.php index 950421b..c8927f2 100644 --- a/app/Jobs/StatUserJob.php +++ b/app/Jobs/StatUserJob.php @@ -10,6 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; class StatUserJob implements ShouldQueue { @@ -22,6 +23,15 @@ class StatUserJob implements ShouldQueue public $tries = 3; public $timeout = 60; + public $maxExceptions = 3; + + /** + * Calculate the number of seconds to wait before retrying the job. + */ + public function backoff(): array + { + return [1, 5, 10]; + } /** * Create a new job instance. @@ -40,34 +50,38 @@ class StatUserJob implements ShouldQueue */ public function handle(): void { - // Calculate record timestamp $recordAt = $this->recordType === 'm' ? strtotime(date('Y-m-01')) : strtotime(date('Y-m-d')); foreach ($this->data as $uid => $v) { - DB::transaction(function () use ($uid, $v, $recordAt) { - $stat = StatUser::lockForUpdate() - ->where('user_id', $uid) - ->where('server_rate', $this->server['rate']) - ->where('record_at', $recordAt) - ->where('record_type', $this->recordType) - ->first(); - if ($stat) { - $stat->u += ($v[0] * $this->server['rate']); - $stat->d += ($v[1] * $this->server['rate']); - $stat->save(); - } else { - StatUser::create([ + try { + DB::transaction(function () use ($uid, $v, $recordAt) { + $affected = StatUser::where([ 'user_id' => $uid, 'server_rate' => $this->server['rate'], 'record_at' => $recordAt, 'record_type' => $this->recordType, - 'u' => ($v[0] * $this->server['rate']), - 'd' => ($v[1] * $this->server['rate']), + ])->update([ + 'u' => DB::raw('u + ' . ($v[0] * $this->server['rate'])), + 'd' => DB::raw('d + ' . ($v[1] * $this->server['rate'])), ]); - } - }); + + if (!$affected) { + StatUser::create([ + 'user_id' => $uid, + 'server_rate' => $this->server['rate'], + 'record_at' => $recordAt, + 'record_type' => $this->recordType, + 'u' => ($v[0] * $this->server['rate']), + 'd' => ($v[1] * $this->server['rate']), + ]); + } + }, 3); + } catch (\Exception $e) { + Log::error('StatUserJob failed for user ' . $uid . ': ' . $e->getMessage()); + throw $e; + } } } } \ No newline at end of file