From e4b3d4dd99a4b82b32494f582ccbaaf9eb644723 Mon Sep 17 00:00:00 2001 From: SajjadMahmoody <117562560+SajjadMahmoody@users.noreply.github.com> Date: Tue, 2 Jun 2026 01:58:55 +0330 Subject: [PATCH] fix: prevent sync timeout and memory issues for large patient batches --- app/Services/SyncService.php | 45 ++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/app/Services/SyncService.php b/app/Services/SyncService.php index 3862167..4f69df0 100644 --- a/app/Services/SyncService.php +++ b/app/Services/SyncService.php @@ -80,6 +80,7 @@ public function isFtpConfigured(): bool public function sync(): array { + set_time_limit(0); $report = []; $baseUrl = "http://{$this->peerIp}:{$this->peerPort}"; @@ -428,31 +429,38 @@ private function extractFilePaths(array $changes): array private function pushFilesViaHttp(array $changes, string $baseUrl, array &$report): void { $currentPaths = $this->extractFilePaths($changes); - $pendingPaths = $this->getPendingFiles('c2s'); $allPaths = array_values(array_unique(array_merge($pendingPaths, $currentPaths))); $failedPaths = []; foreach ($allPaths as $filePath) { - if (! Storage::disk('public')->exists($filePath)) { + $localPath = Storage::disk('public')->path($filePath); + + if (! file_exists($localPath)) { $report[] = "فایل [{$filePath}] در سیستم محلی یافت نشد ✗"; continue; } + + $stream = fopen($localPath, 'rb'); try { $response = Http::timeout(600) ->withHeader('X-Sync-Token', $this->token) - ->attach('file', Storage::disk('public')->get($filePath), basename($filePath)) + ->attach('file', $stream, basename($filePath)) ->post("{$baseUrl}/api/sync/receive-file", ['path' => $filePath]); if ($response->successful()) { $report[] = "فایل [{$filePath}] ارسال شد (HTTP) ✓"; } else { - $report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $response->status(); + $report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $response->status(); $failedPaths[] = $filePath; } } catch (\Throwable $e) { - $report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $e->getMessage(); + $report[] = "فایل [{$filePath}] ارسال نشد (HTTP) ✗ " . $e->getMessage(); $failedPaths[] = $filePath; + } finally { + if (is_resource($stream)) { + fclose($stream); + } } } @@ -464,30 +472,47 @@ private function pushFilesViaHttp(array $changes, string $baseUrl, array &$repor private function syncFilesViaHttp(array $changes, string $baseUrl, array &$report): void { + $localBase = rtrim(Storage::disk('public')->path(''), '/\\'); $currentPaths = $this->extractFilePaths($changes); - $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; + continue; } + + $localFile = $localBase . '/' . $filePath; + $partFile = $localFile . '.part'; + $localDir = dirname($localFile); + try { + if (! is_dir($localDir)) { + mkdir($localDir, 0755, true); + } + + if (file_exists($partFile)) { + @unlink($partFile); + } + $response = Http::timeout(60) ->withHeader('X-Sync-Token', $this->token) ->get("{$baseUrl}/api/sync/file", ['path' => $filePath]); if ($response->successful()) { - Storage::disk('public')->put($filePath, $response->body()); + file_put_contents($partFile, $response->body()); + rename($partFile, $localFile); $report[] = "فایل [{$filePath}] دریافت شد (HTTP) ✓"; } else { - $report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $response->status(); + $report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $response->status(); $failedPaths[] = $filePath; } } catch (\Throwable $e) { - $report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $e->getMessage(); + if (file_exists($partFile)) { + @unlink($partFile); + } + $report[] = "فایل [{$filePath}] دریافت نشد (HTTP) ✗ " . $e->getMessage(); $failedPaths[] = $filePath; } }