A fullstack app for indexing standard.site documents
at main 66 lines 1.7 kB view raw
1import { Hono } from "hono"; 2import { cors } from "hono/cors"; 3import type { Bindings } from "./types"; 4import { health, webhook, feed, stats, records, admin, rss } from "./routes"; 5import { processDocument } from "./utils"; 6 7const app = new Hono<{ Bindings: Bindings }>(); 8 9// Middleware 10app.use("*", cors()); 11 12// Mount routes 13app.route("/health", health); 14app.route("/webhook", webhook); 15app.route("/feed", feed); 16app.route("/stats", stats); 17app.route("/records", records); 18app.route("/admin", admin); 19app.route("/rss.xml", rss); 20 21// 404 handler 22app.notFound((c) => { 23 return c.json({ error: "Not found" }, 404); 24}); 25 26// Export for Cloudflare Workers 27export default { 28 fetch: app.fetch, 29 async scheduled(event: ScheduledEvent, env: Bindings, ctx: ExecutionContext) { 30 const batchSize = 50; 31 // Select stale documents 32 const { results } = await env.DB.prepare( 33 `SELECT did, rkey FROM resolved_documents 34 WHERE stale_at < datetime('now') OR stale_at IS NULL 35 LIMIT ?`, 36 ) 37 .bind(batchSize) 38 .all<{ did: string; rkey: string }>(); 39 40 if (results && results.length > 0) { 41 const messages = results.map((row) => ({ 42 body: { 43 did: row.did, 44 collection: "site.standard.document", 45 rkey: row.rkey, 46 }, 47 })); 48 49 // Send to queue 50 await env.RESOLUTION_QUEUE.sendBatch(messages); 51 console.log(`Queued ${messages.length} documents for resolution`); 52 } 53 }, 54 async queue(batch: MessageBatch<any>, env: Bindings) { 55 for (const message of batch.messages) { 56 try { 57 const { did, collection, rkey } = message.body; 58 await processDocument(env.DB, did, collection, rkey); 59 message.ack(); 60 } catch (error) { 61 console.error("Queue processing error:", error); 62 message.retry(); 63 } 64 } 65 }, 66};