fix: properly handle transaction for concurrent index operations

Instead of redefining the $withinTransaction property (which causes
a type error), we now manually commit the transaction before running
CREATE INDEX CONCURRENTLY and begin a new transaction afterward.

This ensures PostgreSQL can execute the concurrent index operations
while maintaining transaction safety for subsequent migrations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai 2025-10-10 18:39:40 +02:00
parent 3501d200d3
commit e256e765e7

View file

@ -6,26 +6,28 @@
return new class extends Migration
{
/**
* Disable transactions for this migration because CREATE INDEX CONCURRENTLY
* cannot run inside a transaction block in PostgreSQL.
*/
public bool $withinTransaction = false;
/**
* Run the migrations.
*/
public function up(): void
{
try {
// CREATE INDEX CONCURRENTLY cannot run inside a transaction block
// We need to commit any open transaction first
DB::commit();
// Add specific index for type_uuid queries with ordering
DB::statement('CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activity_type_uuid_created_at ON activity_log ((properties->>\'type_uuid\'), created_at DESC)');
DB::unprepared('CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activity_type_uuid_created_at ON activity_log ((properties->>\'type_uuid\'), created_at DESC)');
// Add specific index for status queries on properties
DB::statement('CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activity_properties_status ON activity_log ((properties->>\'status\'))');
DB::unprepared('CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activity_properties_status ON activity_log ((properties->>\'status\'))');
// Begin a new transaction for subsequent migrations
DB::beginTransaction();
} catch (\Exception $e) {
Log::error('Error adding optimized indexes to activity_log: '.$e->getMessage());
// Ensure we have a transaction for subsequent migrations
DB::beginTransaction();
}
}
@ -35,10 +37,16 @@ public function up(): void
public function down(): void
{
try {
DB::statement('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_type_uuid_created_at');
DB::statement('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_properties_status');
// DROP INDEX CONCURRENTLY cannot run inside a transaction block
DB::commit();
DB::unprepared('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_type_uuid_created_at');
DB::unprepared('DROP INDEX CONCURRENTLY IF EXISTS idx_activity_properties_status');
DB::beginTransaction();
} catch (\Exception $e) {
Log::error('Error dropping optimized indexes from activity_log: '.$e->getMessage());
DB::beginTransaction();
}
}
};