From 15167831293d30a3153b6b54d74b3e844c4a44ac Mon Sep 17 00:00:00 2001 From: alisawavezen12 Date: Wed, 14 Oct 2026 17:01:50 +0300 Subject: [PATCH 1/4] Add compound index for repetition release lookups --- ...0000-add-repetition-group-release-index.js | 58 +++++++++++++++++++ src/resolvers/project.js | 8 +++ test/resolvers/project.test.ts | 5 ++ 3 files changed, 71 insertions(+) create mode 100644 migrations/20261014000000-add-repetition-group-release-index.js diff --git a/migrations/20261014000000-add-repetition-group-release-index.js b/migrations/20261014000000-add-repetition-group-release-index.js new file mode 100644 index 00000000..8c110a7d --- /dev/null +++ b/migrations/20261014000000-add-repetition-group-release-index.js @@ -0,0 +1,58 @@ +const { MongoClient } = require('mongodb'); + +const REPETITIONS_INDEX_NAME = 'groupHashAndRelease'; + +/** + * Run an operation against the events database. + * + * @param {Function} callback - operation to run + */ +async function withEventsDatabase(callback) { + const url = process.env.MONGO_EVENTS_DB_URL; + + if (!url) { + throw new Error('MONGO_EVENTS_DB_URL must be set to migrate repetition indexes'); + } + + const client = new MongoClient(url); + + try { + await client.connect(); + + return await callback(client.db()); + } finally { + await client.close(); + } +} + +module.exports = { + async up() { + await withEventsDatabase(async db => { + const collections = await db.listCollections({ name: /^repetitions:/ }, { nameOnly: true }).toArray(); + + for (const { name } of collections) { + await db.collection(name).createIndex({ + groupHash: 1, + release: 1, + }, { + name: REPETITIONS_INDEX_NAME, + }); + } + }); + }, + + async down() { + await withEventsDatabase(async db => { + const collections = await db.listCollections({ name: /^repetitions:/ }, { nameOnly: true }).toArray(); + + for (const { name } of collections) { + await db.collection(name).dropIndex(REPETITIONS_INDEX_NAME) + .catch(error => { + if (error.codeName !== 'IndexNotFound' && error.code !== 27) { + throw error; + } + }); + } + }); + }, +}; diff --git a/src/resolvers/project.js b/src/resolvers/project.js index 40bfb51e..310f54d6 100644 --- a/src/resolvers/project.js +++ b/src/resolvers/project.js @@ -13,6 +13,7 @@ const { GitHubService } = require('../integrations/github/service'); const EVENTS_GROUP_HASH_INDEX_NAME = 'groupHashUnique'; const REPETITIONS_GROUP_HASH_INDEX_NAME = 'groupHash_hashed'; +const REPETITIONS_GROUP_HASH_AND_RELEASE_INDEX_NAME = 'groupHashAndRelease'; const REPETITIONS_USER_ID_INDEX_NAME = 'userId'; const REPETITIONS_TIMESTAMP_INDEX_NAME = 'timestamp'; const EVENTS_TIMESTAMP_INDEX_NAME = 'timestamp'; @@ -409,6 +410,13 @@ module.exports = { name: REPETITIONS_GROUP_HASH_INDEX_NAME, }); + await projectRepetitionsEventsCollection.createIndex({ + groupHash: 1, + release: 1, + }, { + name: REPETITIONS_GROUP_HASH_AND_RELEASE_INDEX_NAME, + }); + await projectRepetitionsEventsCollection.createIndex({ 'payload.user.id': 1, }, { diff --git a/test/resolvers/project.test.ts b/test/resolvers/project.test.ts index 00a4a907..ea894eb0 100644 --- a/test/resolvers/project.test.ts +++ b/test/resolvers/project.test.ts @@ -596,6 +596,11 @@ describe('Project Resolver - createProject', () => { context ); + expect(repetitionsCollectionMock.createIndex).toHaveBeenCalledWith( + { groupHash: 1, release: 1 }, + { name: 'groupHashAndRelease' } + ); + expect(repetitionsCollectionMock.createIndex).toHaveBeenCalledWith( { timestamp: 1 }, { name: 'timestamp', sparse: true } From 981b7925d6876dfd6c603d949479368b80a75334 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 14 Oct 2026 14:04:20 +0000 Subject: [PATCH 2/4] Bump version up to 1.5.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2319788e..3f359ea0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.5.16", + "version": "1.5.17", "main": "index.ts", "license": "BUSL-1.1", "scripts": { From 8b870fce4a26922329eca0d50d745487681b2477 Mon Sep 17 00:00:00 2001 From: alisawavezen12 Date: Wed, 14 Oct 2026 17:07:41 +0300 Subject: [PATCH 3/4] version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f359ea0..85f560d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.5.17", + "version": "1.6.0", "main": "index.ts", "license": "BUSL-1.1", "scripts": { From 799f2069c665f10b119beb4e6b99b86e0477b430 Mon Sep 17 00:00:00 2001 From: alisawavezen12 Date: Wed, 14 Oct 2026 17:18:46 +0300 Subject: [PATCH 4/4] chore --- src/resolvers/project.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/resolvers/project.js b/src/resolvers/project.js index 310f54d6..2e82f6c0 100644 --- a/src/resolvers/project.js +++ b/src/resolvers/project.js @@ -410,6 +410,9 @@ module.exports = { name: REPETITIONS_GROUP_HASH_INDEX_NAME, }); + /** + * Used by the release validator to find the releases in which each event occurred. + */ await projectRepetitionsEventsCollection.createIndex({ groupHash: 1, release: 1,