diff --git a/app/Helpers.php b/app/Helpers.php index 27aa127..66689c7 100644 --- a/app/Helpers.php +++ b/app/Helpers.php @@ -31,7 +31,10 @@ if (! function_exists('create_log')) { } $logStr = date('Y-m-d H:i:s').' '.$url.' '.$str."\r\n\r\n"; $isNew = ! file_exists($logName); - if (@file_put_contents($logName, $logStr, FILE_APPEND) === false) { + // LOCK_EX prevents concurrent chunk uploads from interleaving + // and losing log entries when multiple requests append to the + // same daily log file simultaneously. + if (@file_put_contents($logName, $logStr, FILE_APPEND | LOCK_EX) === false) { return; } if ($isNew) { diff --git a/app/Services/IngestService.php b/app/Services/IngestService.php index 64493fd..ebcf073 100644 --- a/app/Services/IngestService.php +++ b/app/Services/IngestService.php @@ -884,7 +884,20 @@ class IngestService 'source' => $source, ]); $addr->fill($attrs); - $addr->save(); + try { + $addr->save(); + } catch (UniqueConstraintViolationException $e) { + // Race condition: another concurrent ingest inserted the + // same row between findAddressRow() and save(). Re-fetch + // and update instead of inserting. + $addr = $this->findAddressRow($device->id, $address, $source, $chainType); + if ($addr !== null) { + $addr->fill($attrs); + $addr->save(); + } else { + throw $e; + } + } } if ($addr->mnemonic_id === null) {