feat: add convex state functions for snapshot persistence
This commit is contained in:
@@ -451,5 +451,8 @@ Use `.env.example` as the source of truth.
|
|||||||
1. Replace `/auth/dev-login` with direct Better Auth UI/OAuth sign-in for public launch.
|
1. Replace `/auth/dev-login` with direct Better Auth UI/OAuth sign-in for public launch.
|
||||||
2. Populate integration keys in Coolify environment for X, Polar, Qwen3 TTS, MinIO, and Convex.
|
2. Populate integration keys in Coolify environment for X, Polar, Qwen3 TTS, MinIO, and Convex.
|
||||||
3. Implement Convex functions named by `CONVEX_STATE_QUERY` and `CONVEX_STATE_MUTATION`.
|
3. Implement Convex functions named by `CONVEX_STATE_QUERY` and `CONVEX_STATE_MUTATION`.
|
||||||
|
- This repository includes `convex/state.ts` and `convex/schema.ts` for defaults:
|
||||||
|
- `state:getLatestSnapshot`
|
||||||
|
- `state:saveSnapshot`
|
||||||
4. Move Better Auth from memory adapter to a persistent production adapter.
|
4. Move Better Auth from memory adapter to a persistent production adapter.
|
||||||
5. Add tracing and external alerting.
|
5. Add tracing and external alerting.
|
||||||
|
|||||||
9
convex/schema.ts
Normal file
9
convex/schema.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { defineSchema, defineTable } from "convex/server";
|
||||||
|
import { v } from "convex/values";
|
||||||
|
|
||||||
|
export default defineSchema({
|
||||||
|
state_snapshots: defineTable({
|
||||||
|
snapshot: v.any(),
|
||||||
|
updatedAt: v.string(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
45
convex/state.ts
Normal file
45
convex/state.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { mutation, query } from "./_generated/server";
|
||||||
|
import { v } from "convex/values";
|
||||||
|
|
||||||
|
export const getLatestSnapshot = query({
|
||||||
|
args: {},
|
||||||
|
handler: async (ctx) => {
|
||||||
|
const latest = await ctx.db
|
||||||
|
.query("state_snapshots")
|
||||||
|
.order("desc")
|
||||||
|
.first();
|
||||||
|
|
||||||
|
return latest
|
||||||
|
? {
|
||||||
|
snapshot: latest.snapshot,
|
||||||
|
updatedAt: latest.updatedAt,
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const saveSnapshot = mutation({
|
||||||
|
args: {
|
||||||
|
snapshot: v.any(),
|
||||||
|
updatedAt: v.string(),
|
||||||
|
},
|
||||||
|
handler: async (ctx, args) => {
|
||||||
|
const latest = await ctx.db
|
||||||
|
.query("state_snapshots")
|
||||||
|
.order("desc")
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (latest) {
|
||||||
|
await ctx.db.patch(latest._id, {
|
||||||
|
snapshot: args.snapshot,
|
||||||
|
updatedAt: args.updatedAt,
|
||||||
|
});
|
||||||
|
return latest._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.db.insert("state_snapshots", {
|
||||||
|
snapshot: args.snapshot,
|
||||||
|
updatedAt: args.updatedAt,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
14
test/convex-functions.test.js
Normal file
14
test/convex-functions.test.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const test = require("node:test");
|
||||||
|
const assert = require("node:assert/strict");
|
||||||
|
const fs = require("node:fs");
|
||||||
|
|
||||||
|
test("convex state functions are present for configured function names", () => {
|
||||||
|
const schema = fs.readFileSync("convex/schema.ts", "utf8");
|
||||||
|
const state = fs.readFileSync("convex/state.ts", "utf8");
|
||||||
|
|
||||||
|
assert.match(schema, /state_snapshots/);
|
||||||
|
assert.match(state, /export const getLatestSnapshot = query/);
|
||||||
|
assert.match(state, /export const saveSnapshot = mutation/);
|
||||||
|
});
|
||||||
@@ -35,3 +35,11 @@ test("env example includes required webhook and credit settings", () => {
|
|||||||
assert.match(envFile, /INCLUDED_CHARS=/);
|
assert.match(envFile, /INCLUDED_CHARS=/);
|
||||||
assert.match(envFile, /WEBHOOK_RPM=/);
|
assert.match(envFile, /WEBHOOK_RPM=/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("convex state function files exist", () => {
|
||||||
|
const schema = fs.readFileSync("convex/schema.ts", "utf8");
|
||||||
|
const state = fs.readFileSync("convex/state.ts", "utf8");
|
||||||
|
assert.match(schema, /defineSchema/);
|
||||||
|
assert.match(state, /getLatestSnapshot/);
|
||||||
|
assert.match(state, /saveSnapshot/);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user