tw: acquire lock before processing
Signed-off-by: Varun Patil <varunpatil@ucla.edu>pull/579/head
parent
039115d8f4
commit
9f62a23895
|
@ -9,6 +9,7 @@ use OCA\Memories\Service\Index;
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\Files\File;
|
use OCP\Files\File;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
|
use OCP\Lock\ILockingProvider;
|
||||||
|
|
||||||
require_once __DIR__.'/../ExifFields.php';
|
require_once __DIR__.'/../ExifFields.php';
|
||||||
|
|
||||||
|
@ -22,28 +23,54 @@ class TimelineWrite
|
||||||
use TimelineWritePlaces;
|
use TimelineWritePlaces;
|
||||||
protected IDBConnection $connection;
|
protected IDBConnection $connection;
|
||||||
protected LivePhoto $livePhoto;
|
protected LivePhoto $livePhoto;
|
||||||
|
protected ILockingProvider $lockingProvider;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IDBConnection $connection,
|
IDBConnection $connection,
|
||||||
LivePhoto $livePhoto
|
LivePhoto $livePhoto,
|
||||||
|
ILockingProvider $lockingProvider
|
||||||
) {
|
) {
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
$this->livePhoto = $livePhoto;
|
$this->livePhoto = $livePhoto;
|
||||||
|
$this->lockingProvider = $lockingProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a file to insert Exif data into the database.
|
* Process a file to insert Exif data into the database.
|
||||||
*
|
*
|
||||||
* @param File $file File node to process
|
* @param File $file File node to process
|
||||||
|
* @param bool $lock Lock the file before processing
|
||||||
* @param bool $force Update the record even if the file has not changed
|
* @param bool $force Update the record even if the file has not changed
|
||||||
|
*
|
||||||
|
* @return bool True if the file was processed
|
||||||
|
*
|
||||||
|
* @throws \OCP\Lock\LockedException If the file is locked
|
||||||
|
* @throws \OCP\DB\Exception If the database query fails
|
||||||
*/
|
*/
|
||||||
public function processFile(File $file, bool $force = false): bool
|
public function processFile(
|
||||||
{
|
File $file,
|
||||||
|
bool $lock = true,
|
||||||
|
bool $force = false
|
||||||
|
): bool {
|
||||||
// Check if we want to process this file
|
// Check if we want to process this file
|
||||||
if (!Index::isSupported($file)) {
|
if (!Index::isSupported($file)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if we need to lock the file
|
||||||
|
if ($lock) {
|
||||||
|
$lockKey = 'memories/'.$file->getId();
|
||||||
|
$lockType = ILockingProvider::LOCK_EXCLUSIVE;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->lockingProvider->acquireLock($lockKey, $lockType);
|
||||||
|
|
||||||
|
return $this->processFile($file, false, $force);
|
||||||
|
} finally {
|
||||||
|
$this->lockingProvider->releaseLock($lockKey, $lockType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get parameters
|
// Get parameters
|
||||||
$mtime = $file->getMtime();
|
$mtime = $file->getMtime();
|
||||||
$fileId = $file->getId();
|
$fileId = $file->getId();
|
||||||
|
|
|
@ -27,14 +27,19 @@ use OCP\EventDispatcher\Event;
|
||||||
use OCP\EventDispatcher\IEventListener;
|
use OCP\EventDispatcher\IEventListener;
|
||||||
use OCP\Files\Events\Node\NodeTouchedEvent;
|
use OCP\Files\Events\Node\NodeTouchedEvent;
|
||||||
use OCP\Files\Events\Node\NodeWrittenEvent;
|
use OCP\Files\Events\Node\NodeWrittenEvent;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
class PostWriteListener implements IEventListener
|
class PostWriteListener implements IEventListener
|
||||||
{
|
{
|
||||||
private TimelineWrite $timelineWrite;
|
private TimelineWrite $timelineWrite;
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
public function __construct(TimelineWrite $timelineWrite)
|
public function __construct(
|
||||||
{
|
TimelineWrite $timelineWrite,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
$this->timelineWrite = $timelineWrite;
|
$this->timelineWrite = $timelineWrite;
|
||||||
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(Event $event): void
|
public function handle(Event $event): void
|
||||||
|
@ -64,6 +69,12 @@ class PostWriteListener implements IEventListener
|
||||||
// and getParent() is called on it.
|
// and getParent() is called on it.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$this->timelineWrite->processFile($node);
|
$this->timelineWrite->processFile($node);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$this->logger->error('Memories failed to process file: {message}', [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,11 +185,15 @@ class Index
|
||||||
*/
|
*/
|
||||||
public function indexFile(File $file): void
|
public function indexFile(File $file): void
|
||||||
{
|
{
|
||||||
|
$path = $file->getPath();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->log("Indexing file {$file->getPath()}", true);
|
$this->log("Indexing file {$path}", true);
|
||||||
$this->timelineWrite->processFile($file);
|
$this->timelineWrite->processFile($file);
|
||||||
|
} catch (\OCP\Lock\LockedException $e) {
|
||||||
|
$this->log("Skipping file {$path} due to lock\n", true);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$this->error("Failed to index file {$file->getPath()}: {$e->getMessage()}");
|
$this->error("Failed to index file {$path}: {$e->getMessage()}");
|
||||||
} finally {
|
} finally {
|
||||||
$this->tempManager->clean();
|
$this->tempManager->clean();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue