WIP: storage-fix-local-nas work before playlist controls feature
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
6b3ab5b65e
commit
c160242dbc
46 files changed
+5365
-815
No files matched your search
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Models\Video;
|
||||
use App\Services\NasSyncService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class NasToLocalMigrationJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public int $tries = 1;
|
||||
public int $timeout = 7200; // 2 hours
|
||||
|
||||
private function updateProgress(array $data): void
|
||||
{
|
||||
Cache::put('nas_disable_progress', json_encode($data), 3600);
|
||||
}
|
||||
|
||||
public function handle(NasSyncService $nas): void
|
||||
{
|
||||
$progress = [
|
||||
'current' => 0,
|
||||
'total' => 0,
|
||||
'phase' => 'Counting files...',
|
||||
'done' => false,
|
||||
'error' => null,
|
||||
];
|
||||
$this->updateProgress($progress);
|
||||
|
||||
try {
|
||||
// ── Count all items ───────────────────────────────────────────────
|
||||
$videos = Video::where('path', 'like', 'users/%')->get();
|
||||
|
||||
$slides = \DB::table('video_slides')
|
||||
->where('filename', 'like', 'users/%')
|
||||
->get();
|
||||
|
||||
$usersWithAvatar = User::where('avatar', 'like', 'users/%')->get();
|
||||
$usersWithBanner = User::where('banner', 'like', 'users/%')->get();
|
||||
|
||||
$postImages = \DB::table('post_images')
|
||||
->where('filename', 'like', 'users/%')
|
||||
->get();
|
||||
|
||||
// Count thumbnails separately (they're additional per-video downloads)
|
||||
$videoThumbs = $videos->filter(fn($v) => $v->thumbnail && str_starts_with($v->thumbnail, 'users/'));
|
||||
|
||||
$total = $videos->count()
|
||||
+ $videoThumbs->count()
|
||||
+ $slides->count()
|
||||
+ $usersWithAvatar->count()
|
||||
+ $usersWithBanner->count()
|
||||
+ $postImages->count();
|
||||
|
||||
$progress['total'] = $total;
|
||||
$progress['phase'] = 'Downloading files from NAS...';
|
||||
$this->updateProgress($progress);
|
||||
|
||||
// ── Download videos ───────────────────────────────────────────────
|
||||
foreach ($videos as $video) {
|
||||
$nasPath = $video->path;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download video #' . $video->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading videos... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Download thumbnails ───────────────────────────────────────────
|
||||
foreach ($videoThumbs as $video) {
|
||||
$nasPath = $video->thumbnail;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download thumbnail for video #' . $video->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading thumbnails... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Download slides ───────────────────────────────────────────────
|
||||
foreach ($slides as $slide) {
|
||||
$nasPath = $slide->filename;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download slide id=' . $slide->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading audio slides... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Download user avatars ─────────────────────────────────────────
|
||||
foreach ($usersWithAvatar as $user) {
|
||||
$nasPath = $user->avatar;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download avatar for user #' . $user->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading avatars... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Download user banners ─────────────────────────────────────────
|
||||
foreach ($usersWithBanner as $user) {
|
||||
$nasPath = $user->banner;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download banner for user #' . $user->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading banners... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Download post images ──────────────────────────────────────────
|
||||
foreach ($postImages as $img) {
|
||||
$nasPath = $img->filename;
|
||||
$localPath = storage_path('app/' . $nasPath);
|
||||
|
||||
try {
|
||||
$nas->ensureLocalAsset($localPath, $nasPath);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: failed to download post image id=' . $img->id . ' path=' . $nasPath . ': ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$progress['current']++;
|
||||
$progress['phase'] = 'Downloading post images... (' . $progress['current'] . '/' . $total . ')';
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
|
||||
// ── Disable NAS ───────────────────────────────────────────────────
|
||||
Setting::set('nas_sync_enabled', 'false');
|
||||
|
||||
$progress['done'] = true;
|
||||
$progress['phase'] = 'Complete';
|
||||
$this->updateProgress($progress);
|
||||
|
||||
Log::info('NasToLocalMigrationJob: completed. ' . $total . ' files migrated. NAS disabled.');
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('NasToLocalMigrationJob: fatal error: ' . $e->getMessage(), [
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
$progress['error'] = $e->getMessage();
|
||||
$this->updateProgress($progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user