Skip to content

Commit

Permalink
feat: DrizzleOutboxMessageRepository
Browse files Browse the repository at this point in the history
  • Loading branch information
Gi-jutsu committed Nov 21, 2024
1 parent 3540382 commit cf68df1
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 3 deletions.
1 change: 1 addition & 0 deletions drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: [
"./src/identity-and-access/infrastructure/database/drizzle/schema.ts",
"./src/shared-kernel/infrastructure/database/drizzle/schema.ts",
],
dialect: "postgresql",
dbCredentials: {
Expand Down
7 changes: 7 additions & 0 deletions drizzle/0002_eager_boomerang.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS "outbox_messages" (
"id" uuid PRIMARY KEY NOT NULL,
"payload" jsonb NOT NULL,
"type" varchar(255) NOT NULL,
"created_at" timestamp DEFAULT now() NOT NULL,
"updated_at" timestamp DEFAULT now() NOT NULL
);
206 changes: 206 additions & 0 deletions drizzle/meta/0002_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
{
"id": "84449fea-aace-45f9-94cd-ddde8ecb0f41",
"prevId": "20fb321c-a6d4-4b5a-a63a-013ae90bb63f",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.accounts": {
"name": "accounts",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"emailUniqueIndex": {
"name": "emailUniqueIndex",
"columns": [
{
"expression": "lower(\"email\")",
"asc": true,
"isExpression": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.password_reset_requests": {
"name": "password_reset_requests",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"account_id": {
"name": "account_id",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"token": {
"name": "token",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"uniqueAccountResetRequest": {
"name": "uniqueAccountResetRequest",
"columns": [
{
"expression": "account_id",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {
"password_reset_requests_account_id_accounts_id_fk": {
"name": "password_reset_requests_account_id_accounts_id_fk",
"tableFrom": "password_reset_requests",
"tableTo": "accounts",
"columnsFrom": [
"account_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.outbox_messages": {
"name": "outbox_messages",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true
},
"payload": {
"name": "payload",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
9 changes: 8 additions & 1 deletion drizzle/meta/_journal.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
"when": 1728664010372,
"tag": "0001_illegal_sunset_bain",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1732214224642,
"tag": "0002_eager_boomerang",
"breakpoints": true
}
]
}
}
20 changes: 20 additions & 0 deletions src/shared-kernel/infrastructure/database/drizzle/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NodePgDatabase } from "drizzle-orm/node-postgres";
import { jsonb, pgTable, timestamp, uuid, varchar } from "drizzle-orm/pg-core";
import { randomUUID } from "node:crypto";

export const outboxMessageSchema = pgTable("outbox_messages", {
id: uuid("id")
.$defaultFn(() => randomUUID())
.primaryKey(),
payload: jsonb("payload").notNull().$type<Record<string, unknown>>(),
type: varchar("type", { length: 255 }).notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at")
.defaultNow()
.notNull()
.$defaultFn(() => new Date()),
});

export type SharedKernelDatabase = NodePgDatabase<{
outboxMessages: typeof outboxMessageSchema;
}>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Inject, Injectable } from "@nestjs/common";
import type { OutboxMessage } from "@shared-kernel/domain/outbox-message/aggregate-root.js";
import type { OutboxMessageRepository } from "@shared-kernel/domain/outbox-message/repository.js";
import { DrizzlePostgresPoolToken } from "../database/drizzle/constants.js";
import {
outboxMessageSchema,
SharedKernelDatabase,
} from "../database/drizzle/schema.js";

@Injectable()
export class DrizzleOutboxMessageRepository implements OutboxMessageRepository {
constructor(
@Inject(DrizzlePostgresPoolToken)
private readonly database: SharedKernelDatabase
) {}

async save(messages: OutboxMessage[]) {
const snapshots = messages.map((message) => message.properties);

await this.database
.insert(outboxMessageSchema)
.values(snapshots)
.onConflictDoNothing();
}
}
4 changes: 2 additions & 2 deletions src/shared-kernel/shared-kernel.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { APP_INTERCEPTOR } from "@nestjs/core";
import { OutboxMessageRepositoryToken } from "./domain/outbox-message/repository.js";
import { DatabaseModule } from "./infrastructure/database/database.module.js";
import { MapErrorToRfc9457HttpException } from "./infrastructure/map-error-to-rfc9457-http-exception.interceptor.js";
import { InMemoryOutboxMessageRepository } from "./infrastructure/repositories/in-memory-outbox-message.repository.js";
import { DrizzleOutboxMessageRepository } from "./infrastructure/repositories/drizzle-outbox-message.repository.js";
import { HealthCheckHttpController } from "./use-cases/health-check/http.controller.js";

@Global()
Expand All @@ -19,7 +19,7 @@ import { HealthCheckHttpController } from "./use-cases/health-check/http.control
},
{
provide: OutboxMessageRepositoryToken,
useClass: InMemoryOutboxMessageRepository,
useClass: DrizzleOutboxMessageRepository,
},
],
exports: [ConfigService, DatabaseModule, OutboxMessageRepositoryToken],
Expand Down

0 comments on commit cf68df1

Please sign in to comment.