Skip to content
12 changes: 6 additions & 6 deletions src/infrastructure/drizzle/DrizzleDiscordAccountRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
discordId,
memberId,
} from "#domain";
import { getClient } from "./client";
import { getClient, runInTransaction } from "./client";
import { discordAccountDomainEvents, discordAccounts } from "./schema";
import { serializeDiscordAccountEventPayload } from "./serializeDiscordAccountEvent";

Expand Down Expand Up @@ -37,18 +37,18 @@ export class DrizzleDiscordAccountRepository implements DiscordAccountRepository
}

async findAll(): Promise<DiscordAccount[]> {
const db = getDb();
const db = getClient();
const rows = await db.query.discordAccounts.findMany();
return rows.map(toDomain);
}

async save(account: DiscordAccount): Promise<void> {
const db = getClient();
const now = new Date().toISOString();
const events = account.getDomainEvents();

await db.transaction(async (tx) => {
await tx
await runInTransaction(async () => {
const client = getClient();
await client
.insert(discordAccounts)
.values({
discordId: account.discordId as string,
Expand All @@ -65,7 +65,7 @@ export class DrizzleDiscordAccountRepository implements DiscordAccountRepository
});

if (events.length > 0) {
await tx.insert(discordAccountDomainEvents).values(
await client.insert(discordAccountDomainEvents).values(
events.map((event) => ({
id: uuid(),
discordId: event.discordId as string,
Expand Down
68 changes: 35 additions & 33 deletions src/infrastructure/drizzle/DrizzleEventRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
exhibitId,
memberId,
} from "#domain";
import { type DrizzleClient, getClient } from "./client";
import { type DrizzleClient, getClient, runInTransaction } from "./client";
import { events, exhibits, lightningTalks, memberEvents, memberExhibits } from "./schema";

// ============================================================================
Expand Down Expand Up @@ -101,45 +101,47 @@ export class DrizzleEventRepository implements EventRepository {
// ==========================================================================

private async persistEvent(event: Event): Promise<void> {
const db = getClient();
const snapshot = event.toSnapshot();
const now = new Date().toISOString();
const dateStr = snapshot.date instanceof Date ? snapshot.date.toISOString() : snapshot.date;

// 1) Event upsert
await db
.insert(events)
.values({
id: snapshot.id,
name: snapshot.name,
date: dateStr,
updatedAt: now,
})
.onConflictDoUpdate({
target: events.id,
set: {
await runInTransaction(async () => {
const client = getClient();
const snapshot = event.toSnapshot();
const now = new Date().toISOString();
const dateStr = snapshot.date instanceof Date ? snapshot.date.toISOString() : snapshot.date;

// 1) Event upsert
await client
.insert(events)
.values({
id: snapshot.id,
name: snapshot.name,
date: dateStr,
updatedAt: now,
},
});
})
.onConflictDoUpdate({
target: events.id,
set: {
name: snapshot.name,
date: dateStr,
updatedAt: now,
},
});

// 2) Find obsolete exhibits and clean up
const snapshotExhibitIds = snapshot.exhibits.map((ex) => ex.id);
await this.deleteObsoleteExhibits(db, snapshot.id, snapshotExhibitIds);
// 2) Find obsolete exhibits and clean up
const snapshotExhibitIds = snapshot.exhibits.map((ex) => ex.id);
await this.deleteObsoleteExhibits(client, snapshot.id, snapshotExhibitIds);

// 3) Upsert exhibits
for (const ex of snapshot.exhibits) {
await this.upsertExhibit(db, snapshot.id, ex);
}
// 3) Upsert exhibits
for (const ex of snapshot.exhibits) {
await this.upsertExhibit(client, snapshot.id, ex);
}

// 4) Sync member events
await this.syncMemberEvents(db, snapshot.id, event.getMemberIds());
// 4) Sync member events
await this.syncMemberEvents(client, snapshot.id, event.getMemberIds());

// 5) Sync member exhibits
for (const exhibitDomain of event.getExhibits()) {
await this.syncMemberExhibits(db, exhibitDomain.id, exhibitDomain.getMemberIds());
}
// 5) Sync member exhibits
for (const exhibitDomain of event.getExhibits()) {
await this.syncMemberExhibits(client, exhibitDomain.id, exhibitDomain.getMemberIds());
}
});
}

private async deleteObsoleteExhibits(
Expand Down
13 changes: 6 additions & 7 deletions src/infrastructure/drizzle/DrizzleKarteRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
type Resolution,
type SupportRecord,
} from "#domain";
import { getClient } from "./client";
import { getClient, runInTransaction } from "./client";
import { karteAssignees, kartes } from "./schema";

// ============================================================================
Expand Down Expand Up @@ -274,8 +274,6 @@ export class DrizzleKarteRepository implements KarteRepository {
}

async save(karte: Karte): Promise<void> {
const db = getClient();

const clientCols = clientToColumns(karte.client);
const resCols = resolutionToColumns(karte.supportRecord.resolution);

Expand Down Expand Up @@ -305,15 +303,16 @@ export class DrizzleKarteRepository implements KarteRepository {

const { id: _, ...updateValues } = values;

await db.transaction(async (tx) => {
await runInTransaction(async () => {
const client = getClient();
// Upsert karte
await tx.insert(kartes).values(values).onConflictDoUpdate({
await client.insert(kartes).values(values).onConflictDoUpdate({
target: kartes.id,
set: updateValues,
});

// Sync assignees (delete-all-then-insert)
await tx.delete(karteAssignees).where(eq(karteAssignees.karteId, karte.id as string));
await client.delete(karteAssignees).where(eq(karteAssignees.karteId, karte.id as string));

if (karte.supportRecord.assignees.type === "recorded") {
const assigneeRows = karte.supportRecord.assignees.value.map((assignee) => ({
Expand All @@ -322,7 +321,7 @@ export class DrizzleKarteRepository implements KarteRepository {
memberId: assignee.type === "resolved" ? (assignee.memberId as string) : null,
assigneeName: assignee.type === "unresolved" ? assignee.name : null,
}));
await tx.insert(karteAssignees).values(assigneeRows);
await client.insert(karteAssignees).values(assigneeRows);
}
});
}
Expand Down
10 changes: 5 additions & 5 deletions src/infrastructure/drizzle/DrizzleMemberRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
type MemberRepository,
type Recorded,
} from "#domain";
import { getClient } from "./client";
import { getClient, runInTransaction } from "./client";
import { memberDomainEvents, members } from "./schema";
import { serializeMemberEventPayload } from "./serializeMemberEvent";

Expand Down Expand Up @@ -124,12 +124,12 @@ export class DrizzleMemberRepository implements MemberRepository {
}

async save(member: Member): Promise<void> {
const db = getClient();
const values = toInsertValues(member);
const events = member.getDomainEvents();

await db.transaction(async (tx) => {
await tx
await runInTransaction(async () => {
const client = getClient();
await client
.insert(members)
.values(values)
.onConflictDoUpdate({
Expand All @@ -146,7 +146,7 @@ export class DrizzleMemberRepository implements MemberRepository {
});

if (events.length > 0) {
await tx.insert(memberDomainEvents).values(
await client.insert(memberDomainEvents).values(
events.map((event) => ({
id: uuid(),
memberId: event.id as string,
Expand Down
36 changes: 2 additions & 34 deletions src/infrastructure/drizzle/client.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
/// <reference types="node" />
import { AsyncLocalStorage } from "node:async_hooks";
<<<<<<< HEAD
import type { PgDatabase } from "drizzle-orm/pg-core";
import { drizzle } from "drizzle-orm/postgres-js";
import type { PostgresJsQueryResultHKT } from "drizzle-orm/postgres-js/session";
import postgres, { type Sql } from "postgres";
import * as schema from "./schema";

export type DrizzleDb = PgDatabase<PostgresJsQueryResultHKT, typeof schema>;
=======
import type { NodePgQueryResultHKT } from "drizzle-orm/node-postgres";
import { drizzle } from "drizzle-orm/node-postgres";
import type { PgDatabase } from "drizzle-orm/pg-core";
import { Pool } from "pg";
import * as schema from "./schema";

export type DrizzleClient = PgDatabase<NodePgQueryResultHKT, typeof schema>;

let pool: Pool | null = null;
>>>>>>> 6d5f1a6 (refactor: DrizzleClientをPgDatabase型で定義しトランザクションの強制キャストを除去)
export type DrizzleClient = PgDatabase<PostgresJsQueryResultHKT, typeof schema>;

let sqlClient: Sql | null = null;

Expand All @@ -34,23 +22,11 @@ function getSqlClient(): Sql {
return sqlClient;
}

<<<<<<< HEAD
<<<<<<< HEAD
function createDb() {
return drizzle(getSqlClient(), { schema });
}

const transactionContext = new AsyncLocalStorage<DrizzleDb>();
=======
function createClient() {
=======
function createClient(): DrizzleClient {
>>>>>>> 6d5f1a6 (refactor: DrizzleClientをPgDatabase型で定義しトランザクションの強制キャストを除去)
return drizzle(getPool(), { schema });
return drizzle(getSqlClient(), { schema });
}

const transactionContext = new AsyncLocalStorage<DrizzleClient>();
>>>>>>> 91008a2 (refactor: getDb/createDb/DrizzleDb を getClient/createClient/DrizzleClient にリネーム)

/**
* Drizzleクライアントを取得する
Expand All @@ -73,14 +49,6 @@ export function runInTransaction<T>(fn: () => Promise<T>): Promise<T> {
}
const db = createClient();
return db.transaction(async (tx) => {
<<<<<<< HEAD
<<<<<<< HEAD
return transactionContext.run(tx, fn);
=======
return transactionContext.run(tx as unknown as DrizzleClient, fn);
>>>>>>> 91008a2 (refactor: getDb/createDb/DrizzleDb を getClient/createClient/DrizzleClient にリネーム)
=======
return transactionContext.run(tx, fn);
>>>>>>> 6d5f1a6 (refactor: DrizzleClientをPgDatabase型で定義しトランザクションの強制キャストを除去)
});
}