Skip to content

Commit

Permalink
prevent infinitely calling processIndexSession when assetindexdata is…
Browse files Browse the repository at this point in the history
… empty
  • Loading branch information
i-just committed Jan 15, 2025
1 parent 67d005e commit a1dbefd
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/controllers/AssetIndexesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ public function actionProcessIndexingSession(): Response
if (!$indexingSession->actionRequired) {
$indexingSession = $assetIndexer->processIndexSession($indexingSession);

if ($indexingSession->forceStop) {
$assetIndexer->stopIndexingSession($indexingSession);
return $this->asFailure(data: [
'stop' => $sessionId,
'message' => Craft::t('app', 'There was an issue indexing assets.'),
]);
}

// If action is now required, we just processed the last entry
// To save a round-trip, just pull the session review data
if ($indexingSession->actionRequired) {
Expand Down
6 changes: 6 additions & 0 deletions src/models/AssetIndexingSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,10 @@ class AssetIndexingSession extends Model
* @since 4.4.0
*/
public bool $processIfRootEmpty = false;

/**
* @var bool Whether we should stop processing the session because there was a problem.
* @since 4.14.0
*/
public bool $forceStop = false;
}
20 changes: 20 additions & 0 deletions src/services/AssetIndexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,26 @@ public function processIndexSession(AssetIndexingSession $indexingSession): Asse

// The most likely scenario is that the last entry is being worked on.
if (!$indexEntry && !$indexingSession->processIfRootEmpty) {
// if indexEntry is null here, we should also check if there's anything in the assetindexdata table at all
// (if not, it could have been deleted when clearing caches)
// if that table is empty, we'll get into an infinite loop, calling processIndexSession with the same data all the time
// (and it'll be very hard to discard the session via ui)
if ($indexingSession->processedEntries < $indexingSession->totalEntries) {
$count = (new Query())
->from([Table::ASSETINDEXDATA])
->where([
'sessionId' => $indexingSession->id,
'completed' => false,
'inProgress' => false,
])
->count();

if ((int)$count === 0) {
Craft::warning('The assetindexdata table is empty; Can’t proceed with indexing.');
$indexingSession->forceStop = true;
}
}

$mutex->release($lockName);
return $indexingSession;
}
Expand Down

0 comments on commit a1dbefd

Please sign in to comment.