fix: retry failed file transfers on next sync using pending queue in osurg_initials
This commit is contained in:
parent
4a85e07804
commit
0e16ea6052
|
|
@ -118,15 +118,15 @@ public function sync(): array
|
|||
} else {
|
||||
$report[] = 'هشدار: peer_cursor پیش نرفت — برخی تغییرات دریافتی اعمال نشد و دفعه بعد retry میشه.';
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isFtpConfigured()) {
|
||||
$this->transferFilesViaFtp($peerChanges, 's2c', $report);
|
||||
$this->transferFilesViaFtp($peerChanges ?? [], 's2c', $report);
|
||||
} else {
|
||||
$this->syncFilesViaHttp($peerChanges, $baseUrl, $report);
|
||||
}
|
||||
$this->syncFilesViaHttp($peerChanges ?? [], $baseUrl, $report);
|
||||
}
|
||||
|
||||
$report[] = count($peerChanges) . ' تغییر از سیستم مقابل دریافت شد.';
|
||||
$report[] = count($peerChanges ?? []) . ' تغییر از سیستم مقابل دریافت شد.';
|
||||
} else {
|
||||
$report[] = 'خطا در دریافت تغییرات از سیستم مقابل: ' . $pullResponse->status();
|
||||
}
|
||||
|
|
@ -196,20 +196,9 @@ public function applyChanges(array $changes): array
|
|||
|
||||
private function transferFilesViaFtp(array $changes, string $side, array &$report): void
|
||||
{
|
||||
if (empty($changes)) {
|
||||
return;
|
||||
}
|
||||
$ftp = $this->connectFtp();
|
||||
if (! $ftp) {
|
||||
$report[] = 'خطا در اتصال FTP به سیستم مقابل';
|
||||
Log::error('FTP connection failed in transferFilesViaFtp');
|
||||
return;
|
||||
}
|
||||
|
||||
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
|
||||
$localBase = rtrim(Storage::disk('public')->path(''), '/\\');
|
||||
$remoteBase = rtrim($this->ftpRemotePath, '/\\');
|
||||
|
||||
$currentPaths = [];
|
||||
foreach ($changes as $change) {
|
||||
$data = $change['changed_data'] ?? [];
|
||||
foreach ($fileFields as $field) {
|
||||
|
|
@ -218,19 +207,39 @@ private function transferFilesViaFtp(array $changes, string $side, array &$repor
|
|||
}
|
||||
$files = is_array($data[$field]) ? $data[$field] : json_decode($data[$field], true) ?? [];
|
||||
foreach ($files as $filePath) {
|
||||
if (! $filePath) {
|
||||
continue;
|
||||
if ($filePath) {
|
||||
$currentPaths[] = ltrim(str_replace('\\', '/', $filePath), '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$filePath = ltrim(str_replace('\\', '/', $filePath), '/');
|
||||
$pendingPaths = $this->getPendingFiles($side);
|
||||
$allPaths = array_values(array_unique(array_merge($pendingPaths, $currentPaths)));
|
||||
|
||||
if (empty($allPaths)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$ftp = $this->connectFtp();
|
||||
if (! $ftp) {
|
||||
$report[] = 'خطا در اتصال FTP به سیستم مقابل';
|
||||
Log::error('FTP connection failed in transferFilesViaFtp');
|
||||
return;
|
||||
}
|
||||
|
||||
$localBase = rtrim(Storage::disk('public')->path(''), '/\\');
|
||||
$remoteBase = rtrim($this->ftpRemotePath, '/\\');
|
||||
$failedPaths = [];
|
||||
|
||||
foreach ($allPaths as $filePath) {
|
||||
$localFile = $localBase . '/' . $filePath;
|
||||
$remoteFile = $remoteBase . '/' . $filePath;
|
||||
$remoteFolder = dirname($remoteFile);
|
||||
|
||||
if ($side === 'c2s') {
|
||||
if (! file_exists($localFile)) {
|
||||
$errorMsg = "فایل [{$filePath}] در سیستم محلی یافت نشد";
|
||||
$report[] = $errorMsg . ' ✗';
|
||||
$report[] = "فایل [{$filePath}] در سیستم محلی یافت نشد ✗";
|
||||
Log::warning('FTP upload skipped - local file not found', [
|
||||
'file' => $filePath,
|
||||
'local_path' => $localFile,
|
||||
|
|
@ -239,40 +248,31 @@ private function transferFilesViaFtp(array $changes, string $side, array &$repor
|
|||
}
|
||||
|
||||
if (! $this->createFtpDirectory($ftp, $remoteFolder)) {
|
||||
$errorMsg = "ایجاد پوشه [{$remoteFolder}] برای فایل [{$filePath}] شکست خورد";
|
||||
$report[] = $errorMsg . ' ✗';
|
||||
Log::error('FTP mkdir failed', [
|
||||
'file' => $filePath,
|
||||
'remote_folder' => $remoteFolder,
|
||||
]);
|
||||
$report[] = "ایجاد پوشه [{$remoteFolder}] برای فایل [{$filePath}] شکست خورد ✗";
|
||||
Log::error('FTP mkdir failed', ['file' => $filePath, 'remote_folder' => $remoteFolder]);
|
||||
$failedPaths[] = $filePath;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ftp_put($ftp, $remoteFile, $localFile, FTP_BINARY)) {
|
||||
$report[] = "فایل [{$filePath}] ارسال شد (FTP) ✓";
|
||||
Log::info('FTP file uploaded', [
|
||||
'file' => $filePath,
|
||||
'size' => filesize($localFile),
|
||||
]);
|
||||
Log::info('FTP file uploaded', ['file' => $filePath, 'size' => filesize($localFile)]);
|
||||
} else {
|
||||
$errorDetail = error_get_last();
|
||||
$errorMsg = "فایل [{$filePath}] ارسال نشد (FTP)";
|
||||
if ($errorDetail) {
|
||||
$errorMsg .= " - " . $errorDetail['message'];
|
||||
$errorMsg .= ' - ' . $errorDetail['message'];
|
||||
}
|
||||
$report[] = $errorMsg . ' ✗';
|
||||
$failedPaths[] = $filePath;
|
||||
Log::error('FTP upload failed', [
|
||||
'file' => $filePath,
|
||||
'local_file' => $localFile,
|
||||
'remote_file' => $remoteFile,
|
||||
'error' => $errorDetail,
|
||||
'file' => $filePath, 'local_file' => $localFile,
|
||||
'remote_file' => $remoteFile, 'error' => $errorDetail,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if (file_exists($localFile)) {
|
||||
Log::debug('FTP download skipped - file already exists', [
|
||||
'file' => $filePath,
|
||||
]);
|
||||
Log::debug('FTP download skipped - file already exists', ['file' => $filePath]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -280,37 +280,34 @@ private function transferFilesViaFtp(array $changes, string $side, array &$repor
|
|||
if (! is_dir($localFolder)) {
|
||||
if (! mkdir($localFolder, 0755, true)) {
|
||||
$report[] = "ایجاد پوشه [{$localFolder}] شکست خورد ✗";
|
||||
Log::error('Local mkdir failed', [
|
||||
'folder' => $localFolder,
|
||||
'error' => error_get_last(),
|
||||
]);
|
||||
$failedPaths[] = $filePath;
|
||||
Log::error('Local mkdir failed', ['folder' => $localFolder, 'error' => error_get_last()]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftp_get($ftp, $localFile, $remoteFile, FTP_BINARY)) {
|
||||
$report[] = "فایل [{$filePath}] دریافت شد (FTP) ✓";
|
||||
Log::info('FTP file downloaded', [
|
||||
'file' => $filePath,
|
||||
'size' => filesize($localFile),
|
||||
]);
|
||||
Log::info('FTP file downloaded', ['file' => $filePath, 'size' => filesize($localFile)]);
|
||||
} else {
|
||||
$errorDetail = error_get_last();
|
||||
$errorMsg = "فایل [{$filePath}] دریافت نشد (FTP)";
|
||||
if ($errorDetail) {
|
||||
$errorMsg .= " - " . $errorDetail['message'];
|
||||
$errorMsg .= ' - ' . $errorDetail['message'];
|
||||
}
|
||||
$report[] = $errorMsg . ' ✗';
|
||||
$failedPaths[] = $filePath;
|
||||
Log::error('FTP download failed', [
|
||||
'file' => $filePath,
|
||||
'local_file' => $localFile,
|
||||
'remote_file' => $remoteFile,
|
||||
'error' => $errorDetail,
|
||||
'file' => $filePath, 'local_file' => $localFile,
|
||||
'remote_file' => $remoteFile, 'error' => $errorDetail,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->savePendingFiles($side, $failedPaths);
|
||||
if (! empty($failedPaths)) {
|
||||
$report[] = count($failedPaths) . ' فایل در صف retry دفعه بعد قرار گرفت.';
|
||||
}
|
||||
|
||||
ftp_close($ftp);
|
||||
|
|
@ -391,6 +388,7 @@ private function pushFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
{
|
||||
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
|
||||
|
||||
$currentPaths = [];
|
||||
foreach ($changes as $change) {
|
||||
$data = $change['changed_data'] ?? [];
|
||||
foreach ($fileFields as $field) {
|
||||
|
|
@ -399,7 +397,20 @@ private function pushFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
}
|
||||
$files = is_array($data[$field]) ? $data[$field] : json_decode($data[$field], true) ?? [];
|
||||
foreach ($files as $filePath) {
|
||||
if (! $filePath || ! Storage::disk('public')->exists($filePath)) {
|
||||
if ($filePath) {
|
||||
$currentPaths[] = ltrim(str_replace('\\', '/', $filePath), '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pendingPaths = $this->getPendingFiles('c2s');
|
||||
$allPaths = array_values(array_unique(array_merge($pendingPaths, $currentPaths)));
|
||||
$failedPaths = [];
|
||||
|
||||
foreach ($allPaths as $filePath) {
|
||||
if (! Storage::disk('public')->exists($filePath)) {
|
||||
$report[] = "فایل [{$filePath}] در سیستم محلی یافت نشد ✗";
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
|
@ -412,12 +423,17 @@ private function pushFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
$report[] = "فایل [{$filePath}] ارسال شد (HTTP) ✓";
|
||||
} else {
|
||||
$report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $response->status();
|
||||
$failedPaths[] = $filePath;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $e->getMessage();
|
||||
$failedPaths[] = $filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->savePendingFiles('c2s', $failedPaths);
|
||||
if (! empty($failedPaths)) {
|
||||
$report[] = count($failedPaths) . ' فایل در صف retry دفعه بعد قرار گرفت.';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +441,7 @@ private function syncFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
{
|
||||
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
|
||||
|
||||
$currentPaths = [];
|
||||
foreach ($changes as $change) {
|
||||
$data = $change['changed_data'] ?? [];
|
||||
foreach ($fileFields as $field) {
|
||||
|
|
@ -433,7 +450,19 @@ private function syncFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
}
|
||||
$files = is_array($data[$field]) ? $data[$field] : json_decode($data[$field], true) ?? [];
|
||||
foreach ($files as $filePath) {
|
||||
if (! $filePath || Storage::disk('public')->exists($filePath)) {
|
||||
if ($filePath) {
|
||||
$currentPaths[] = ltrim(str_replace('\\', '/', $filePath), '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$pendingPaths = $this->getPendingFiles('s2c');
|
||||
$allPaths = array_values(array_unique(array_merge($pendingPaths, $currentPaths)));
|
||||
$failedPaths = [];
|
||||
|
||||
foreach ($allPaths as $filePath) {
|
||||
if (Storage::disk('public')->exists($filePath)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
|
@ -444,12 +473,19 @@ private function syncFilesViaHttp(array $changes, string $baseUrl, array &$repor
|
|||
if ($response->successful()) {
|
||||
Storage::disk('public')->put($filePath, $response->body());
|
||||
$report[] = "فایل [{$filePath}] دریافت شد (HTTP) ✓";
|
||||
} else {
|
||||
$report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $response->status();
|
||||
$failedPaths[] = $filePath;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
$report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $e->getMessage();
|
||||
$failedPaths[] = $filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->savePendingFiles('s2c', $failedPaths);
|
||||
if (! empty($failedPaths)) {
|
||||
$report[] = count($failedPaths) . ' فایل در صف retry دفعه بعد قرار گرفت.';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -484,6 +520,25 @@ private function applyChange(array $change, string $prefix, array &$report): voi
|
|||
}
|
||||
}
|
||||
|
||||
private function getPendingFiles(string $direction): array
|
||||
{
|
||||
$record = \App\Models\OsurgInitial::where('init_parameter', "sync_pending_{$direction}")->first();
|
||||
if (! $record || ! $record->attachment) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return json_decode($record->attachment, true) ?: [];
|
||||
}
|
||||
|
||||
private function savePendingFiles(string $direction, array $files): void
|
||||
{
|
||||
$files = array_values(array_unique(array_filter($files)));
|
||||
\App\Models\OsurgInitial::updateOrCreate(
|
||||
['init_parameter' => "sync_pending_{$direction}"],
|
||||
['attachment' => empty($files) ? null : json_encode($files, JSON_UNESCAPED_UNICODE)],
|
||||
);
|
||||
}
|
||||
|
||||
private function saveOurCursor(string $cursor): void
|
||||
{
|
||||
\App\Models\OsurgInitial::updateOrCreate(
|
||||
|
|
|
|||
Loading…
Reference in New Issue