diff --git a/components/gitpod-db/src/typeorm/entity/db-volume-snapshot.ts b/components/gitpod-db/src/typeorm/entity/db-volume-snapshot.ts index 079006d3caec33..b9e5518a593b0c 100644 --- a/components/gitpod-db/src/typeorm/entity/db-volume-snapshot.ts +++ b/components/gitpod-db/src/typeorm/entity/db-volume-snapshot.ts @@ -31,4 +31,8 @@ export class DBVolumeSnapshot implements VolumeSnapshot { @Column("varchar") volumeHandle: string; + + // This column triggers the db-sync deletion mechanism. It's not intended for public consumption. + @Column() + deleted: boolean; } diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.ts index 88fcc39f907dee..451e46d0a30b6a 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.ts @@ -764,7 +764,11 @@ export abstract class AbstractTypeORMWorkspaceDBImpl implements WorkspaceDB { public async findVolumeSnapshotById(volumeSnapshotId: string): Promise { const volumeSnapshots = await this.getVolumeSnapshotRepo(); - return volumeSnapshots.findOne(volumeSnapshotId); + return volumeSnapshots + .createQueryBuilder("vs") + .where("vs.deleted = 0") + .andWhere("vs.id = :id", { id: volumeSnapshotId }) + .getOne(); } public async storeVolumeSnapshot(volumeSnapshot: VolumeSnapshot): Promise { @@ -775,7 +779,7 @@ export abstract class AbstractTypeORMWorkspaceDBImpl implements WorkspaceDB { public async deleteVolumeSnapshot(volumeSnapshotId: string): Promise { const volumeSnapshots = await this.getVolumeSnapshotRepo(); - await volumeSnapshots.delete(volumeSnapshotId); + await volumeSnapshots.update(volumeSnapshotId, { deleted: true }); } public async updateVolumeSnapshot( @@ -792,6 +796,7 @@ export abstract class AbstractTypeORMWorkspaceDBImpl implements WorkspaceDB { const qb = volumeSnapshotRepo .createQueryBuilder("vs") .select("vs.workspaceId", "workspaceId") + .where("vs.deleted = 0") .groupBy("vs.workspaceId") .having("COUNT(*) > 1") .limit(limit); @@ -805,6 +810,7 @@ export abstract class AbstractTypeORMWorkspaceDBImpl implements WorkspaceDB { const results = await volumeSnapshotRepo .createQueryBuilder("vs") .where("vs.workspaceId = :wsId", { wsId }) + .andWhere("vs.deleted = 0") .orderBy("vs.creationTime", "DESC") .limit(limit) .getMany(); diff --git a/components/gitpod-db/src/workspace-db.spec.db.ts b/components/gitpod-db/src/workspace-db.spec.db.ts index ae24c1a83e4d34..72d709aef9dd62 100644 --- a/components/gitpod-db/src/workspace-db.spec.db.ts +++ b/components/gitpod-db/src/workspace-db.spec.db.ts @@ -663,6 +663,24 @@ class WorkspaceDBSpec { } } + @test(timeout(10000)) + public async testCanFindVolumeSnapshotById() { + await this.threeVolumeSnapshotsForTwoWorkspaces(); + + const volSnapshot = await this.db.findVolumeSnapshotById("123"); + + expect(volSnapshot?.id).to.eq("123"); + } + + @test(timeout(10000)) + public async testCantFindDeletedVolumeSnapshotById() { + await this.threeVolumeSnapshotsForTwoWorkspaces(); + + const volSnapshot = await this.db.findVolumeSnapshotById("456b"); + + expect(volSnapshot).to.be.undefined; + } + @test(timeout(10000)) public async testFindVolumeSnapshotWorkspacesForGC() { await this.threeVolumeSnapshotsForTwoWorkspaces(); @@ -682,12 +700,14 @@ class WorkspaceDBSpec { expect(vss).to.deep.equal([ { creationTime: "", + deleted: false, id: "456", volumeHandle: "some-handle2", workspaceId: "ws-123", }, { creationTime: "", + deleted: false, id: "123", volumeHandle: "some-handle", workspaceId: "ws-123", @@ -717,6 +737,16 @@ class WorkspaceDBSpec { workspaceId, }); + const longBeforeNow = new Date(2018, 2, 15, 10, 0, 0).toISOString(); + const id2b = "456b"; + await repo.save({ + id: id2b, + creationTime: longBeforeNow, + volumeHandle: "some-handle2b", + workspaceId, + deleted: true, + }); + const someOtherTime = new Date(2018, 2, 10, 6, 5).toISOString(); const id3 = "789"; const workspaceId2 = "ws-789"; @@ -726,6 +756,16 @@ class WorkspaceDBSpec { volumeHandle: "some-handle3", workspaceId: workspaceId2, }); + + const yetAnotherTime = new Date(2018, 2, 10, 5, 5).toISOString(); + const id4 = "012"; + await repo.save({ + id: id4, + creationTime: yetAnotherTime, + volumeHandle: "some-handle4", + workspaceId: workspaceId2, + deleted: true, + }); } @test(timeout(10000))