fix: delete patient files and clean pending queue on sync delete/update

This commit is contained in:
SajjadMahmoody 2026-06-02 02:30:58 +03:30
parent e4b3d4dd99
commit 4447002908
1 changed files with 159 additions and 0 deletions

View File

@ -84,6 +84,11 @@ public function sync(): array
$report = [];
$baseUrl = "http://{$this->peerIp}:{$this->peerPort}";
$pruned = $this->pruneOrphanedPending();
if ($pruned > 0) {
$report[] = "{$pruned} مسیر فایل یتیم از صف retry حذف شد.";
}
$healed = $this->healMissingFiles();
if ($healed > 0) {
$report[] = "{$healed} فایل گمشده شناسایی شد و در صف دریافت قرار گرفت.";
@ -534,6 +539,10 @@ private function applyChange(array $change, string $prefix, array &$report): voi
try {
if ($action === 'deleted') {
if ($table === 'patients') {
$this->deletePatientFilesFromDisk((int) $recordId);
$this->removePatientFilesFromPending((int) $recordId);
}
DB::table($table)->where('id', $recordId)->delete();
$report[] = "{$label} حذف ✓";
} elseif ($action === 'created') {
@ -546,6 +555,9 @@ private function applyChange(array $change, string $prefix, array &$report): voi
$report[] = "{$label} ایجاد ✓";
}
} elseif ($action === 'updated') {
if ($table === 'patients') {
$this->deleteRemovedPatientFiles((int) $recordId, $data);
}
DB::table($table)->where('id', $recordId)->update($this->sanitize($data));
$report[] = "{$label} بروزرسانی ✓";
}
@ -554,6 +566,153 @@ private function applyChange(array $change, string $prefix, array &$report): voi
}
}
private function deletePatientFilesFromDisk(int $patientId): void
{
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
$row = DB::table('patients')->find($patientId);
if (! $row) {
return;
}
foreach ($fileFields as $field) {
if (empty($row->$field)) {
continue;
}
$files = json_decode($row->$field, true) ?? [];
foreach ($files as $path) {
if (! empty($path)) {
Storage::disk('public')->delete(ltrim(str_replace('\\', '/', $path), '/'));
Log::info('sync: deleted patient file from disk', ['file' => $path, 'patient_id' => $patientId]);
}
}
}
}
private function removePatientFilesFromPending(int $patientId): void
{
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
$row = DB::table('patients')->find($patientId);
if (! $row) {
return;
}
$patientPaths = [];
foreach ($fileFields as $field) {
if (empty($row->$field)) {
continue;
}
$files = json_decode($row->$field, true) ?? [];
foreach ($files as $path) {
if (! empty($path)) {
$patientPaths[] = ltrim(str_replace('\\', '/', $path), '/');
}
}
}
if (empty($patientPaths)) {
return;
}
foreach (['s2c', 'c2s'] as $direction) {
$pending = $this->getPendingFiles($direction);
$cleaned = array_values(array_diff($pending, $patientPaths));
if (count($cleaned) !== count($pending)) {
$this->savePendingFiles($direction, $cleaned);
Log::info('sync: removed deleted patient files from pending', [
'patient_id' => $patientId,
'direction' => $direction,
'removed' => count($pending) - count($cleaned),
]);
}
}
}
private function deleteRemovedPatientFiles(int $patientId, array $newData): void
{
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
foreach ($fileFields as $field) {
if (! array_key_exists($field, $newData)) {
continue;
}
$row = DB::table('patients')->find($patientId);
if (! $row || empty($row->$field)) {
continue;
}
$oldFiles = json_decode($row->$field, true) ?? [];
$newRaw = $newData[$field];
$newFiles = is_array($newRaw) ? $newRaw : (json_decode($newRaw, true) ?? []);
$newFiles = array_map(fn($p) => ltrim(str_replace('\\', '/', $p), '/'), $newFiles);
$removed = array_diff(
array_map(fn($p) => ltrim(str_replace('\\', '/', $p), '/'), $oldFiles),
$newFiles,
);
foreach ($removed as $path) {
if (! empty($path)) {
Storage::disk('public')->delete($path);
Log::info('sync: deleted removed patient file from disk', ['file' => $path, 'patient_id' => $patientId]);
}
}
}
}
public function pruneOrphanedPending(): int
{
$referenced = $this->getAllReferencedFilePaths();
$pruned = 0;
foreach (['s2c', 'c2s'] as $direction) {
$pending = $this->getPendingFiles($direction);
if (empty($pending)) {
continue;
}
$valid = array_values(array_filter($pending, fn($p) => in_array($p, $referenced)));
$removed = count($pending) - count($valid);
if ($removed > 0) {
$this->savePendingFiles($direction, $valid);
$pruned += $removed;
Log::info("pruneOrphanedPending: {$removed} orphaned paths removed from {$direction} pending");
}
}
return $pruned;
}
private function getAllReferencedFilePaths(): array
{
$fileFields = ['photos_before', 'photos_after', 'videos', 'audio_files'];
$paths = [];
$rows = DB::table('patients')
->where(function ($q) use ($fileFields) {
foreach ($fileFields as $field) {
$q->orWhereNotNull($field);
}
})
->get($fileFields);
foreach ($rows as $row) {
foreach ($fileFields as $field) {
if (empty($row->$field)) {
continue;
}
$files = json_decode($row->$field, true) ?? [];
foreach ($files as $path) {
if ($path) {
$paths[] = ltrim(str_replace('\\', '/', $path), '/');
}
}
}
}
return array_unique($paths);
}
public function healMissingFiles(): int
{