refacto: use @db/sqlite for better usage
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -35,3 +35,5 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
*.db
|
||||
*.db-journal
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
|
||||
11
deno.json
11
deno.json
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"tasks": {
|
||||
"jetstream:prod": "deno run --allow-net --allow-read --allow-write --allow-env jetstream.ts",
|
||||
"jetstream": "deno run --watch --allow-net --allow-read --allow-write --allow-env jetstream.ts",
|
||||
"server": "deno run --watch --allow-net --allow-read --allow-write --allow-env server.ts",
|
||||
"server:prod": "deno run --allow-net --allow-read --allow-write --allow-env server.ts",
|
||||
"migrate": "deno run --allow-read --allow-write --allow-env src/migrations/init.ts"
|
||||
"jetstream:prod": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi jetstream.ts",
|
||||
"jetstream": "deno run --watch --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi jetstream.ts",
|
||||
"server": "deno run --watch --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi server.ts",
|
||||
"server:prod": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi server.ts",
|
||||
"migrate": "deno run --allow-net --allow-read --allow-write --allow-env --allow-ffi --unstable-ffi src/migrations/init.ts"
|
||||
},
|
||||
"imports": {
|
||||
"@db/sqlite": "jsr:@db/sqlite@^0.13.0",
|
||||
"@oak/oak": "jsr:@oak/oak@^17.2.0",
|
||||
"@skyware/jetstream": "npm:@skyware/jetstream@^0.2.5",
|
||||
"@std/assert": "jsr:@std/assert@1"
|
||||
|
||||
44
deno.lock
generated
44
deno.lock
generated
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"version": "5",
|
||||
"specifiers": {
|
||||
"jsr:@db/sqlite@*": "0.13.0",
|
||||
"jsr:@db/sqlite@0.13": "0.13.0",
|
||||
"jsr:@denosaurs/plug@1": "1.1.0",
|
||||
"jsr:@oak/commons@1": "1.0.0",
|
||||
"jsr:@oak/oak@^17.2.0": "17.2.0",
|
||||
"jsr:@std/assert@1": "1.0.18",
|
||||
@@ -8,14 +11,35 @@
|
||||
"jsr:@std/crypto@1": "1.0.3",
|
||||
"jsr:@std/encoding@1": "1.0.6",
|
||||
"jsr:@std/encoding@^1.0.5": "1.0.6",
|
||||
"jsr:@std/fmt@1": "1.0.9",
|
||||
"jsr:@std/fs@1": "1.0.19",
|
||||
"jsr:@std/http@1": "1.0.12",
|
||||
"jsr:@std/internal@^1.0.12": "1.0.12",
|
||||
"jsr:@std/internal@^1.0.9": "1.0.12",
|
||||
"jsr:@std/media-types@1": "1.1.0",
|
||||
"jsr:@std/path@1": "1.1.4",
|
||||
"jsr:@std/path@1.0": "1.0.9",
|
||||
"jsr:@std/path@^1.1.1": "1.1.4",
|
||||
"npm:@skyware/jetstream@~0.2.5": "0.2.5",
|
||||
"npm:path-to-regexp@^6.3.0": "6.3.0"
|
||||
},
|
||||
"jsr": {
|
||||
"@db/sqlite@0.13.0": {
|
||||
"integrity": "4545c635e0b3d4ddfdc0f2240f932f24b8ad0178e9c2e3a0f9403e7b18ae2fb5",
|
||||
"dependencies": [
|
||||
"jsr:@denosaurs/plug",
|
||||
"jsr:@std/path@1.0"
|
||||
]
|
||||
},
|
||||
"@denosaurs/plug@1.1.0": {
|
||||
"integrity": "eb2f0b7546c7bca2000d8b0282c54d50d91cf6d75cb26a80df25a6de8c4bc044",
|
||||
"dependencies": [
|
||||
"jsr:@std/encoding@1",
|
||||
"jsr:@std/fmt",
|
||||
"jsr:@std/fs",
|
||||
"jsr:@std/path@1"
|
||||
]
|
||||
},
|
||||
"@oak/commons@1.0.0": {
|
||||
"integrity": "49805b55603c3627a9d6235c0655aa2b6222d3036b3a13ff0380c16368f607ac",
|
||||
"dependencies": [
|
||||
@@ -35,14 +59,14 @@
|
||||
"jsr:@std/bytes",
|
||||
"jsr:@std/http",
|
||||
"jsr:@std/media-types",
|
||||
"jsr:@std/path",
|
||||
"jsr:@std/path@1",
|
||||
"npm:path-to-regexp"
|
||||
]
|
||||
},
|
||||
"@std/assert@1.0.18": {
|
||||
"integrity": "270245e9c2c13b446286de475131dc688ca9abcd94fc5db41d43a219b34d1c78",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal"
|
||||
"jsr:@std/internal@^1.0.12"
|
||||
]
|
||||
},
|
||||
"@std/bytes@1.0.4": {
|
||||
@@ -54,6 +78,16 @@
|
||||
"@std/encoding@1.0.6": {
|
||||
"integrity": "ca87122c196e8831737d9547acf001766618e78cd8c33920776c7f5885546069"
|
||||
},
|
||||
"@std/fmt@1.0.9": {
|
||||
"integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0"
|
||||
},
|
||||
"@std/fs@1.0.19": {
|
||||
"integrity": "051968c2b1eae4d2ea9f79a08a3845740ef6af10356aff43d3e2ef11ed09fb06",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal@^1.0.9",
|
||||
"jsr:@std/path@^1.1.1"
|
||||
]
|
||||
},
|
||||
"@std/http@1.0.12": {
|
||||
"integrity": "85246d8bfe9c8e2538518725b158bdc31f616e0869255f4a8d9e3de919cab2aa",
|
||||
"dependencies": [
|
||||
@@ -66,10 +100,13 @@
|
||||
"@std/media-types@1.1.0": {
|
||||
"integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4"
|
||||
},
|
||||
"@std/path@1.0.9": {
|
||||
"integrity": "260a49f11edd3db93dd38350bf9cd1b4d1366afa98e81b86167b4e3dd750129e"
|
||||
},
|
||||
"@std/path@1.1.4": {
|
||||
"integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5",
|
||||
"dependencies": [
|
||||
"jsr:@std/internal"
|
||||
"jsr:@std/internal@^1.0.12"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -156,6 +193,7 @@
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@db/sqlite@0.13",
|
||||
"jsr:@oak/oak@^17.2.0",
|
||||
"jsr:@std/assert@1",
|
||||
"npm:@skyware/jetstream@~0.2.5"
|
||||
|
||||
@@ -77,5 +77,6 @@ jetstream.start();
|
||||
setInterval(() => {
|
||||
if (jetstream.cursor) {
|
||||
saveCursor(jetstream.cursor);
|
||||
console.log(`[jetstream] updated cursor: ${jetstream.cursor}`);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
import { DB } from "https://deno.land/x/sqlite/mod.ts";
|
||||
import { Database } from "@db/sqlite";
|
||||
import type { Note } from "./note.ts";
|
||||
|
||||
export const db = new DB(Deno.env.get("SQLITE_PATH") ?? "notes.db");
|
||||
export const db = new Database(Deno.env.get("SQLITE_PATH") ?? "notes.db");
|
||||
try {
|
||||
const [[journalMode]] = db.query<[string]>("PRAGMA journal_mode=WAL");
|
||||
db.query("PRAGMA busy_timeout=5000");
|
||||
console.log(`[db] journal_mode=${journalMode}, busy_timeout=5000`);
|
||||
db.exec("PRAGMA journal_mode=WAL");
|
||||
db.exec("PRAGMA busy_timeout=5000");
|
||||
const [row] = db.prepare("PRAGMA journal_mode").all<{ journal_mode: string }>();
|
||||
console.log(`[db] journal_mode=${row.journal_mode}, busy_timeout=5000`);
|
||||
} catch (e) {
|
||||
console.error("[db] failed to set PRAGMAs:", e);
|
||||
}
|
||||
|
||||
export const getNotes = (cursor?: string, limit = 20) => {
|
||||
const rows = cursor
|
||||
? db.query<[string, string, string, string, string]>(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE rkey < ? ORDER BY rkey DESC LIMIT ?",
|
||||
[cursor, limit],
|
||||
)
|
||||
: db.query<[string, string, string, string, string]>(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note ORDER BY rkey DESC LIMIT ?",
|
||||
[limit],
|
||||
);
|
||||
type NoteRow = {
|
||||
did: string;
|
||||
rkey: string;
|
||||
title: string;
|
||||
publishedAt: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
const notes = rows.map(([did, rkey, title, publishedAt, createdAt]) => ({
|
||||
did,
|
||||
rkey,
|
||||
title,
|
||||
publishedAt,
|
||||
createdAt,
|
||||
}));
|
||||
export const getNotes = (cursor?: string, limit = 20) => {
|
||||
const notes = cursor
|
||||
? db.prepare(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE rkey < ? ORDER BY rkey DESC LIMIT ?",
|
||||
).all<NoteRow>(cursor, limit)
|
||||
: db.prepare(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note ORDER BY rkey DESC LIMIT ?",
|
||||
).all<NoteRow>(limit);
|
||||
|
||||
return {
|
||||
notes,
|
||||
@@ -36,23 +35,13 @@ export const getNotes = (cursor?: string, limit = 20) => {
|
||||
};
|
||||
|
||||
export const getNotesByDid = (did: string, cursor?: string, limit = 20) => {
|
||||
const rows = cursor
|
||||
? db.query<[string, string, string, string, string]>(
|
||||
const notes = cursor
|
||||
? db.prepare(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE did = ? AND rkey < ? ORDER BY rkey DESC LIMIT ?",
|
||||
[did, cursor, limit],
|
||||
)
|
||||
: db.query<[string, string, string, string, string]>(
|
||||
).all<NoteRow>(did, cursor, limit)
|
||||
: db.prepare(
|
||||
"SELECT did, rkey, title, publishedAt, createdAt FROM note WHERE did = ? ORDER BY rkey DESC LIMIT ?",
|
||||
[did, limit],
|
||||
);
|
||||
|
||||
const notes = rows.map(([did, rkey, title, publishedAt, createdAt]) => ({
|
||||
did,
|
||||
rkey,
|
||||
title,
|
||||
publishedAt,
|
||||
createdAt,
|
||||
}));
|
||||
).all<NoteRow>(did, limit);
|
||||
|
||||
return {
|
||||
notes,
|
||||
@@ -61,35 +50,26 @@ export const getNotesByDid = (did: string, cursor?: string, limit = 20) => {
|
||||
};
|
||||
|
||||
export const deleteNote = ({ did, rkey }: { did: string; rkey: string }) => {
|
||||
db.query("DELETE FROM note WHERE did = ? AND rkey = ?", [did, rkey]);
|
||||
db.exec("DELETE FROM note WHERE did = ? AND rkey = ?", did, rkey);
|
||||
};
|
||||
|
||||
export const getCursor = (): string | undefined => {
|
||||
const rows = db.query<[string]>(
|
||||
const row = db.prepare(
|
||||
"SELECT value FROM state WHERE key = 'cursor'",
|
||||
);
|
||||
return rows[0]?.[0];
|
||||
).get<{ value: string }>();
|
||||
return row?.value;
|
||||
};
|
||||
|
||||
export const saveCursor = (cursor: number) => {
|
||||
db.query(
|
||||
db.exec(
|
||||
"INSERT OR REPLACE INTO state (key, value) VALUES ('cursor', ?)",
|
||||
[String(cursor)],
|
||||
String(cursor),
|
||||
);
|
||||
};
|
||||
|
||||
export const upsertNote = (note: Note) => {
|
||||
const now = new Date().toISOString();
|
||||
const params = [
|
||||
note.title,
|
||||
note.publishedAt ? new Date(note.publishedAt).toISOString() : now,
|
||||
note.createdAt ? new Date(note.createdAt).toISOString() : now,
|
||||
note.did,
|
||||
note.rkey,
|
||||
];
|
||||
console.log(`[db] upsertNote params: ${JSON.stringify(params)}`);
|
||||
|
||||
db.query(
|
||||
db.exec(
|
||||
`
|
||||
INSERT INTO note (
|
||||
title,
|
||||
@@ -104,6 +84,10 @@ export const upsertNote = (note: Note) => {
|
||||
title = excluded.title,
|
||||
publishedAt = excluded.publishedAt
|
||||
`,
|
||||
params,
|
||||
note.title,
|
||||
note.publishedAt ? new Date(note.publishedAt).toISOString() : now,
|
||||
note.createdAt ? new Date(note.createdAt).toISOString() : now,
|
||||
note.did,
|
||||
note.rkey,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "../data/db.ts";
|
||||
|
||||
db.execute(`
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS note (
|
||||
title TEXT NOT NULL,
|
||||
publishedAt DATETIME,
|
||||
@@ -11,7 +11,7 @@ db.execute(`
|
||||
);
|
||||
`);
|
||||
|
||||
db.execute(`
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS state (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL
|
||||
|
||||
Reference in New Issue
Block a user