fix(server): gate viewFilter.relationTargetFieldMetadataId behind its 2.6 upgrade command (#21267)
## Problem Self-hosted upgrades crossing 2.6 (e.g. `2.4 → 2.6/2.9`) can abort with: ``` column ViewFilterEntity.relationTargetFieldMetadataId does not exist at WorkspaceFlatViewFilterMapCacheService.computeForCache at WorkspaceCacheService.recomputeDataFromProvider [UpgradeSequenceRunnerService] Workspace steps ended with 1 failure(s). Aborting ``` This is **Failure #1** from #20841 — the counterpart to the role-permission cache crash fixed in #21257 (Failure #2). Same shape: a workspace **cache recompute runs mid-upgrade and reads schema that the target version's migration hasn't applied yet**. ## Root cause `ViewFilterEntity.relationTargetFieldMetadataId` is added to `core.viewFilter` only at the **2.6.0** cursor (`AddRelationTargetFieldMetadataIdToViewFilterFastInstanceCommand`, ts `1798000005000`). But the workspace cache recompute SELECTs every column of the entity, and it runs during *earlier* (2.5) workspace steps. Unlike `RolePermissionFlagEntity.permissionFlag`, this column has **no `@WasIntroducedInUpgrade` gate**, so the proxy can't hide it — and the SELECT fails when the column isn't there yet. There are three `IF NOT EXISTS` backport commands (2.3/2.4/2.5) meant to add the column sooner, but they use **low timestamps** that sort to the front of their version bundles. An instance whose cursor has already advanced past those positions (e.g. it reached 2.4, or a prior failed attempt advanced it through 2.5 instance commands) treats them as already-applied and **skips them** — so the column is never created, yet the entity keeps selecting it. ## Fix Gate the column with `@WasIntroducedInUpgrade` pointing at the **2.6.0** command that adds it: ```ts @WasIntroducedInUpgrade({ upgradeCommandName: '2.6.0_AddRelationTargetFieldMetadataIdToViewFilterFastInstanceCommand_1798000005000', }) @Column({ nullable: true, type: 'uuid', default: null }) relationTargetFieldMetadataId: string | null; ``` `UpgradeAwareRepositoryProxy` then hides the column from reads while the cursor is < 2.6, so the cache recompute simply omits it — no crash — and it becomes visible once the 2.6.0 command has run (where it's guaranteed to exist). Gating to **2.6.0** specifically (not the earlier backports) is what fixes the cursor-skip case: 2.6.0 is the first point where the column is reliably present regardless of whether the backports ran. Validator-safe: the referenced command resolves to a real step (`computeCommandName` = `${version}_${className}_${timestamp}`), so `validate-upgrade-aware-entity-decorators` accepts it. The existing backport commands are left untouched (committed instance commands). ## Recovery for already-stuck instances This prevents *new* failures. An instance already aborted mid-upgrade needs the column added manually before retrying: ```sql ALTER TABLE core."viewFilter" ADD COLUMN IF NOT EXISTS "relationTargetFieldMetadataId" uuid; DELETE FROM core."upgradeMigration" WHERE status='failed'; ``` then re-run the upgrade on a build that includes this fix. Refs #20841 Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+5
@@ -12,6 +12,7 @@ import {
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { WasIntroducedInUpgrade } from 'src/engine/core-modules/upgrade/decorators/was-introduced-in-upgrade.decorator';
|
||||
import { type JsonbProperty } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/jsonb-property.type';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
|
||||
@@ -64,6 +65,10 @@ export class ViewFilterEntity
|
||||
@Column({ nullable: true, type: 'text', default: null })
|
||||
subFieldName: string | null;
|
||||
|
||||
@WasIntroducedInUpgrade({
|
||||
upgradeCommandName:
|
||||
'2.6.0_AddRelationTargetFieldMetadataIdToViewFilterFastInstanceCommand_1798000005000',
|
||||
})
|
||||
@Column({ nullable: true, type: 'uuid', default: null })
|
||||
relationTargetFieldMetadataId: string | null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user