#123: The process command (which is now bt-queue:process to avoid conflicts with Laravel's default queue namespace) now uses the S3 storage to retrieve images

This commit is contained in:
Andy Heathershaw 2019-07-13 10:15:13 +01:00
parent 7a71a06e4e
commit 95e79f2d28
7 changed files with 133 additions and 13 deletions

View File

@ -20,6 +20,30 @@ class AmazonS3Source extends AlbumSourceBase implements IAlbumSource, IAnalysisQ
// The delete routine will have already removed all photos // The delete routine will have already removed all photos
} }
/**
* Deletes a photo to be analysed from the storage source
* @param string $queueToken Queue token holding the photo
* @param string $fileName Filename of the photo to download
* @return void
*/
public function deleteItemFromAnalysisQueue($queueToken, $fileName)
{
$fileToDelete = $this->getPathToAnalysisQueueItem($queueToken, $fileName);
try
{
$this->getClient()->deleteObject([
'Bucket' => $this->configuration->container_name,
'Key' => $fileToDelete
]);
}
catch (ClientErrorResponseException $ex)
{
// Don't worry if the file no longer exists
Log::warning('Failed deleting image from S3.', ['error' => $ex->getMessage(), 'path' => $fileToDelete]);
}
}
/** /**
* Deletes a thumbnail file for a photo. * Deletes a thumbnail file for a photo.
* @param Photo $photo Photo to delete the thumbnail from. * @param Photo $photo Photo to delete the thumbnail from.
@ -44,6 +68,25 @@ class AmazonS3Source extends AlbumSourceBase implements IAlbumSource, IAnalysisQ
} }
} }
/**
* Downloads a photo to be analysed from the storage source to a temporary file
* @param string $queueToken Queue token holding the photo
* @param string $fileName Filename of the photo to download
* @return string Path to the photo that was downloaded
*/
public function fetchItemFromAnalysisQueue($queueToken, $fileName)
{
$tempFile = tempnam(sys_get_temp_dir(), 'BlueTwilight_');
$this->getClient()->getObject([
'Bucket' => $this->configuration->container_name,
'Key' => $this->getPathToAnalysisQueueItem($queueToken, $fileName),
'SaveAs' => $tempFile
]);
return $tempFile;
}
/** /**
* Fetches the contents of a thumbnail for a photo. * Fetches the contents of a thumbnail for a photo.
* @param Photo $photo Photo to fetch the thumbnail for. * @param Photo $photo Photo to fetch the thumbnail for.
@ -155,6 +198,11 @@ class AmazonS3Source extends AlbumSourceBase implements IAlbumSource, IAnalysisQ
return sprintf('analysis-queue/%s', $queueToken); return sprintf('analysis-queue/%s', $queueToken);
} }
private function getPathToAnalysisQueueItem($queueToken, $fileName)
{
return sprintf('%s/%s', $this->getPathToAnalysisQueue($queueToken), $fileName);
}
private function getPathToPhoto(Photo $photo, $thumbnail = null) private function getPathToPhoto(Photo $photo, $thumbnail = null)
{ {
return sprintf( return sprintf(

View File

@ -6,6 +6,22 @@ use App\Storage;
interface IAnalysisQueueSource interface IAnalysisQueueSource
{ {
/**
* Deletes a photo to be analysed from the storage source
* @param string $queueToken Queue token holding the photo
* @param string $fileName Filename of the photo to download
* @return void
*/
function deleteItemFromAnalysisQueue($queueToken, $fileName);
/**
* Downloads a photo to be analysed from the storage source to a temporary file
* @param string $queueToken Queue token holding the photo
* @param string $fileName Filename of the photo to download
* @return string Path to the photo that was downloaded
*/
function fetchItemFromAnalysisQueue($queueToken, $fileName);
/** /**
* @param Storage $configuration * @param Storage $configuration
* @return mixed * @return mixed

View File

@ -2,6 +2,7 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Album;
use App\Facade\UserConfig; use App\Facade\UserConfig;
use App\Photo; use App\Photo;
use App\QueueItem; use App\QueueItem;
@ -10,6 +11,7 @@ use App\Services\RabbitMQService;
use App\User; use App\User;
use App\UserActivity; use App\UserActivity;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\App;
class ProcessQueueCommand extends Command class ProcessQueueCommand extends Command
{ {
@ -18,7 +20,7 @@ class ProcessQueueCommand extends Command
* *
* @var string * @var string
*/ */
protected $signature = 'queue:process'; protected $signature = 'bt-queue:process';
/** /**
* The console command description. * The console command description.
@ -181,21 +183,20 @@ class ProcessQueueCommand extends Command
switch (strtolower($action)) switch (strtolower($action))
{ {
/* This needs a bit more work - we need to also store the new album ID in the queue_items table */ /* This needs a bit more work - we need to also store the new album ID in the queue_items table */
/*case 'change_album': case 'change_album':
if ($user->can('change-metadata', $photo)) if ($user->can('change-metadata', $photo))
{ {
$newAlbumId = intval($request->get('new-album-id')); $newAlbum = Album::where('id', intval($queueItem->new_album_id))->first();
if ($newAlbumId == $photo->album_id) if (is_null($newAlbum) || !$user->can('upload-photos', $newAlbum))
{ {
// Photo already belongs to this album, don't move $this->output->writeln('Target album does not exist or user does not have permission.');
return; return;
} }
$newAlbum = $this->loadAlbum($newAlbumId, 'upload-photos'); $this->output->writeln(sprintf('Moving photo to album \'%s\'', $newAlbum->name));
$photoService->changeAlbum($newAlbum); $photoService->changeAlbum($newAlbum);
$changed = true;
} }
break;*/ break;
case 'delete': case 'delete':
if ($user->can('delete', $photo)) if ($user->can('delete', $photo))

View File

@ -601,6 +601,18 @@ class PhotoController extends Controller
'user_id' => $this->getUser()->id, 'user_id' => $this->getUser()->id,
'queued_at' => new \DateTime() 'queued_at' => new \DateTime()
]); ]);
if (strtolower($action) == 'change_album')
{
$queueItem->new_album_id = intval($request->get('new-album-id'));
$newAlbumId = intval($request->get('new-album-id'));
if ($newAlbumId == $photo->album_id)
{
// Photo already belongs to this album, don't move
continue;
}
}
$queueItem->save(); $queueItem->save();
$rabbitmq = new RabbitMQService(); $rabbitmq = new RabbitMQService();

View File

@ -4,6 +4,8 @@ namespace App\Services;
use App\Album; use App\Album;
use App\AlbumSources\IAlbumSource; use App\AlbumSources\IAlbumSource;
use App\AlbumSources\IAnalysisQueueSource;
use App\Helpers\AnalysisQueueHelper;
use App\Helpers\FileHelper; use App\Helpers\FileHelper;
use App\Helpers\ImageHelper; use App\Helpers\ImageHelper;
use App\Helpers\MiscHelper; use App\Helpers\MiscHelper;
@ -52,8 +54,10 @@ class PhotoService
public function analyse($queueToken, $isReanalyse = false) public function analyse($queueToken, $isReanalyse = false)
{ {
$queuePath = FileHelper::getQueuePath($queueToken); /** @var IAnalysisQueueSource $analysisQueueStorage */
$photoFile = join(DIRECTORY_SEPARATOR, [$queuePath, $this->photo->storage_file_name]); $analysisQueueStorage = AnalysisQueueHelper::getStorageQueueSource();
$photoFile = $analysisQueueStorage->fetchItemFromAnalysisQueue($queueToken, $this->photo->storage_file_name);
try try
{ {
@ -143,10 +147,11 @@ class PhotoService
} }
finally finally
{ {
// Remove the temporary file
@unlink($photoFile); @unlink($photoFile);
// If the queue directory is now empty, get rid of it // Remove from the storage
FileHelper::deleteIfEmpty($queuePath); $analysisQueueStorage->deleteItemFromAnalysisQueue($queueToken, $this->photo->storage_file_name);
} }
} }

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddNewAlbumIdColumn extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('user_activity', function (Blueprint $table)
{
$table->unsignedInteger('new_album_id')->nullable(true);
$table->foreign('new_album_id')
->references('id')->on('albums')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('user_activity', function (Blueprint $table)
{
$table->dropColumn('new_album_id');
});
}
}

View File

@ -3,7 +3,7 @@ Description=Blue Twilight Processing Queue Runner
[Service] [Service]
WorkingDirectory=/data/www/blue-twilight.andysh.dev/ WorkingDirectory=/data/www/blue-twilight.andysh.dev/
ExecStart=/usr/bin/php artisan queue:process ExecStart=/usr/bin/php artisan bt-queue:process
Restart=on-failure Restart=on-failure
User=www-data User=www-data
Group=www-data Group=www-data