Skip to content

Commit

Permalink
Potentially fixed #3197
Browse files Browse the repository at this point in the history
Signed-off-by: brandonkelly <[email protected]>
  • Loading branch information
brandonkelly committed Apr 3, 2019
1 parent f03b0e3 commit 79334a9
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG-v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Changed
- Changed the way Craft updates search indexes, to reduce the likelihood of a deadlock. ([#3197](https://github.com/craftcms/cms/issues/3197))

### Fixed
- Fixed a PHP error that could occur during asset indexing in some cases.

Expand Down
50 changes: 33 additions & 17 deletions src/services/Search.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use craft\helpers\Db;
use craft\helpers\Search as SearchHelper;
use craft\helpers\StringHelper;
use craft\models\Site;
use craft\search\SearchQuery;
use craft\search\SearchQueryTerm;
use craft\search\SearchQueryTermGroup;
Expand Down Expand Up @@ -268,26 +269,43 @@ public function filterElementIdsByQuery(array $elementIds, $query, bool $scoreRe
* @param int $elementId
* @param string $attribute
* @param string $fieldId
* @param int|null $siteId
* @param int $siteId
* @param string $dirtyKeywords
* @throws \craft\errors\SiteNotFoundException
*/
private function _indexElementKeywords(int $elementId, string $attribute, string $fieldId, int $siteId = null, string $dirtyKeywords)
private function _indexElementKeywords(int $elementId, string $attribute, string $fieldId, int $siteId, string $dirtyKeywords)
{
$attribute = strtolower($attribute);
$driver = Craft::$app->getDb()->getDriverName();

if ($siteId !== null) {
$site = Craft::$app->getSites()->getSiteById($siteId);
} else {
$site = Craft::$app->getSites()->getPrimarySite();
// Acquire a lock for this element/attribute/field ID/site ID
$mutex = Craft::$app->getMutex();
$lockKey = "searchindex:{$elementId}:{$attribute}:{$fieldId}:{$siteId}";

if (!$mutex->acquire($lockKey)) {
// Not worth waiting around; for all we know the other process has newer search attributes anyway
return;
}

// Drop all current rows for this element/attribute/site ID
$db = Craft::$app->getDb();
$db->createCommand()
->delete(Table::SEARCHINDEX, [
'elementId' => $elementId,
'attribute' => $attribute,
'fieldId' => $fieldId,
'siteId' => $siteId,
])
->execute();

$driver = $db->getDriverName();
/** @var Site $site */
$site = Craft::$app->getSites()->getSiteById($siteId);

// Clean 'em up
$cleanKeywords = SearchHelper::normalizeKeywords($dirtyKeywords, [], true, $site->language);

// Save 'em
$keyColumns = [
$columns = [
'elementId' => $elementId,
'attribute' => $attribute,
'fieldId' => $fieldId,
Expand All @@ -309,21 +327,19 @@ private function _indexElementKeywords(int $elementId, string $attribute, string
$cleanKeywords = $this->_truncateSearchIndexKeywords($cleanKeywords, $maxSize);
}

$keywordColumns = ['keywords' => $cleanKeywords];
$columns['keywords'] = $cleanKeywords;

if ($driver === DbConfig::DRIVER_PGSQL) {
$keywordColumns['keywords_vector'] = $cleanKeywords;
$columns['keywords_vector'] = $cleanKeywords;
}

// Insert/update the row in searchindex
Craft::$app->getDb()->createCommand()
->upsert(
Table::SEARCHINDEX,
$keyColumns,
$keywordColumns,
[],
false)
$db->createCommand()
->insert(Table::SEARCHINDEX, $columns, false)
->execute();

// Release the lock
$mutex->release($lockKey);
}

/**
Expand Down

0 comments on commit 79334a9

Please sign in to comment.