diff --git a/components/gitpod-db/README.md b/components/gitpod-db/README.md index 794deeab8dcdeb..0c6d91f7638e2e 100644 --- a/components/gitpod-db/README.md +++ b/components/gitpod-db/README.md @@ -7,14 +7,14 @@ When you are making changes to gitpod-protocol component, make sure to run `yarn ### Adding a new table 1. Create a [migration](./src/typeorm/migration/README.md) - use the [baseline](./src/typeorm/migration/1592203031938-Baseline.ts) as an exemplar -1. Create a new entity that implements the requisite interface or extend an existing entity as required - see [db-user.ts](./src/typeorm/entity/db-user.ts) -1. If it is a new table, create the matching injectable ORM implementation and interface (if required) - see [user-db-impl.ts](./src/typeorm/user-db-impl.ts) and [user-db.ts](./src/user-db.ts). Otherwise extend the existing interface and implementation as required. -1. Add the injectable implementation to the [DB container module](./src/container-module.ts), binding the interface and implementation as appropriate, otherwise it will not be instantiated correctly e.g. +2. Create a new entity that implements the requisite interface or extend an existing entity as required - see [db-user.ts](./src/typeorm/entity/db-user.ts) +3. If it is a new table, create the matching injectable ORM implementation and interface (if required) - see [user-db-impl.ts](./src/typeorm/user-db-impl.ts) and [user-db.ts](./src/user-db.ts). Otherwise extend the existing interface and implementation as required. +4. Add the injectable implementation to the [DB container module](./src/container-module.ts), binding the interface and implementation as appropriate, otherwise it will not be instantiated correctly e.g. ``` bind(TypeORMUserDBImpl).toSelf().inSingletonScope(); bind(UserDB).toService(TypeORMUserDBImpl); ``` -1. Add the new ORM as an injected component where required e.g. in [user-controller.ts](./src/user/user-controller.ts) +5. Add the new ORM as an injected component where required e.g. in [user-controller.ts](./src/user/user-controller.ts) ``` @inject(UserDB) protected readonly userDb: UserDB; -``` \ No newline at end of file +``` diff --git a/components/gitpod-db/src/typeorm/entity/db-workspace-instance-usage.ts b/components/gitpod-db/src/typeorm/entity/db-workspace-instance-usage.ts new file mode 100644 index 00000000000000..b1b36fa61e9734 --- /dev/null +++ b/components/gitpod-db/src/typeorm/entity/db-workspace-instance-usage.ts @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2022 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +import { Entity, Column, PrimaryColumn, Index } from "typeorm"; +import { TypeORM } from "../typeorm"; +import { Transformer } from "../transformer"; + +@Entity() +export class DBWorkspaceInstanceUsage { + @PrimaryColumn(TypeORM.UUID_COLUMN_TYPE) + workspaceId: string; + + @Column("varchar") + @Index() + attributionId: string; + + @Column({ + type: "timestamp", + precision: 6, + transformer: Transformer.MAP_ISO_STRING_TO_TIMESTAMP_DROP, + }) + @Index() + startedAt: string; + + @Column({ + type: "timestamp", + precision: 6, + nullable: true, + transformer: Transformer.MAP_ISO_STRING_TO_TIMESTAMP_DROP, + }) + @Index() + stoppedAt: string; + + @Column("double") + creditsUsed: number; + + @Column() + generationId: number; + + // 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/migration/1657621928045-AddWorkspaceInstanceUsageTable.ts b/components/gitpod-db/src/typeorm/migration/1657621928045-AddWorkspaceInstanceUsageTable.ts new file mode 100644 index 00000000000000..fc31dadcae793c --- /dev/null +++ b/components/gitpod-db/src/typeorm/migration/1657621928045-AddWorkspaceInstanceUsageTable.ts @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2022 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddWorkspaceInstanceUsageTable1657621928045 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE \`d_b_workspace_instance_usage\` (\`workspaceId\` char(36) NOT NULL, \`attributionId\` varchar(255) NOT NULL, \`startedAt\` timestamp(6) NOT NULL, \`stoppedAt\` timestamp(6) NULL, \`creditsUsed\` double NOT NULL, \`generationId\` int NOT NULL, \`deleted\` tinyint NOT NULL, INDEX \`IDX_1358af969a29fd9e0c6cabf37c\` (\`attributionId\`), INDEX \`IDX_25d77dfa246b93672c317e26ad\` (\`startedAt\`), INDEX \`IDX_e759ab5fcf57350da51fcf56bc\` (\`stoppedAt\`), PRIMARY KEY (\`workspaceId\`)) ENGINE=InnoDB`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX \`IDX_e759ab5fcf57350da51fcf56bc\` ON \`d_b_workspace_instance_usage\``); + await queryRunner.query(`DROP INDEX \`IDX_25d77dfa246b93672c317e26ad\` ON \`d_b_workspace_instance_usage\``); + await queryRunner.query(`DROP INDEX \`IDX_1358af969a29fd9e0c6cabf37c\` ON \`d_b_workspace_instance_usage\``); + await queryRunner.query(`DROP TABLE \`d_b_workspace_instance_usage\``); + } +}