-
Notifications
You must be signed in to change notification settings - Fork 6
fix: make the content providers queue unique #230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
13fe836
f4af7b7
2b5663e
eb9ef30
bdbf202
0fb6180
cb76595
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| /** | ||
| * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| namespace OCA\ContextChat\Migration; | ||
|
|
||
| use Closure; | ||
| use OCP\DB\ISchemaWrapper; | ||
| use OCP\Migration\IOutput; | ||
| use OCP\Migration\SimpleMigrationStep; | ||
| use Override; | ||
|
|
||
| class Version005003002Date20260320093626 extends SimpleMigrationStep { | ||
| /** | ||
| * @param IOutput $output | ||
| * @param Closure(): ISchemaWrapper $schemaClosure | ||
| * @param array $options | ||
| * @return null|ISchemaWrapper | ||
| */ | ||
| #[Override] | ||
| public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { | ||
| /** @var ISchemaWrapper $schema */ | ||
| $schema = $schemaClosure(); | ||
| $schemaChanged = false; | ||
|
|
||
| if ($schema->hasTable('context_chat_content_queue')) { | ||
| $table = $schema->getTable('context_chat_content_queue'); | ||
| $appIdCol = $table->getColumn('app_id'); | ||
| if ($appIdCol->getLength() !== 32) { | ||
| // appId has the same length in other tables like oc_appconfig | ||
| $appIdCol->setLength(32); | ||
| $schemaChanged = true; | ||
| } | ||
|
|
||
| $providerIdCol = $table->getColumn('provider_id'); | ||
| if ($providerIdCol->getLength() !== 63) { | ||
| // limit length of provider id, almost double of appId length | ||
| // 63 instead of 64 to avoid extra byte in utf8mb4 from varchar's length overhead | ||
| $providerIdCol->setLength(63); | ||
| $schemaChanged = true; | ||
| } | ||
|
|
||
| $itemIdCol = $table->getColumn('item_id'); | ||
| // max length of item id so far is in mail at 41 bytes "bigint:bigint" | ||
| // for bigint ids converted to string 20 should be enough | ||
| if ($itemIdCol->getLength() !== 63) { | ||
| $itemIdCol->setLength(63); | ||
| $schemaChanged = true; | ||
| } | ||
| } | ||
|
|
||
| return $schemaChanged ? $schema : null; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| /** | ||
| * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| namespace OCA\ContextChat\Migration; | ||
|
|
||
| use Closure; | ||
| use OCP\DB\ISchemaWrapper; | ||
| use OCP\IDBConnection; | ||
| use OCP\Migration\IOutput; | ||
| use OCP\Migration\SimpleMigrationStep; | ||
| use Override; | ||
|
|
||
| class Version005003002Date20260320093628 extends SimpleMigrationStep { | ||
| public function __construct( | ||
| private IDBConnection $db, | ||
| ) { | ||
| } | ||
|
|
||
| /** | ||
| * @param IOutput $output | ||
| * @param Closure(): ISchemaWrapper $schemaClosure | ||
| * @param array $options | ||
| * @return null|ISchemaWrapper | ||
| */ | ||
| #[Override] | ||
| public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options) { | ||
| /** @var ISchemaWrapper $schema */ | ||
| $schema = $schemaClosure(); | ||
|
|
||
| if (!$schema->hasTable('context_chat_content_queue')) { | ||
| $output->info('Table context_chat_content_queue does not exist, skipping de-duplication.'); | ||
| return; | ||
| } | ||
|
|
||
| $totalRowsDeleted = 0; | ||
| $qb = $this->db->getQueryBuilder(); | ||
| $qb->select('app_id', 'provider_id', 'item_id') | ||
| ->selectAlias($qb->func()->count('*'), 'count') | ||
| ->selectAlias($qb->func()->max('id'), 'keep_id') | ||
| ->from('context_chat_content_queue') | ||
| ->groupBy('app_id', 'provider_id', 'item_id') | ||
| ->having($qb->expr()->gt('count', $qb->createNamedParameter(1))); | ||
| $selectQuery = $qb->executeQuery(); | ||
|
|
||
| $qb2 = $this->db->getQueryBuilder(); | ||
| $qb2->delete('context_chat_content_queue') | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will not utilize the new index, I think. That may be ok, though.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yep, a unique index cannot be added without de-duplicating it first, we do it in another migration. |
||
| ->where( | ||
| $qb2->expr()->eq('app_id', $qb2->createParameter('appId')), | ||
| $qb2->expr()->eq('provider_id', $qb2->createParameter('providerId')), | ||
| $qb2->expr()->eq('item_id', $qb2->createParameter('itemId')), | ||
| $qb2->expr()->neq('id', $qb2->createParameter('keepId')), | ||
| ); | ||
|
|
||
| try { | ||
| while ($row = $selectQuery->fetch()) { | ||
| $qb2->setParameter('appId', $row['app_id']) | ||
| ->setParameter('providerId', $row['provider_id']) | ||
| ->setParameter('itemId', $row['item_id']) | ||
| ->setParameter('keepId', $row['keep_id']); | ||
|
|
||
| $rowsDeleted = $qb2->executeStatement(); | ||
| $totalRowsDeleted += $rowsDeleted; | ||
| } | ||
| } catch (\Exception $e) { | ||
| $selectQuery->closeCursor(); | ||
| throw $e; | ||
| } | ||
|
|
||
| $output->info("Removed $totalRowsDeleted duplicate content provider entries."); | ||
| } | ||
|
|
||
| /** | ||
| * @param IOutput $output | ||
| * @param Closure(): ISchemaWrapper $schemaClosure | ||
| * @param array $options | ||
| * @return null|ISchemaWrapper | ||
| */ | ||
| #[Override] | ||
| public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { | ||
| /** @var ISchemaWrapper $schema */ | ||
| $schema = $schemaClosure(); | ||
| $schemaChanged = false; | ||
|
|
||
| if ($schema->hasTable('context_chat_content_queue')) { | ||
| $table = $schema->getTable('context_chat_content_queue'); | ||
| $table->addUniqueIndex(['app_id', 'provider_id', 'item_id'], 'ccc_q_provider'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On large instances this will take a while. What made you give up the way of the AddMissingIndeces event?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we didn't have a way before to de-duplicate, now that we do that, it would be good to add the unique index just after since the table might not remain unique if there is time between the de-duplication and the index addition by the admin.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not against a unique index, it makes sense. I'm just afraid that we're not being a nice citizen by forcing the creation of the index on people with a large table which will cause a long downtime for them with this update. But might be acceptable.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true but the subset of the affected people might be quite small since this only affects the instances with analytics and/or mail apps that have turned on the context chat indexing. |
||
| $schemaChanged = true; | ||
| } | ||
|
|
||
| return $schemaChanged ? $schema : null; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.