aboutsummaryrefslogtreecommitdiffstats
path: root/feed/service.js
diff options
context:
space:
mode:
Diffstat (limited to 'feed/service.js')
-rw-r--r--feed/service.js29
1 files changed, 29 insertions, 0 deletions
diff --git a/feed/service.js b/feed/service.js
new file mode 100644
index 0000000..304b40f
--- /dev/null
+++ b/feed/service.js
@@ -0,0 +1,29 @@
+import { SimplePool } from 'nostr-tools/pool';
+import { readFile, mkdir, writeFile, rename } from 'node:fs/promises';
+import { dirname } from 'node:path';
+import { buildSnapshot, createSnapshotCache, PUBLIC_FEED_RELAYS } from './cache.js';
+
+export async function startFeedCache() {
+ const file = process.env.FEED_CACHE_FILE || new URL('../db/public-feed.json', import.meta.url).pathname;
+ let initial = null;
+ try {
+ const data = JSON.parse(await readFile(file, 'utf8'));
+ if (data.version === 1 && Number.isFinite(data.generatedAt) && Array.isArray(data.notes) && data.notes.length && Array.isArray(data.profiles)) initial = data;
+ } catch {}
+ // SimplePool verifies signatures and matches filters before accepting events.
+ const pool = new SimplePool();
+ const cache = createSnapshotCache({
+ initial,
+ build: () => buildSnapshot((filter) => pool.querySync(PUBLIC_FEED_RELAYS, filter, { maxWait: 4500 })),
+ save: async (data) => {
+ await mkdir(dirname(file), { recursive: true });
+ await writeFile(file + '.tmp', JSON.stringify(data));
+ await rename(file + '.tmp', file);
+ },
+ onError: (e) => console.warn('[public feed]', e.message),
+ });
+ cache.read(); // warm before the first visitor, reusing the persisted snapshot
+ const timer = setInterval(() => cache.read(), 15_000);
+ timer.unref();
+ return cache;
+}