tw: prevent re-index on aborted force
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/888/head
parent
46366d6715
commit
7cdced22c0
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace OCA\Memories\Db;
|
namespace OCA\Memories\Db;
|
||||||
|
|
||||||
|
use OCA\Memories\Util;
|
||||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
use OCP\IDBConnection;
|
use OCP\IDBConnection;
|
||||||
|
|
||||||
|
@ -14,15 +15,14 @@ trait TimelineWriteOrphans
|
||||||
/**
|
/**
|
||||||
* Mark all or some files in the table as (un)orphaned.
|
* Mark all or some files in the table as (un)orphaned.
|
||||||
*
|
*
|
||||||
* @param bool $value True to mark as orphaned, false to mark as un-orphaned
|
* @param bool $value True to mark as orphaned, false to mark as un-orphaned
|
||||||
* @param int[] $fileIds List of file IDs to mark, or empty to mark all files
|
* @param int[] $fileIds List of file IDs to mark, or empty to mark all files
|
||||||
* @param bool $onlyMain Only mark the main file, not the live photo
|
* @param bool $livephoto Also include live photos in the update
|
||||||
*
|
|
||||||
* @return int Number of rows affected
|
|
||||||
*/
|
*/
|
||||||
public function orphanAll(bool $value = true, ?array $fileIds = null, bool $onlyMain = false): int
|
public function orphanAll(bool $value = true, ?array $fileIds = null, bool $livephoto = true): void
|
||||||
{
|
{
|
||||||
$do = function (string $table) use ($value, $fileIds): int {
|
// Helper function to update a table.
|
||||||
|
$update = function (string $table) use ($value, $fileIds): int {
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
$query->update($table)
|
$query->update($table)
|
||||||
->set('orphan', $query->createNamedParameter($value, IQueryBuilder::PARAM_BOOL))
|
->set('orphan', $query->createNamedParameter($value, IQueryBuilder::PARAM_BOOL))
|
||||||
|
@ -35,13 +35,26 @@ trait TimelineWriteOrphans
|
||||||
return $query->executeStatement();
|
return $query->executeStatement();
|
||||||
};
|
};
|
||||||
|
|
||||||
$count = $do('memories');
|
// Mark all files as orphaned.
|
||||||
|
$update('memories');
|
||||||
|
|
||||||
if ($onlyMain) {
|
// Mark all live photos as orphaned.
|
||||||
return $count;
|
if ($livephoto) {
|
||||||
|
$update('memories_livephoto');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $count + $do('memories_livephoto');
|
// Unorphan all files on abort if we can
|
||||||
|
if ($value) {
|
||||||
|
Util::registerInterruptHandler('orphanAll', function () {
|
||||||
|
// If we are in a transaction, abort it.
|
||||||
|
if ($this->connection->inTransaction()) {
|
||||||
|
$this->connection->rollBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unorphan all files.
|
||||||
|
$this->orphanAll(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,7 +68,7 @@ trait TimelineWriteOrphans
|
||||||
{
|
{
|
||||||
// Orphan all files. This means if we are interrupted,
|
// Orphan all files. This means if we are interrupted,
|
||||||
// it will lead to a re-index of the whole library!
|
// it will lead to a re-index of the whole library!
|
||||||
$this->orphanAll(true, null, true);
|
$this->orphanAll(true, null, false);
|
||||||
|
|
||||||
while (\count($orphans = $this->getSomeOrphans($txnSize, $fields))) {
|
while (\count($orphans = $this->getSomeOrphans($txnSize, $fields))) {
|
||||||
$this->connection->beginTransaction();
|
$this->connection->beginTransaction();
|
||||||
|
@ -66,7 +79,7 @@ trait TimelineWriteOrphans
|
||||||
|
|
||||||
// Mark all files as not orphaned.
|
// Mark all files as not orphaned.
|
||||||
$fileIds = array_map(static fn ($row): int => (int) $row['fileid'], $orphans);
|
$fileIds = array_map(static fn ($row): int => (int) $row['fileid'], $orphans);
|
||||||
$this->orphanAll(false, $fileIds, true);
|
$this->orphanAll(false, $fileIds, false);
|
||||||
|
|
||||||
$this->connection->commit();
|
$this->connection->commit();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +91,7 @@ trait TimelineWriteOrphans
|
||||||
* @param int $count max number of rows to return
|
* @param int $count max number of rows to return
|
||||||
* @param string[] $fields list of fields to select
|
* @param string[] $fields list of fields to select
|
||||||
*/
|
*/
|
||||||
protected function getSomeOrphans(int $count, array $fields): array
|
private function getSomeOrphans(int $count, array $fields): array
|
||||||
{
|
{
|
||||||
$query = $this->connection->getQueryBuilder();
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
|
37
lib/Util.php
37
lib/Util.php
|
@ -391,4 +391,41 @@ class Util
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a signal handler with pcntl for SIGINT.
|
||||||
|
*/
|
||||||
|
public static function registerInterruptHandler(string $name, callable $callback): void
|
||||||
|
{
|
||||||
|
// Only register signal handlers in CLI mode
|
||||||
|
if (!\OC::$CLI || !\extension_loaded('pcntl')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register handler only once
|
||||||
|
static $handlers = [];
|
||||||
|
if ($handlers[$name] ?? null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is the first handler
|
||||||
|
$registered = \count($handlers) > 0;
|
||||||
|
|
||||||
|
// Register handler
|
||||||
|
$handlers[$name] = $callback;
|
||||||
|
|
||||||
|
// pcntl_signal is already registered
|
||||||
|
if ($registered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register handler
|
||||||
|
pcntl_signal(SIGINT, static function () use ($handlers): void {
|
||||||
|
foreach ($handlers as $handler) {
|
||||||
|
$handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue