Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions cloud/backend/hono-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import { Context, Hono, Next } from "hono";
import { WSContext, WSContextInit, WSMessageReceive } from "hono/ws";
// import { CFExposeCtxItem } from "./cf-hono-server.js";
import { metaMerger } from "./meta-merger/meta-merger.js";
import { SQLDatabase } from "./meta-merger/abstract-sql.js";
// import { SQLDatabase } from "./meta-merger/abstract-sql.js";
import { WSRoom } from "./ws-room.js";
import { MsgDispatcher, MsgDispatcherCtx, Promisable, WSConnectionPair } from "./msg-dispatch.js";
import { calculatePreSignedUrl } from "./pre-signed-url.js";
import { buildMsgDispatcher } from "./msg-dispatcher-impl.js";
import { LibSQLDatabase } from "drizzle-orm/libsql";

type BindGetMeta = ps.cloud.BindGetMeta;
type ReqPutMeta = ps.cloud.ReqPutMeta;
Expand Down Expand Up @@ -51,7 +52,7 @@ export interface ExposeCtxItem<T extends WSRoom> {
readonly ende: ps.cloud.EnDeCoder;
readonly stsService: rt.sts.SessionTokenService;
readonly gestalt: ps.cloud.Gestalt;
readonly dbFactory: () => SQLDatabase;
readonly dbFactory: () => LibSQLDatabase;
// readonly metaMerger: MetaMerger;
readonly id: string;
}
Expand Down Expand Up @@ -138,10 +139,11 @@ export abstract class HonoServerBase implements HonoServerImpl {
}
// abstract getConnected(): Connected[];

start(ctx: ExposeCtxItem<WSRoom>, drop = false): Promise<HonoServerImpl> {
return metaMerger(ctx)
.createSchema(drop)
.then(() => this);
start(ctx: ExposeCtxItem<WSRoom>): Promise<HonoServerImpl> {
metaMerger(ctx)
return Promise.resolve(this);
// .createSchema(drop)
// .then(() => this);
}

// gestalt(): Gestalt {
Expand Down Expand Up @@ -248,7 +250,7 @@ class NoBackChannel implements MsgDispatcherCtx {
readonly logger: Logger;
readonly ende: ps.cloud.EnDeCoder;
readonly gestalt: ps.cloud.Gestalt;
readonly dbFactory: () => SQLDatabase;
readonly dbFactory: () => LibSQLDatabase;
readonly id: string;
readonly stsService: rt.sts.SessionTokenService;

Expand Down
53 changes: 0 additions & 53 deletions cloud/backend/meta-merger/abstract-sql.ts

This file was deleted.

37 changes: 0 additions & 37 deletions cloud/backend/meta-merger/bettersql-abstract-sql.ts

This file was deleted.

9 changes: 0 additions & 9 deletions cloud/backend/meta-merger/create-schema-cli.ts

This file was deleted.

196 changes: 118 additions & 78 deletions cloud/backend/meta-merger/key-by-tenant-ledger.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js";
// import { conditionalDrop, SQLDatabase, SQLStatement } from "./abstract-sql.js";
import { ByConnection } from "./meta-merger.js";
import { TenantLedgerSql } from "./tenant-ledger.js";
// import { TenantLedgerSql } from "./tenant-ledger.js";
import { foreignKey, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
import { sqlTenantLedger } from "./tenant-ledger.js";
import { LibSQLDatabase } from "drizzle-orm/libsql";
import { eq, and, inArray } from "drizzle-orm/expressions";

export interface KeysForTenantLedger {
readonly tenant: string;
Expand All @@ -9,102 +13,138 @@ export interface KeysForTenantLedger {
readonly createdAt: Date;
}

export interface SQLMetaByTenantLedgerRow {
readonly tenant: string;
readonly ledger: string;
readonly key: string;
readonly createdAt: string;
}
// export interface SQLMetaByTenantLedgerRow {
// readonly tenant: string;
// readonly ledger: string;
// readonly key: string;
// readonly createdAt: string;
// }

export const sqlKeyByTenantLedger = sqliteTable(
"KeyByTenantLedger",
{
tenant: text().notNull(),
ledger: text().notNull(),
key: text().notNull(),
createdAt: text().notNull(),
},
(table) => [
primaryKey({ columns: [table.tenant, table.ledger, table.key] }),
foreignKey({
columns: [table.tenant, table.ledger],
foreignColumns: [sqlTenantLedger.tenant, sqlTenantLedger.ledger],
}),
],
);

export class KeyByTenantLedgerSql {
static schema(drop = false) {
return [
...conditionalDrop(
drop,
"KeyByTenantLedger",
`
CREATE TABLE IF NOT EXISTS KeyByTenantLedger(
tenant TEXT NOT NULL,
ledger TEXT NOT NULL,
key TEXT NOT NULL,
createdAt TEXT NOT NULL,
PRIMARY KEY (tenant, ledger, key),
FOREIGN KEY (tenant, ledger) REFERENCES TenantLedger(tenant, ledger)
)
`,
),
];
}
// static schema(drop = false) {
// return [
// ...conditionalDrop(
// drop,
// "KeyByTenantLedger",
// `
// CREATE TABLE IF NOT EXISTS KeyByTenantLedger(
// tenant TEXT NOT NULL,
// ledger TEXT NOT NULL,
// key TEXT NOT NULL,
// createdAt TEXT NOT NULL,
// PRIMARY KEY (tenant, ledger, key),
// FOREIGN KEY (tenant, ledger) REFERENCES TenantLedger(tenant, ledger)
// )
// `,
// ),
// ];
// }

readonly db: SQLDatabase;
readonly tenantLedgerSql: TenantLedgerSql;
readonly db: LibSQLDatabase;
// readonly tenantLedgerSql: TenantLedgerSql;
readonly id: string;
constructor(id: string, db: SQLDatabase, tenantLedgerSql: TenantLedgerSql) {
constructor(id: string, db: LibSQLDatabase) {
this.db = db;
this.tenantLedgerSql = tenantLedgerSql;
this.id = id;
}

// readonly #sqlCreateMetaByTenantLedger = new ResolveOnce();
sqlCreateKeyByTenantLedger(): SQLStatement[] {
// return this.#sqlCreateMetaByTenantLedger.once(() => {
return KeyByTenantLedgerSql.schema().map((i) => this.db.prepare(i));
// });
}
// sqlCreateKeyByTenantLedger(): SQLStatement[] {
// // return this.#sqlCreateMetaByTenantLedger.once(() => {
// return KeyByTenantLedgerSql.schema().map((i) => this.db.prepare(i));
// // });
// }

// readonly #sqlInsertMetaByTenantLedger = new ResolveOnce();
sqlEnsureKeyByTenantLedger(): SQLStatement {
// return this.#sqlInsertMetaByTenantLedger.once(() => {
return this.db.prepare(`
INSERT INTO KeyByTenantLedger(tenant, ledger, key, createdAt)
SELECT ?, ?, ?, ? WHERE NOT EXISTS (
SELECT 1 FROM KeyByTenantLedger WHERE key = ? and tenant = ? and ledger = ?
)
`);
// });
}

// readonly #sqlDeleteByConnection = new ResolveOnce();
sqlDeleteByTenantLedgerKey(): SQLStatement {
// return this.#sqlDeleteByConnection.once(() => {
return this.db.prepare(`
DELETE FROM KeyByTenantLedger
WHERE
tenant = ?
AND
ledger = ?
AND
key = ?
`);
// });
}
// sqlDeleteByTenantLedgerKey(): SQLStatement {
// // return this.#sqlDeleteByConnection.once(() => {
// return this.db.prepare(`
// DELETE FROM KeyByTenantLedger
// WHERE
// tenant = ?
// AND
// ledger = ?
// AND
// key = ?
// `);
// // });
// }

async deleteByTenantLedgerKey(t: Omit<KeysForTenantLedger, "createdAt">): Promise<void> {
const stmt = this.sqlDeleteByTenantLedgerKey();
for (const key of t.keys) {
await stmt.run(t.tenant, t.ledger, key);
}
async deleteByTenantLedgerKey(t: Omit<KeysForTenantLedger, "createdAt">) {
return this.db
.delete(sqlKeyByTenantLedger)
.where(
and(
eq(sqlKeyByTenantLedger.tenant, t.tenant),
eq(sqlKeyByTenantLedger.ledger, t.ledger),
inArray(sqlKeyByTenantLedger.key, t.keys),
),
)
.run();
}

async ensure(t: KeysForTenantLedger): Promise<void> {
const stmt = this.sqlEnsureKeyByTenantLedger();
for (const key of t.keys) {
await stmt.run(t.tenant, t.ledger, key, t.createdAt, key, t.tenant, t.ledger);
}
}
// sqlEnsureKeyByTenantLedger(): SQLStatement {
// // return this.#sqlInsertMetaByTenantLedger.once(() => {
// return this.db.prepare(`
// INSERT INTO KeyByTenantLedger(tenant, ledger, key, createdAt)
// SELECT ?, ?, ?, ? WHERE NOT EXISTS (
// SELECT 1 FROM KeyByTenantLedger WHERE key = ? and tenant = ? and ledger = ?
// )
// `);
// // });
// }

sqlSelectByTenantLedger(): SQLStatement {
return this.db.prepare(`
SELECT tenant, ledger, key, createdAt
FROM KeyByTenantLedger
WHERE tenant = ? AND ledger = ?
ORDER BY key
`);
async ensure(t: KeysForTenantLedger) {
return this.db
.insert(sqlKeyByTenantLedger)
.values(
t.keys.map((key) => ({
tenant: t.tenant,
ledger: t.ledger,
key: key,
createdAt: t.createdAt.toISOString(),
})),
)
.onConflictDoNothing()
.run();
}

// sqlSelectByTenantLedger(): SQLStatement {
// return this.db.prepare(`
// SELECT tenant, ledger, key, createdAt
// FROM KeyByTenantLedger
// WHERE tenant = ? AND ledger = ?
// ORDER BY key
// `);
// }

async selectKeysByTenantLedger(conn: ByConnection): Promise<Omit<KeysForTenantLedger, "createdAt">> {
const stmt = this.sqlSelectByTenantLedger();
const rows = await stmt.all<SQLMetaByTenantLedgerRow>(conn.tenant, conn.ledger);
// const stmt = this.sqlSelectByTenantLedger();
const rows = await this.db
.select()
.from(sqlKeyByTenantLedger)
.where(and(eq(sqlKeyByTenantLedger.tenant, conn.tenant), eq(sqlKeyByTenantLedger.ledger, conn.ledger)))
.orderBy(sqlKeyByTenantLedger.key)
.all();
return {
tenant: conn.tenant,
ledger: conn.ledger,
Expand Down
Loading
Loading