search for standard sites pub-search.waow.tech
search zig blog atproto
11
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: dashboard zeros — local SQLite missing embedded_at column

fetchLocal() queried COUNT(*) WHERE embedded_at IS NOT NULL, but the
local schema never had that column. Every dashboard request failed,
falling through to turso batch (which also returned zeros).

- add embedded_at column migration to LocalDb schema
- sync embedded_at from turso in full and incremental sync
- add logfire warnings when fetchLocal fails or turso batch returns no rows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz 35a7f427 17a5e222

+13 -5
+7 -1
backend/src/dashboard.zig
··· 2 2 const json = std.json; 3 3 const Allocator = std.mem.Allocator; 4 4 const db = @import("db/mod.zig"); 5 + const logfire = @import("logfire"); 5 6 const timing = @import("metrics.zig").timing; 6 7 7 8 // JSON output types ··· 73 74 if (db.getLocalDb()) |local| { 74 75 if (fetchLocal(alloc, local)) |result| { 75 76 return result; 76 - } else |_| {} 77 + } else |err| { 78 + logfire.warn("dashboard: fetchLocal failed: {s}, falling back to turso batch", .{@errorName(err)}); 79 + } 77 80 } 78 81 79 82 // fall back to Turso (slow) ··· 91 94 92 95 // extract stats (query 0) 93 96 const stats_row = batch.getFirst(0); 97 + if (stats_row == null) { 98 + logfire.warn("dashboard: turso batch returned no stats row", .{}); 99 + } 94 100 const started_at = if (stats_row) |r| r.int(4) else 0; 95 101 const searches = if (stats_row) |r| r.int(2) else 0; 96 102 const publications = if (stats_row) |r| r.int(1) else 0;
+1
backend/src/db/LocalDb.zig
··· 241 241 242 242 // migrations for existing local DBs 243 243 c.exec("ALTER TABLE documents ADD COLUMN indexed_at TEXT", .{}) catch {}; 244 + c.exec("ALTER TABLE documents ADD COLUMN embedded_at TEXT", .{}) catch {}; 244 245 } 245 246 246 247 /// Row adapter matching result.Row interface (column-indexed access)
+5 -4
backend/src/db/sync.zig
··· 40 40 // fetch from Turso (no lock held — search can use local DB) 41 41 var result = turso.query( 42 42 \\SELECT uri, did, rkey, title, content, created_at, publication_uri, 43 - \\ platform, source_collection, path, base_path, has_publication, indexed_at 43 + \\ platform, source_collection, path, base_path, has_publication, indexed_at, embedded_at 44 44 \\FROM documents 45 45 \\ORDER BY uri 46 46 \\LIMIT 500 OFFSET ? ··· 236 236 { 237 237 var result = turso.query( 238 238 \\SELECT uri, did, rkey, title, content, created_at, publication_uri, 239 - \\ platform, source_collection, path, base_path, has_publication, indexed_at 239 + \\ platform, source_collection, path, base_path, has_publication, indexed_at, embedded_at 240 240 \\FROM documents 241 241 \\WHERE indexed_at >= ? 242 242 \\ORDER BY indexed_at ··· 278 278 conn.exec( 279 279 \\INSERT OR REPLACE INTO documents 280 280 \\(uri, did, rkey, title, content, created_at, publication_uri, 281 - \\ platform, source_collection, path, base_path, has_publication, indexed_at) 282 - \\VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 281 + \\ platform, source_collection, path, base_path, has_publication, indexed_at, embedded_at) 282 + \\VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 283 283 , .{ 284 284 row.text(0), // uri 285 285 row.text(1), // did ··· 294 294 row.text(10), // base_path 295 295 row.int(11), // has_publication 296 296 row.text(12), // indexed_at 297 + row.text(13), // embedded_at 297 298 }) catch |err| { 298 299 return err; 299 300 };