krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Commit bba8b92669

bba8b926692609d51db8d6c45f164cded2fb53ed

parent: 7da97cdb74

Verified · cmc

cmc <hello@cleberg.net> · 2026-10-18 04:01 UTC

Keep the last good feed snapshot when a poll fails

Failures are recorded under "<feed>:error" in feed_snapshots instead of
overwriting the feed's row, so /v1/launches keeps its fetchedAt and
/v1/today keeps serving space weather after a failed poll.

Layout: unified · split

server/src/index.ts +3 −2
@@ -98,13 +98,14 @@ async function launches(env: Env, now: Date): Promise<Response> {
9898 });
9999}
100100
101// Failures are recorded under "<feed>:error" so the last good snapshot and its time survive.
101102async function pollLaunches(env: Env, now: Date): Promise<void> {
102103 let list: Launch[];
103104 try {
104105 list = await fetchUpcoming(env.LL2_API_KEY);
105106 } catch (e) {
106107 console.error("ll2", String(e));
107 await env.DB.prepare("INSERT INTO feed_snapshots (feed, fetched_at, ok) VALUES ('ll2', ?1, 0) ON CONFLICT (feed) DO UPDATE SET fetched_at = ?1, ok = 0").bind(now.toISOString()).run();
108 await env.DB.prepare("INSERT INTO feed_snapshots (feed, fetched_at, ok) VALUES ('ll2:error', ?1, 0) ON CONFLICT (feed) DO UPDATE SET fetched_at = ?1").bind(now.toISOString()).run();
108109 return;
109110 }
110111 const upsert = env.DB.prepare(
@@ -126,7 +127,7 @@ async function pollSpaceWeather(env: Env, now: Date): Promise<void> {
126127 w = await fetchSpaceWeather();
127128 } catch (e) {
128129 console.error("swpc", String(e));
129 await env.DB.prepare("INSERT INTO feed_snapshots (feed, fetched_at, ok) VALUES ('swpc', ?1, 0) ON CONFLICT (feed) DO UPDATE SET fetched_at = ?1, ok = 0").bind(now.toISOString()).run();
130 await env.DB.prepare("INSERT INTO feed_snapshots (feed, fetched_at, ok) VALUES ('swpc:error', ?1, 0) ON CONFLICT (feed) DO UPDATE SET fetched_at = ?1").bind(now.toISOString()).run();
130131 return;
131132 }
132133 await env.DB.prepare(