From c86750c0c14431fb392c659b5d6ae0fb5240b468 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 17 Aug 2026 22:25:41 -0400 Subject: [PATCH 1/4] feat: add pagination indexes for completed tasks in the process_request_tokens table --- ..._17_000000_add_task_pagination_indexes.php | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 database/migrations/2026_08_17_000000_add_task_pagination_indexes.php diff --git a/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php b/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php new file mode 100644 index 0000000000..a69e9d11a0 --- /dev/null +++ b/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php @@ -0,0 +1,78 @@ +alterTable($clauses); + $this->refreshStatistics(); + } + + /** + * Remove completed-task pagination indexes. + */ + public function down(): void + { + $clauses = []; + + if (Schema::hasIndex(self::TABLE, self::COUNT_INDEX)) { + $clauses[] = sprintf('DROP INDEX `%s`', self::COUNT_INDEX); + } + + if (Schema::hasIndex(self::TABLE, self::PAGE_INDEX)) { + $clauses[] = sprintf('DROP INDEX `%s`', self::PAGE_INDEX); + } + + $this->alterTable($clauses); + $this->refreshStatistics(); + } + + private function alterTable(array $clauses): void + { + if ($clauses === []) { + return; + } + + DB::statement(sprintf( + 'ALTER TABLE `%s` %s, ALGORITHM=INPLACE, LOCK=NONE', + self::TABLE, + implode(', ', $clauses) + )); + } + + private function refreshStatistics(): void + { + DB::statement(sprintf('ANALYZE TABLE `%s`', self::TABLE)); + } +}; From 7d9c0cab5c6dd13deac19653e5d1b723533b4c18 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 17 Aug 2026 22:25:50 -0400 Subject: [PATCH 2/4] test: add unit tests for task pagination indexes migration --- .../AddTaskPaginationIndexesTest.php | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/Feature/Migrations/AddTaskPaginationIndexesTest.php diff --git a/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php b/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php new file mode 100644 index 0000000000..c7cd5c4195 --- /dev/null +++ b/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php @@ -0,0 +1,89 @@ +migration(); + $migration->down(); + + try { + $queries = $this->captureQueries(fn () => $migration->up()); + + $this->assertTrue(Schema::hasIndex('process_request_tokens', self::COUNT_INDEX)); + $this->assertTrue(Schema::hasIndex('process_request_tokens', self::PAGE_INDEX)); + $this->assertStatisticsWereRefreshed($queries); + } finally { + $migration->up(); + } + } + + public function testUpIsIdempotentAndStillRefreshesStatistics(): void + { + $migration = $this->migration(); + $migration->up(); + + $queries = $this->captureQueries(fn () => $migration->up()); + + $this->assertTrue(Schema::hasIndex('process_request_tokens', self::COUNT_INDEX)); + $this->assertTrue(Schema::hasIndex('process_request_tokens', self::PAGE_INDEX)); + $this->assertStatisticsWereRefreshed($queries); + $this->assertFalse(collect($queries)->contains( + fn (string $query) => str_starts_with($query, 'ALTER TABLE `process_request_tokens`') + )); + } + + public function testDownRemovesBothIndexesAndRefreshesStatistics(): void + { + $migration = $this->migration(); + $migration->up(); + + try { + $queries = $this->captureQueries(fn () => $migration->down()); + + $this->assertFalse(Schema::hasIndex('process_request_tokens', self::COUNT_INDEX)); + $this->assertFalse(Schema::hasIndex('process_request_tokens', self::PAGE_INDEX)); + $this->assertStatisticsWereRefreshed($queries); + } finally { + $migration->up(); + } + } + + private function migration() + { + return include base_path(self::MIGRATION_PATH); + } + + private function captureQueries(callable $callback): array + { + $queries = []; + + DB::listen(function (QueryExecuted $query) use (&$queries) { + $queries[] = $query->sql; + }); + + $callback(); + + return $queries; + } + + private function assertStatisticsWereRefreshed(array $queries): void + { + $this->assertContains('ANALYZE TABLE `process_request_tokens`', $queries); + } +} From 92235ca2a0c5d2431a818ba6e6293a92a0ec26bf Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 18 Aug 2026 14:07:15 -0400 Subject: [PATCH 3/4] refactor: rename pagination index constants for clarity in task migration --- .../2026_08_17_000000_add_task_pagination_indexes.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php b/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php index a69e9d11a0..8a5042068e 100644 --- a/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php +++ b/database/migrations/2026_08_17_000000_add_task_pagination_indexes.php @@ -7,9 +7,9 @@ return new class extends Migration { private const TABLE = 'process_request_tokens'; - private const COUNT_INDEX = 'idx_prt_completed_task_count'; + private const COUNT_INDEX = 'process_request_tokens_prt_completed_task_count'; - private const PAGE_INDEX = 'idx_prt_task_created'; + private const PAGE_INDEX = 'process_request_tokens_prt_task_created'; /** * Add indexes used by completed-task pagination. From 4a3faa8744a5145d74403f8050e5efd36ca48515 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Tue, 18 Aug 2026 15:01:37 -0400 Subject: [PATCH 4/4] test: update pagination index constants to include table name for better context --- tests/Feature/Migrations/AddTaskPaginationIndexesTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php b/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php index c7cd5c4195..b67d9ea811 100644 --- a/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php +++ b/tests/Feature/Migrations/AddTaskPaginationIndexesTest.php @@ -11,9 +11,9 @@ class AddTaskPaginationIndexesTest extends TestCase { private const MIGRATION_PATH = 'database/migrations/2026_08_17_000000_add_task_pagination_indexes.php'; - private const COUNT_INDEX = 'idx_prt_completed_task_count'; + private const COUNT_INDEX = 'process_request_tokens_prt_completed_task_count'; - private const PAGE_INDEX = 'idx_prt_task_created'; + private const PAGE_INDEX = 'process_request_tokens_prt_task_created'; protected $connectionsToTransact = [];