fix: delete patient files and clean pending queue on sync delete/update
This commit is contained in:
parent
e4b3d4dd99
commit
4447002908
|
|
@ -84,6 +84,11 @@ public function sync(): array
|
||||||
$report = [];
|
$report = [];
|
||||||
$baseUrl = "http://{$this->peerIp}:{$this->peerPort}";
|
$baseUrl = "http://{$this->peerIp}:{$this->peerPort}";
|
||||||
|
|
||||||
|
$pruned = $this->pruneOrphanedPending();
|
||||||
|
if ($pruned > 0) {
|
||||||
|
$report[] = "{$pruned} مسیر فایل یتیم از صف retry حذف شد.";
|
||||||
|
}
|
||||||
|
|
||||||
$healed = $this->healMissingFiles();
|
$healed = $this->healMissingFiles();
|
||||||
if ($healed > 0) {
|
if ($healed > 0) {
|
||||||
$report[] = "{$healed} فایل گمشده شناسایی شد و در صف دریافت قرار گرفت.";
|
$report[] = "{$healed} فایل گمشده شناسایی شد و در صف دریافت قرار گرفت.";
|
||||||
|
|
@ -534,6 +539,10 @@ private function applyChange(array $change, string $prefix, array &$report): voi
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($action === 'deleted') {
|
if ($action === 'deleted') {
|
||||||
|
if ($table === 'patients') {
|
||||||
|
$this->deletePatientFilesFromDisk((int) $recordId);
|
||||||
|
$this->removePatientFilesFromPending((int) $recordId);
|
||||||
|
}
|
||||||
DB::table($table)->where('id', $recordId)->delete();
|
DB::table($table)->where('id', $recordId)->delete();
|
||||||
$report[] = "{$label} حذف ✓";
|
$report[] = "{$label} حذف ✓";
|
||||||
} elseif ($action === 'created') {
|
} elseif ($action === 'created') {
|
||||||
|
|
@ -546,6 +555,9 @@ private function applyChange(array $change, string $prefix, array &$report): voi
|
||||||
$report[] = "{$label} ایجاد ✓";
|
$report[] = "{$label} ایجاد ✓";
|
||||||
}
|
}
|
||||||
} elseif ($action === 'updated') {
|
} elseif ($action === 'updated') {
|
||||||
|
if ($table === 'patients') {
|
||||||
|
$this->deleteRemovedPatientFiles((int) $recordId, $data);
|
||||||
|
}
|
||||||
DB::table($table)->where('id', $recordId)->update($this->sanitize($data));
|
DB::table($table)->where('id', $recordId)->update($this->sanitize($data));
|
||||||
$report[] = "{$label} بروزرسانی ✓";
|
$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
|
public function healMissingFiles(): int
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue