Skip to content

Commit df56997

Browse files
committed
[db][protocol] Implement a CostCenter entity to attribute workspace usage to
1 parent c2ce96d commit df56997

File tree

14 files changed

+133
-18
lines changed

14 files changed

+133
-18
lines changed

components/gitpod-db/src/container-module.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ import { TypeORMInstallationAdminImpl } from "./typeorm/installation-admin-db-im
6464
import { InstallationAdminDB } from "./installation-admin-db";
6565
import { TeamSubscription2DB } from "./team-subscription-2-db";
6666
import { TeamSubscription2DBImpl } from "./typeorm/team-subscription-2-db-impl";
67+
import { CostCenterDB } from "./cost-center-db";
68+
import { CostCenterDBImpl } from "./typeorm/cost-center-db-impl";
6769

6870
// THE DB container module that contains all DB implementations
6971
export const dbContainerModule = new ContainerModule((bind, unbind, isBound, rebind) => {
@@ -137,6 +139,9 @@ export const dbContainerModule = new ContainerModule((bind, unbind, isBound, reb
137139
bind(ProjectDBImpl).toSelf().inSingletonScope();
138140
bind(ProjectDB).toService(ProjectDBImpl);
139141

142+
bind(CostCenterDBImpl).toSelf().inSingletonScope();
143+
bind(CostCenterDB).toService(CostCenterDBImpl);
144+
140145
// com concerns
141146
bind(AccountingDB).to(TypeORMAccountingDBImpl).inSingletonScope();
142147
bind(TransactionalAccountingDBFactory).toFactory((ctx) => {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the Gitpod Enterprise Source Code License,
4+
* See License.enterprise.txt in the project root folder.
5+
*/
6+
7+
import { CostCenter } from "@gitpod/gitpod-protocol";
8+
9+
export const CostCenterDB = Symbol("CostCenterDB");
10+
export interface CostCenterDB {
11+
storeEntry(ts: CostCenter): Promise<void>;
12+
findById(id: string): Promise<CostCenter | undefined>;
13+
}

components/gitpod-db/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,4 @@ export * from "./typeorm/entity/db-account-entry";
3939
export * from "./project-db";
4040
export * from "./team-db";
4141
export * from "./installation-admin-db";
42+
export * from "./cost-center-db";

components/gitpod-db/src/tables.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ export class GitpodTableDescriptionProvider implements TableDescriptionProvider
268268
deletionColumn: "deleted",
269269
timeColumn: "_lastModified",
270270
},
271+
{
272+
name: "d_b_cost_center",
273+
primaryKeys: ["id"],
274+
deletionColumn: "deleted",
275+
timeColumn: "_lastModified",
276+
},
271277
/**
272278
* BEWARE
273279
*
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the Gitpod Enterprise Source Code License,
4+
* See License.enterprise.txt in the project root folder.
5+
*/
6+
7+
import { injectable, inject } from "inversify";
8+
import { Repository } from "typeorm";
9+
10+
import { CostCenter } from "@gitpod/gitpod-protocol";
11+
12+
import { CostCenterDB } from "../cost-center-db";
13+
import { DBCostCenter } from "./entity/db-cost-center";
14+
import { TypeORM } from "./typeorm";
15+
16+
@injectable()
17+
export class CostCenterDBImpl implements CostCenterDB {
18+
@inject(TypeORM) protected readonly typeORM: TypeORM;
19+
20+
protected async getEntityManager() {
21+
return (await this.typeORM.getConnection()).manager;
22+
}
23+
24+
protected async getRepo(): Promise<Repository<DBCostCenter>> {
25+
return (await this.getEntityManager()).getRepository(DBCostCenter);
26+
}
27+
28+
async storeEntry(ts: CostCenter): Promise<void> {
29+
const repo = await this.getRepo();
30+
await repo.save(ts);
31+
}
32+
33+
async findById(id: string): Promise<CostCenter | undefined> {
34+
const repo = await this.getRepo();
35+
return repo.findOne(id);
36+
}
37+
}

components/gitpod-db/src/typeorm/deleted-entry-gc.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const tables: TableWithDeletion[] = [
6363
{ deletionColumn: "deleted", name: "d_b_project_info" },
6464
{ deletionColumn: "deleted", name: "d_b_project_usage" },
6565
{ deletionColumn: "deleted", name: "d_b_team_subscription2" },
66+
{ deletionColumn: "deleted", name: "d_b_cost_center" },
6667
];
6768

6869
interface TableWithDeletion {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the Gitpod Enterprise Source Code License,
4+
* See License.enterprise.txt in the project root folder.
5+
*/
6+
7+
import { Entity, Column, PrimaryColumn } from "typeorm";
8+
import { CostCenter } from "@gitpod/gitpod-protocol";
9+
10+
@Entity()
11+
// on DB but not Typeorm: @Index("ind_lastModified", ["_lastModified"]) // DBSync
12+
export class DBCostCenter implements CostCenter {
13+
@PrimaryColumn("uuid")
14+
id: string;
15+
16+
// This column triggers the db-sync deletion mechanism. It's not intended for public consumption.
17+
@Column()
18+
deleted: boolean;
19+
}

components/gitpod-db/src/typeorm/entity/db-workspace-instance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,5 @@ export class DBWorkspaceInstance implements WorkspaceInstance {
107107
default: "",
108108
transformer: Transformer.MAP_EMPTY_STR_TO_UNDEFINED,
109109
})
110-
attributedTeamId?: string;
110+
costCenterId?: string;
111111
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Copyright (c) 2022 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License-AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { MigrationInterface, QueryRunner } from "typeorm";
8+
import { columnExists } from "./helper/helper";
9+
10+
export class CostCenter1655795038249 implements MigrationInterface {
11+
public async up(queryRunner: QueryRunner): Promise<void> {
12+
await queryRunner.query(
13+
"CREATE TABLE IF NOT EXISTS `d_b_cost_center` (`id` char(36) NOT NULL, `deleted` tinyint(4) NOT NULL DEFAULT '0', `_lastModified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`), KEY `ind_dbsync` (`_lastModified`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;",
14+
);
15+
if (!(await columnExists(queryRunner, "d_b_workspace_instance", "costCenterId"))) {
16+
await queryRunner.query(
17+
"ALTER TABLE `d_b_workspace_instance` CHANGE `attributedTeamId` `costCenterId` char(36) NOT NULL DEFAULT '', ALGORITHM=INPLACE, LOCK=NONE",
18+
);
19+
}
20+
}
21+
22+
public async down(queryRunner: QueryRunner): Promise<void> {
23+
if (!(await columnExists(queryRunner, "d_b_workspace_instance", "attributedTeamId"))) {
24+
await queryRunner.query(
25+
"ALTER TABLE `d_b_workspace_instance` CHANGE `costCenterId` `attributedTeamId` char(36) NOT NULL DEFAULT '', ALGORITHM=INPLACE, LOCK=NONE",
26+
);
27+
}
28+
}
29+
}

components/gitpod-db/src/workspace-db.spec.db.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class WorkspaceDBSpec {
6666
ideImage: "unknown",
6767
},
6868
deleted: false,
69-
attributedTeamId: undefined,
69+
costCenterId: undefined,
7070
};
7171
readonly wsi2: WorkspaceInstance = {
7272
workspaceId: this.ws.id,
@@ -89,7 +89,7 @@ class WorkspaceDBSpec {
8989
ideImage: "unknown",
9090
},
9191
deleted: false,
92-
attributedTeamId: undefined,
92+
costCenterId: undefined,
9393
};
9494
readonly ws2: Workspace = {
9595
id: "2",
@@ -127,7 +127,7 @@ class WorkspaceDBSpec {
127127
ideImage: "unknown",
128128
},
129129
deleted: false,
130-
attributedTeamId: undefined,
130+
costCenterId: undefined,
131131
};
132132

133133
readonly ws3: Workspace = {
@@ -165,7 +165,7 @@ class WorkspaceDBSpec {
165165
ideImage: "unknown",
166166
},
167167
deleted: false,
168-
attributedTeamId: undefined,
168+
costCenterId: undefined,
169169
};
170170

171171
async before() {

0 commit comments

Comments
 (0)