199 lines · 6.2 KB · TypeScript
RawDownload
import { ThreadId } from "@t3tools/contracts";import * as SqlClient from "effect/unstable/sql/SqlClient";import * as SqlSchema from "effect/unstable/sql/SqlSchema";import { Effect, Layer, Option, Schema, Struct } from "effect"; import {  toPersistenceDecodeError,  toPersistenceSqlError,  type ProviderSessionRuntimeRepositoryError,} from "../Errors.ts";import {  ProviderSessionRuntime,  ProviderSessionRuntimeRepository,  type ProviderSessionRuntimeRepositoryShape,} from "../Services/ProviderSessionRuntime.ts"; const ProviderSessionRuntimeDbRowSchema = ProviderSessionRuntime.mapFields(  Struct.assign({    resumeCursor: Schema.NullOr(Schema.fromJsonString(Schema.Unknown)),    runtimePayload: Schema.NullOr(Schema.fromJsonString(Schema.Unknown)),  }),); const decodeRuntime = Schema.decodeUnknownEffect(ProviderSessionRuntime); const GetRuntimeRequestSchema = Schema.Struct({  threadId: ThreadId,}); const DeleteRuntimeRequestSchema = GetRuntimeRequestSchema; function toPersistenceSqlOrDecodeError(sqlOperation: string, decodeOperation: string) {  return (cause: unknown): ProviderSessionRuntimeRepositoryError =>    Schema.isSchemaError(cause)      ? toPersistenceDecodeError(decodeOperation)(cause)      : toPersistenceSqlError(sqlOperation)(cause);} const makeProviderSessionRuntimeRepository = Effect.gen(function* () {  const sql = yield* SqlClient.SqlClient;   const upsertRuntimeRow = SqlSchema.void({    Request: ProviderSessionRuntimeDbRowSchema,    execute: (runtime) =>      sql`        INSERT INTO provider_session_runtime (          thread_id,          provider_name,          adapter_key,          runtime_mode,          status,          last_seen_at,          resume_cursor_json,          runtime_payload_json        )        VALUES (          ${runtime.threadId},          ${runtime.providerName},          ${runtime.adapterKey},          ${runtime.runtimeMode},          ${runtime.status},          ${runtime.lastSeenAt},          ${runtime.resumeCursor},          ${runtime.runtimePayload}        )        ON CONFLICT (thread_id)        DO UPDATE SET          provider_name = excluded.provider_name,          adapter_key = excluded.adapter_key,          runtime_mode = excluded.runtime_mode,          status = excluded.status,          last_seen_at = excluded.last_seen_at,          resume_cursor_json = excluded.resume_cursor_json,          runtime_payload_json = excluded.runtime_payload_json      `,  });   const getRuntimeRowByThreadId = SqlSchema.findOneOption({    Request: GetRuntimeRequestSchema,    Result: ProviderSessionRuntimeDbRowSchema,    execute: ({ threadId }) =>      sql`        SELECT          thread_id AS "threadId",          provider_name AS "providerName",          adapter_key AS "adapterKey",          runtime_mode AS "runtimeMode",          status,          last_seen_at AS "lastSeenAt",          resume_cursor_json AS "resumeCursor",          runtime_payload_json AS "runtimePayload"        FROM provider_session_runtime        WHERE thread_id = ${threadId}      `,  });   const listRuntimeRows = SqlSchema.findAll({    Request: Schema.Void,    Result: ProviderSessionRuntimeDbRowSchema,    execute: () =>      sql`        SELECT          thread_id AS "threadId",          provider_name AS "providerName",          adapter_key AS "adapterKey",          runtime_mode AS "runtimeMode",          status,          last_seen_at AS "lastSeenAt",          resume_cursor_json AS "resumeCursor",          runtime_payload_json AS "runtimePayload"        FROM provider_session_runtime        ORDER BY last_seen_at ASC, thread_id ASC      `,  });   const deleteRuntimeByThreadId = SqlSchema.void({    Request: DeleteRuntimeRequestSchema,    execute: ({ threadId }) =>      sql`        DELETE FROM provider_session_runtime        WHERE thread_id = ${threadId}      `,  });   const upsert: ProviderSessionRuntimeRepositoryShape["upsert"] = (runtime) =>    upsertRuntimeRow(runtime).pipe(      Effect.mapError(        toPersistenceSqlOrDecodeError(          "ProviderSessionRuntimeRepository.upsert:query",          "ProviderSessionRuntimeRepository.upsert:encodeRequest",        ),      ),    );   const getByThreadId: ProviderSessionRuntimeRepositoryShape["getByThreadId"] = (input) =>    getRuntimeRowByThreadId(input).pipe(      Effect.mapError(        toPersistenceSqlOrDecodeError(          "ProviderSessionRuntimeRepository.getByThreadId:query",          "ProviderSessionRuntimeRepository.getByThreadId:decodeRow",        ),      ),      Effect.flatMap((runtimeRowOption) =>        Option.match(runtimeRowOption, {          onNone: () => Effect.succeed(Option.none()),          onSome: (row) =>            decodeRuntime(row).pipe(              Effect.mapError(                toPersistenceDecodeError(                  "ProviderSessionRuntimeRepository.getByThreadId:rowToRuntime",                ),              ),              Effect.map((runtime) => Option.some(runtime)),            ),        }),      ),    );   const list: ProviderSessionRuntimeRepositoryShape["list"] = () =>    listRuntimeRows(undefined).pipe(      Effect.mapError(        toPersistenceSqlOrDecodeError(          "ProviderSessionRuntimeRepository.list:query",          "ProviderSessionRuntimeRepository.list:decodeRows",        ),      ),      Effect.flatMap((rows) =>        Effect.forEach(          rows,          (row) =>            decodeRuntime(row).pipe(              Effect.mapError(                toPersistenceDecodeError("ProviderSessionRuntimeRepository.list:rowToRuntime"),              ),            ),          { concurrency: "unbounded" },        ),      ),    );   const deleteByThreadId: ProviderSessionRuntimeRepositoryShape["deleteByThreadId"] = (input) =>    deleteRuntimeByThreadId(input).pipe(      Effect.mapError(        toPersistenceSqlError("ProviderSessionRuntimeRepository.deleteByThreadId:query"),      ),    );   return {    upsert,    getByThreadId,    list,    deleteByThreadId,  } satisfies ProviderSessionRuntimeRepositoryShape;}); export const ProviderSessionRuntimeRepositoryLive = Layer.effect(  ProviderSessionRuntimeRepository,  makeProviderSessionRuntimeRepository,);