mirror of
https://github.com/twentyhq/twenty.git
synced 2026-05-24 16:32:28 -04:00
fix(server): batch upgrade migration inserts to stay under PG param limit (#20588)
## Summary
Prod deploy of v2.5.0 fails with a query failure inserting into
`core.upgradeMigration`:
```
query failed: INSERT INTO "core"."upgradeMigration" ("id", "name", "status", "attempt", "executedByVersion", "errorMessage", "isInitial", "workspaceId", "createdAt")
VALUES (DEFAULT, $1, $2, $3, $4, $5, DEFAULT, $6, DEFAULT),
(DEFAULT, $7, $8, $9, $10, $11, DEFAULT, $12, DEFAULT),
... (continues past $2515) ...
```
### Root cause
`UpgradeMigrationService.recordUpgradeMigration` writes one row per
workspace via a single `repository.save([...rows])` call.
`UpgradeMigrationEntity` has **6 user-provided columns** per row
(`name`, `status`, `attempt`, `executedByVersion`, `errorMessage`,
`workspaceId`), so the multi-row INSERT binds `6 * (1 + N_workspaces)`
parameters.
Postgres' wire protocol caps a single statement at **65,535 bind
parameters** (16-bit count). That gives a hard ceiling of ~10,920 rows
per call. Production has enough workspaces to overflow.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import chunk from 'lodash.chunk';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { In, IsNull, type QueryRunner, Repository } from 'typeorm';
|
||||
|
||||
@@ -21,6 +22,8 @@ export type WorkspaceLastAttemptedCommand = {
|
||||
isInitial: boolean;
|
||||
};
|
||||
|
||||
const UPGRADE_MIGRATION_SAVE_BATCH_SIZE = 1000;
|
||||
|
||||
@Injectable()
|
||||
export class UpgradeMigrationService {
|
||||
constructor(
|
||||
@@ -95,7 +98,7 @@ export class UpgradeMigrationService {
|
||||
where: { name, workspaceId: IsNull() },
|
||||
});
|
||||
|
||||
await repository.save([
|
||||
const instanceRows = [
|
||||
{
|
||||
name,
|
||||
status,
|
||||
@@ -112,7 +115,14 @@ export class UpgradeMigrationService {
|
||||
workspaceId,
|
||||
errorMessage,
|
||||
})),
|
||||
]);
|
||||
];
|
||||
|
||||
for (const batch of chunk(
|
||||
instanceRows,
|
||||
UPGRADE_MIGRATION_SAVE_BATCH_SIZE,
|
||||
)) {
|
||||
await repository.save(batch);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +144,9 @@ export class UpgradeMigrationService {
|
||||
});
|
||||
}
|
||||
|
||||
await repository.save(rows);
|
||||
for (const batch of chunk(rows, UPGRADE_MIGRATION_SAVE_BATCH_SIZE)) {
|
||||
await repository.save(batch);
|
||||
}
|
||||
}
|
||||
|
||||
async markAsWorkspaceInitial({
|
||||
|
||||
Reference in New Issue
Block a user