Skip to content

Commit e1b1377

Browse files
committed
fix(FsActionService): Pass userId to bg job to allow finding nodes via user folder
plus make sure to tear down fs in between action processing to prevent OOM Signed-off-by: Marcel Klehr <[email protected]>
1 parent 8684d31 commit e1b1377

File tree

5 files changed

+44
-9
lines changed

5 files changed

+44
-9
lines changed

lib/Db/FsActionMapper.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,19 @@ public function insertAccessUpdate(int $storageId, int $rootId): Entity {
180180
/**
181181
* @param int $storageId
182182
* @param int $rootId
183+
* @param string $userId
183184
* @return FsCreation|FsDeletion|FsMove|FsAccessUpdate
184185
* @throws Exception
185186
* @throws MultipleObjectsReturnedException
186187
*/
187-
public function insertCreation(int $storageId, int $rootId): Entity {
188+
public function insertCreation(int $storageId, int $rootId, string $userId): Entity {
188189
try {
189190
$creation = $this->findByStorageIdAndRootId(FsCreation::class, $storageId, $rootId);
190191
} catch (DoesNotExistException $e) {
191192
$creation = new FsCreation();
192193
$creation->setStorageId($storageId);
193194
$creation->setRootId($rootId);
195+
$creation->setUserId($userId);
194196
$this->insert($creation);
195197
$arguments = [ 'type' => FsCreation::class, 'storage_id' => $storageId ];
196198
if (!$this->jobList->has(ProcessFsActionsJob::class, $arguments)) {

lib/Db/FsCreation.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@
1717
* @method setStorageId(int $storageId)
1818
* @method int getRootId()
1919
* @method setRootId(int $rootId)
20+
* @method string getUserId()
21+
* @method setUserId(string $userId)
2022
*/
2123
final class FsCreation extends Entity {
2224
protected ?int $storageId = null;
2325
protected ?int $rootId = null;
26+
protected ?string $userId = null;
2427

2528
/**
2629
* @var string[]
2730
*/
28-
public static array $columns = ['id', 'storage_id', 'root_id'];
31+
public static array $columns = ['id', 'storage_id', 'root_id', 'user_id'];
2932

3033
/**
3134
* @var string[]
3235
*/
33-
public static array $fields = ['id', 'storageId', 'rootId'];
36+
public static array $fields = ['id', 'storageId', 'rootId', 'userId'];
3437

3538
public static string $tableName = 'recognize_fs_creations';
3639

@@ -39,5 +42,6 @@ public function __construct() {
3942
$this->addType('id', 'integer');
4043
$this->addType('storageId', 'integer');
4144
$this->addType('rootId', 'integer');
45+
$this->addType('userId', 'string');
4246
}
4347
}

lib/Hooks/FileListener.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ public function handle(Event $event): void {
195195
return;
196196
}
197197
if ($event instanceof CacheEntryInsertedEvent) {
198-
$node = current($this->rootFolder->getById($event->getFileId()));
199-
if ($node === false) {
198+
$node = $this->rootFolder->getFirstNodeById($event->getFileId());
199+
if ($node === null) {
200200
return;
201201
}
202202
if ($node instanceof Folder) {
@@ -214,8 +214,8 @@ public function handle(Event $event): void {
214214
if ($cacheEntry === false) {
215215
return;
216216
}
217-
$node = current($this->rootFolder->getById($cacheEntry->getId()));
218-
if ($node === false) {
217+
$node = $this->rootFolder->getFirstNodeById($cacheEntry->getId());
218+
if ($node === null) {
219219
return;
220220
}
221221
if (in_array($node->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true)) {
@@ -269,7 +269,12 @@ public function postInsert(Node $node, bool $recurse = true, ?array $mimeTypes =
269269
if (preg_match('#^/[^/]*?/files($|/)#', $node->getPath()) !== 1 && preg_match('#^/groupfolders/#', $node->getPath()) !== 1) {
270270
return;
271271
}
272-
$this->fsActionMapper->insertCreation($storageId, $node->getId());
272+
$owner = $node->getOwner();
273+
if ($owner === null) {
274+
$this->logger->info('Node has no owner: ' . $node->getPath() . ' - Ignoring.');
275+
return;
276+
}
277+
$this->fsActionMapper->insertCreation($storageId, $node->getId(), $owner->getUID());
273278
}
274279

275280
/**

lib/Migration/Version011000001Date20251215094821.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function changeSchema(IOutput $output, Closure $schemaClosure, array $opt
4343
$table->addColumn('id', Types::BIGINT, ['autoincrement' => true]);
4444
$table->addColumn('storage_id', Types::BIGINT, ['notnull' => true]);
4545
$table->addColumn('root_id', Types::BIGINT, ['notnull' => true]);
46+
$table->addColumn('user_id', Types::STRING, ['notnull' => true]);
4647
$table->setPrimaryKey(['id'], 'recognize_fs_cr_pk');
4748
$table->addUniqueIndex(['storage_id', 'root_id'], 'recognize_fs_cr_unique');
4849
$changed = true;

lib/Service/FsActionService.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace OCA\Recognize\Service;
44

5+
use OC\Files\SetupManager;
6+
use OC\User\NoUserException;
57
use OCA\Recognize\BackgroundJobs\ClusterFacesJob;
68
use OCA\Recognize\Classifiers\Audio\MusicnnClassifier;
79
use OCA\Recognize\Classifiers\Images\ClusteringFaceClassifier;
@@ -25,6 +27,7 @@
2527
use OCP\Files\IRootFolder;
2628
use OCP\Files\Node;
2729
use OCP\Files\NotFoundException;
30+
use OCP\Files\NotPermittedException;
2831
use Psr\Log\LoggerInterface;
2932

3033
final class FsActionService {
@@ -72,10 +75,25 @@ public function processActionsByClass(string $className): void {
7275
* @param array<FsCreation|FsDeletion|FsMove|FsAccessUpdate> $actions
7376
*/
7477
public function processActions(array $actions): void {
78+
$lastUserId = null;
7579
foreach ($actions as $action) {
7680
switch ($action::class) {
7781
case FsCreation::class:
78-
$rootNode = $this->rootFolder->getFirstNodeById($action->getRootId());
82+
$this->logger->debug('Processing FsCreation action for storageId ' . $action->getStorageId() . ' and rootId ' . $action->getRootId());
83+
// Tear down to avoid memory leaks and OOMs
84+
// The fs event table is sorted by user ID, so we only need to tear down when the user ID changes
85+
$actionUserId = $action->getUserId();
86+
if ($actionUserId !== $lastUserId) {
87+
$lastUserId = $actionUserId;
88+
$setupManager = \OCP\Server::get(SetupManager::class);
89+
$setupManager->tearDown();
90+
}
91+
try {
92+
$rootNode = $this->rootFolder->getUserFolder($actionUserId)->getFirstNodeById($action->getRootId());
93+
} catch (NotPermittedException|NoUserException $e) {
94+
$this->logger->warning('Failed to find root node for creation action: ' . $e->getMessage(), ['exception' => $e]);
95+
break;
96+
}
7997
if ($rootNode === null) {
8098
$this->logger->info('Failed to find root node for creation action', ['nodeId' => $action->getRootId(), 'storageId' => $action->getStorageId()]);
8199
break;
@@ -88,16 +106,19 @@ public function processActions(array $actions): void {
88106
break;
89107

90108
case FsDeletion::class:
109+
$this->logger->debug('Processing FsDeletion action for nodeId ' . $action->getNodeId());
91110
$this->onDeletion($action->getNodeId()); // todo add mimetypes filter here
92111
break;
93112
case FsAccessUpdate::class:
113+
$this->logger->debug('Processing FsAccessUpdate action for storageId ' . $action->getStorageId() . ' and rootId ' . $action->getRootId());
94114
try {
95115
$this->onAccessUpdate($action->getStorageId(), $action->getRootId());
96116
} catch (Exception|InvalidPathException|NotFoundException $e) {
97117
$this->logger->warning('Failed to process access update action: ' . $e->getMessage() . ' Continuing.', ['exception' => $e]);
98118
}
99119
break;
100120
case FsMove::class:
121+
$this->logger->debug('Processing FsMove action for nodeId ' . $action->getNodeId());
101122
$node = $this->rootFolder->getFirstNodeById($action->getNodeId());
102123
if ($node === null) {
103124
$this->logger->info('Failed to find root node for move action', ['nodeId' => $action->getNodeId()]);
@@ -202,12 +223,14 @@ public function onCreation(Node $node, bool $recurse = true, ?array $mimeTypes =
202223
$queueFile = new QueueFile();
203224
$storageId = $node->getMountPoint()->getNumericStorageId();
204225
if ($storageId === null) {
226+
$this->logger->debug('Storage ID is null for node ' . $node->getId());
205227
return;
206228
}
207229
$queueFile->setStorageId($storageId);
208230
$queueFile->setRootId($node->getMountPoint()->getStorageRootId());
209231

210232
if ($this->isFileIgnored($node)) {
233+
$this->logger->debug('File ignored, skipping: ' . $node->getId());
211234
return;
212235
}
213236

0 commit comments

Comments
 (0)