Files
snort/packages/worker-relay/src/migrations.ts

101 lines
2.8 KiB
TypeScript

import { NostrEvent } from "./types";
import { SqliteRelay } from "./sqlite-relay";
import debug from "debug";
const log = debug("SqliteRelay:migrations");
const migrations = [
{ version: 1, script: migrate_v1 },
{ version: 2, script: migrate_v2 },
{ version: 3, script: migrate_v3 },
{ version: 4, script: migrate_v4 },
{ version: 5, script: migrate_v5 },
];
async function migrate(relay: SqliteRelay) {
if (!relay.db) throw new Error("DB must be open");
const res = relay.db.exec("SELECT MAX(version) FROM __migration", { returnValue: "resultRows" });
let currentVersion = (res[0][0] as number | undefined) ?? 0;
for (const { version, script } of migrations) {
if (currentVersion < version) {
log(`Migrating to v${version}`);
await script(relay);
currentVersion = version;
}
}
}
function migrate_v1(relay: SqliteRelay) {
return relay.db?.transaction(db => {
db.exec(
"CREATE TABLE events (\
id TEXT(64) PRIMARY KEY, \
pubkey TEXT(64), \
created INTEGER, \
kind INTEGER, \
json TEXT \
)",
);
db.exec(
"CREATE TABLE tags (\
event_id TEXT(64), \
key TEXT, \
value TEXT, \
CONSTRAINT tags_FK FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE \
)",
);
db.exec("CREATE INDEX tags_key_IDX ON tags (key,value)");
db.exec("insert into __migration values(1, ?)", {
bind: [new Date().getTime() / 1000],
});
});
}
function migrate_v2(relay: SqliteRelay) {
relay.db?.transaction(db => {
db.exec("CREATE INDEX pubkey_kind_IDX ON events (pubkey,kind)");
db.exec("CREATE INDEX pubkey_created_IDX ON events (pubkey,created)");
db.exec("insert into __migration values(2, ?)", {
bind: [new Date().getTime() / 1000],
});
});
}
function migrate_v3(relay: SqliteRelay) {
relay.db?.transaction(db => {
db.exec("CREATE VIRTUAL TABLE search_content using fts5(id UNINDEXED, content)");
const events = db.selectArrays("select json from events where kind in (?,?)", [0, 1]);
for (const json of events) {
const ev = JSON.parse(json[0] as string) as NostrEvent;
if (ev) {
relay.insertIntoSearchIndex(db, ev);
}
}
db.exec("insert into __migration values(3, ?)", {
bind: [new Date().getTime() / 1000],
});
});
}
async function migrate_v4(relay: SqliteRelay) {
relay.db?.transaction(db => {
db.exec("ALTER TABLE events ADD COLUMN seen_at INTEGER");
db.exec("insert into __migration values(4, ?)", {
bind: [new Date().getTime() / 1000],
});
});
}
async function migrate_v5(relay: SqliteRelay) {
relay.db?.transaction(db => {
db.exec("CREATE INDEX seen_at_IDX ON events (seen_at)");
db.exec("insert into __migration values(5, ?)", {
bind: [new Date().getTime() / 1000],
});
});
}
export default migrate;