From a479575897d9400de52ff1efd0df3d71bd7ea5e9 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 29 Aug 2026 15:17:15 +0100 Subject: [PATCH 1/7] fix: Add database indexes to the answer entity (#1228) --- src/assessment/entities/answer.entity.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/assessment/entities/answer.entity.ts b/src/assessment/entities/answer.entity.ts index a67a51ef..dba25748 100644 --- a/src/assessment/entities/answer.entity.ts +++ b/src/assessment/entities/answer.entity.ts @@ -1,10 +1,16 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, VersionColumn } from 'typeorm'; +import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, VersionColumn } from 'typeorm'; import { AssessmentAttempt } from './assessment-attempt.entity'; import { Question } from './question.entity'; /** * Represents the answer entity. */ @Entity() +// Composite index for the common "answers of an attempt" lookup and +// the "answer for a given question within an attempt" lookup. Because the +// leading column is `attempt`, this also serves attempt-only filters, so a +// separate single-column index on `attempt` would be redundant. +@Index('IDX_answer_attempt_question', ['attempt', 'question']) +@Index('IDX_answer_question', ['question']) export class Answer { @PrimaryGeneratedColumn('uuid') id: string; From 0d6f99cb84f42a565379e4942d76d0eaba08f5e5 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 29 Aug 2026 15:17:17 +0100 Subject: [PATCH 2/7] fix: Add database indexes to the answer entity (#1228) --- .../1756476695000-add-answer-indexes.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/migrations/1756476695000-add-answer-indexes.ts diff --git a/src/migrations/1756476695000-add-answer-indexes.ts b/src/migrations/1756476695000-add-answer-indexes.ts new file mode 100644 index 00000000..ca280bfb --- /dev/null +++ b/src/migrations/1756476695000-add-answer-indexes.ts @@ -0,0 +1,31 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class AddAnswerIndexes1756476695000 implements MigrationInterface { + name = 'AddAnswerIndexes1756476695000'; + + public async up(queryRunner: QueryRunner): Promise { + // Foreign-key / lookup column indexes for the "answer" table. + await queryRunner.query( + `CREATE INDEX IF NOT EXISTS "IDX_answer_question_id" ON "answer" ("question_id")`, + ); + await queryRunner.query( + `CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id" ON "answer" ("submission_id")`, + ); + await queryRunner.query( + `CREATE INDEX IF NOT EXISTS "IDX_answer_created_at" ON "answer" ("created_at")`, + ); + // Composite index for the common "answers for a submission, by question" lookup. + await queryRunner.query( + `CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id_question_id" ON "answer" ("submission_id", "question_id")`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `DROP INDEX IF EXISTS "IDX_answer_submission_id_question_id"`, + ); + await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_created_at"`); + await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_submission_id"`); + await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_question_id"`); + } +} From b0fafc16ddf158c3e0f42ce09b9b69cf6a6150bd Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 5 Sep 2026 10:09:19 +0100 Subject: [PATCH 3/7] fix(ci): resolve failing checks for #1380 --- src/migrations/1599999999999-BaselineSchema.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/migrations/1599999999999-BaselineSchema.ts b/src/migrations/1599999999999-BaselineSchema.ts index c85bb6a6..6fc9ceb2 100644 --- a/src/migrations/1599999999999-BaselineSchema.ts +++ b/src/migrations/1599999999999-BaselineSchema.ts @@ -616,6 +616,10 @@ export class BaselineSchema1599999999999 implements MigrationInterface { "attemptId" uuid, "questionId" uuid ) + `); + await queryRunner.query(`CREATE INDEX idx_answer_attempt_id ON public.answer USING btree ("attemptId") + `); + await queryRunner.query(`CREATE INDEX idx_answer_question_id ON public.answer USING btree ("questionId") `); await queryRunner.query(`CREATE TABLE public.archived_data ( id uuid DEFAULT public.uuid_generate_v4() NOT NULL, From 1b5d8ce63ad00cf57378a18cc6feb401f6dce482 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 5 Sep 2026 10:09:20 +0100 Subject: [PATCH 4/7] fix(ci): resolve failing checks for #1380 --- src/achievements/achievements.seed.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/achievements/achievements.seed.ts b/src/achievements/achievements.seed.ts index 3435280a..2e0e373a 100644 --- a/src/achievements/achievements.seed.ts +++ b/src/achievements/achievements.seed.ts @@ -1,5 +1,4 @@ import { AchievementType, AchievementDifficulty } from './entities/achievement.entity'; -import { Logger } from '@nestjs/common'; /** * Seed data for default achievements From ef14dbfb49ebf64f4ca24756c0fb88ccfe1f6442 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 5 Sep 2026 10:09:21 +0100 Subject: [PATCH 5/7] fix(ci): resolve failing checks for #1380 --- src/payments/providers/payment-provider.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/payments/providers/payment-provider.service.ts b/src/payments/providers/payment-provider.service.ts index ec21c9dc..64c7ab4e 100644 --- a/src/payments/providers/payment-provider.service.ts +++ b/src/payments/providers/payment-provider.service.ts @@ -38,7 +38,7 @@ export class PaymentProviderService { userId: string, amount: number, currency: string, - metadata: Record = {}, + _metadata: Record = {}, ): Promise { // TODO: replace with real Stripe call: // const intent = await stripe.paymentIntents.create({ amount: Math.round(amount * 100), currency, ... }); @@ -58,7 +58,7 @@ export class PaymentProviderService { userId: string, amount: number, currency: string, - metadata: Record = {}, + _metadata: Record = {}, ): Promise { // TODO: replace with real Stripe call: // const credit = await stripe.customers.createBalanceTransaction(customerId, { amount: -Math.round(amount * 100), currency }); From 68b6b96ac1b7482696578811a563f6b97b56d956 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 5 Sep 2026 10:09:23 +0100 Subject: [PATCH 6/7] fix(ci): resolve failing checks for #1380 --- .../1756476695000-add-answer-indexes.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/migrations/1756476695000-add-answer-indexes.ts b/src/migrations/1756476695000-add-answer-indexes.ts index ca280bfb..2509735f 100644 --- a/src/migrations/1756476695000-add-answer-indexes.ts +++ b/src/migrations/1756476695000-add-answer-indexes.ts @@ -6,26 +6,24 @@ export class AddAnswerIndexes1756476695000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { // Foreign-key / lookup column indexes for the "answer" table. await queryRunner.query( - `CREATE INDEX IF NOT EXISTS "IDX_answer_question_id" ON "answer" ("question_id")`, + 'CREATE INDEX IF NOT EXISTS "IDX_answer_question_id" ON "answer" ("question_id")', ); await queryRunner.query( - `CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id" ON "answer" ("submission_id")`, + 'CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id" ON "answer" ("submission_id")', ); await queryRunner.query( - `CREATE INDEX IF NOT EXISTS "IDX_answer_created_at" ON "answer" ("created_at")`, + 'CREATE INDEX IF NOT EXISTS "IDX_answer_created_at" ON "answer" ("created_at")', ); // Composite index for the common "answers for a submission, by question" lookup. await queryRunner.query( - `CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id_question_id" ON "answer" ("submission_id", "question_id")`, + 'CREATE INDEX IF NOT EXISTS "IDX_answer_submission_id_question_id" ON "answer" ("submission_id", "question_id")', ); } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `DROP INDEX IF EXISTS "IDX_answer_submission_id_question_id"`, - ); - await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_created_at"`); - await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_submission_id"`); - await queryRunner.query(`DROP INDEX IF EXISTS "IDX_answer_question_id"`); + await queryRunner.query('DROP INDEX IF EXISTS "IDX_answer_submission_id_question_id"'); + await queryRunner.query('DROP INDEX IF EXISTS "IDX_answer_created_at"'); + await queryRunner.query('DROP INDEX IF EXISTS "IDX_answer_submission_id"'); + await queryRunner.query('DROP INDEX IF EXISTS "IDX_answer_question_id"'); } } From fce26c461f68200a93d239d22b60a717effa2e27 Mon Sep 17 00:00:00 2001 From: Nathanpvd Date: Sat, 5 Sep 2026 10:09:24 +0100 Subject: [PATCH 7/7] fix(ci): resolve failing checks for #1380 --- src/auth/auth.controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index c17cd1db..197e54c4 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -20,7 +20,6 @@ import { RegisterDto } from './dto/register.dto'; import { RefreshTokenDto } from './dto/refresh-token.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { User } from '../users/entities/user.entity'; -import { Tenant } from '../tenancy/entities/tenant.entity'; import { Repository } from 'typeorm'; import * as bcrypt from 'bcrypt'; import { JwtAuthGuard } from './guards/jwt-auth.guard';