Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117910352
D3490.1775396793.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None
D3490.1775396793.diff
View Options
diff --git a/src/app/Backends/Storage.php b/src/app/Backends/Storage.php
--- a/src/app/Backends/Storage.php
+++ b/src/app/Backends/Storage.php
@@ -33,7 +33,25 @@
$disk->deleteDirectory($path);
- $file->chunks()->delete();
+ $file->forceDelete();
+ }
+
+ /**
+ * Delete a file chunk.
+ *
+ * @param \App\Fs\Chunk $chunk File chunk object
+ *
+ * @throws \Exception
+ */
+ public static function fileChunkDelete(Chunk $chunk): void
+ {
+ $disk = LaravelStorage::disk('files');
+
+ $path = self::chunkLocation($chunk->chunk_id, $chunk->item);
+
+ $disk->delete($path);
+
+ $chunk->forceDelete();
}
/**
diff --git a/src/app/Console/Commands/Fs/ExpungeCommand.php b/src/app/Console/Commands/Fs/ExpungeCommand.php
new file mode 100644
--- /dev/null
+++ b/src/app/Console/Commands/Fs/ExpungeCommand.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace App\Console\Commands\Fs;
+
+use App\Backends\Storage;
+use App\Console\Command;
+use App\Fs\Chunk;
+use App\Fs\Item;
+
+class ExpungeCommand extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'fs:expunge';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Remove deleted files and file chunks';
+
+ /**
+ * Execute the console command.
+ *
+ * @return mixed
+ */
+ public function handle()
+ {
+ // We remove deleted files as soon as they were deleted
+ // It should be done before dealing with orpahned chunks below
+ $files = Item::withTrashed()
+ ->where('type', '&', Item::TYPE_FILE)
+ ->whereNotNull('deleted_at')
+ ->orderBy('deleted_at')
+ ->cursor();
+
+ // FIXME: Should we use an async job for each file?
+
+ foreach ($files as $file) {
+ Storage::fileDelete($file);
+ }
+
+ // We remove orphaned chunks after upload ttl (while marked as deleted some chunks may still be
+ // in the process of uploading a file).
+ $chunks = Chunk::withTrashed()
+ ->where('deleted_at', '<', now()->subSeconds(Storage::UPLOAD_TTL))
+ ->orderBy('deleted_at')
+ ->cursor();
+
+ // FIXME: Should we use an async job for each chunk?
+
+ foreach ($chunks as $chunk) {
+ Storage::fileChunkDelete($chunk);
+ }
+ }
+}
diff --git a/src/app/Console/Kernel.php b/src/app/Console/Kernel.php
--- a/src/app/Console/Kernel.php
+++ b/src/app/Console/Kernel.php
@@ -28,6 +28,9 @@
// this is a laravel 8-ism
//$schedule->command('wallet:charge')->everyFourHours();
+
+ // This command removes deleted storage files/file chunks from the filesystem
+ $schedule->command('fs:expunge')->hourly();
}
/**
diff --git a/src/app/Http/Controllers/API/V4/FilesController.php b/src/app/Http/Controllers/API/V4/FilesController.php
--- a/src/app/Http/Controllers/API/V4/FilesController.php
+++ b/src/app/Http/Controllers/API/V4/FilesController.php
@@ -41,12 +41,8 @@
return $this->errorResponse($file);
}
- // FIXME: Here we're just deleting the file, but maybe it would be better/faster
- // to mark the file (record in db) as deleted and invoke a job to
- // delete it asynchronously?
-
- Storage::fileDelete($file);
-
+ // Here we're just marking the file as deleted, it will be removed from the
+ // storage later with the fs:expunge command
$file->delete();
return response()->json([
diff --git a/src/resources/vue/File/List.vue b/src/resources/vue/File/List.vue
--- a/src/resources/vue/File/List.vue
+++ b/src/resources/vue/File/List.vue
@@ -23,7 +23,7 @@
<tbody>
<tr v-for="file in files" :key="file.id" @click="$root.clickRecord">
<td class="name">
- <svg-icon icon="file" :title="file.mimetype"></svg-icon>
+ <svg-icon icon="file"></svg-icon>
<router-link :to="{ path: 'file/' + file.id }">{{ file.name }}</router-link>
</td>
<td class="buttons">
diff --git a/src/tests/Feature/Controller/FilesTest.php b/src/tests/Feature/Controller/FilesTest.php
--- a/src/tests/Feature/Controller/FilesTest.php
+++ b/src/tests/Feature/Controller/FilesTest.php
@@ -65,27 +65,9 @@
$this->assertSame('success', $json['status']);
$this->assertSame("File deleted successfully.", $json['message']);
-
- // Test that the file has been removed from the filesystem?
- $disk = LaravelStorage::disk('files');
- $this->assertFalse($disk->directoryExists($file->path . '/' . $file->id));
$this->assertSame(null, Item::find($file->id));
- // Test deletion of a chunked file
- $file = $this->getTestFile($john, 'test.txt', ['T1', 'T2']);
-
- $response = $this->actingAs($john)->delete("api/v4/files/{$file->id}");
- $response->assertStatus(200);
-
- $json = $response->json();
-
- $this->assertSame('success', $json['status']);
- $this->assertSame("File deleted successfully.", $json['message']);
-
- // Test that the file has been removed from the filesystem?
- $disk = LaravelStorage::disk('files');
- $this->assertFalse($disk->directoryExists($file->path . '/' . $file->id));
- $this->assertSame(null, Item::find($file->id));
+ // Note: The file is expected to stay still in the filesystem, we're not testing this here.
// TODO: Test acting as another user with permissions
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Apr 5, 1:46 PM (1 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18833579
Default Alt Text
D3490.1775396793.diff (5 KB)
Attached To
Mode
D3490: fs:expunge command
Attached
Detach File
Event Timeline