Skip to content

Add desktop persistent cache, offline circuit-breaker states, and panel freshness badges#48

Merged
koala73 merged 2 commits into
codex/add-tauri-v2-integration-and-configurationfrom
codex/add-fallback-logic-for-unavailable-apis
Feb 13, 2026
Merged

Add desktop persistent cache, offline circuit-breaker states, and panel freshness badges#48
koala73 merged 2 commits into
codex/add-tauri-v2-integration-and-configurationfrom
codex/add-fallback-logic-for-unavailable-apis

Conversation

@koala73

@koala73 koala73 commented Feb 13, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Ensure the app remains useful when cloud APIs are unreachable by providing durable local fallbacks and clearer UI indicators for stale/offline data.
  • Persist recent feed items, latest computed risk snapshots, and stale-tolerant map overlays for desktop builds so a packaged app can operate without network.
  • Surface data freshness and whether values are live, cached, or unavailable in panels so analysts understand what they are seeing.

Description

  • Add a desktop-aware persistent cache service (src/services/persistent-cache.ts) that uses Tauri invoke commands (read_cache_entry / write_cache_entry) with localStorage as a fallback for non-desktop runtimes.
  • Extend the Tauri backend (src-tauri/src/main.rs) to provide file-backed JSON cache storage under app data and register read_cache_entry and write_cache_entry handlers.
  • Wire persistent fallbacks into runtime services: RSS feeds (src/services/rss.ts), cached risk scores (src/services/cached-risk-scores.ts), earthquake overlay data (src/services/earthquakes.ts), and the Insights world-brief snapshot (src/components/InsightsPanel.ts).
  • Enhance circuit-breaker semantics in src/utils/circuit-breaker.ts to track BreakerDataState (modes: live / cached / unavailable) and detect desktop offline mode so callers can show more precise status and use cached fallbacks.
  • Add panel-level data-state badges and helpers in src/components/Panel.ts and apply them to NewsPanel, InsightsPanel, and StrategicRiskPanel, plus styling in src/styles/main.css.
  • Include static resources in desktop bundle config by adding ../data and ../src/config to src-tauri/tauri.conf.json so pre-bundled datasets are available in production desktop builds.

Testing

  • Ran npm run typecheck (tsc --noEmit) which completed successfully.
  • Started the dev server and exercised the UI; captured a screenshot demonstrating panel freshness badges (artifact recorded during the run).
  • cargo check could not complete in this environment due to network/crates.io access being blocked (error: CONNECT tunnel failed / 403), so native Rust/Tauri build verification was not possible here.

Codex Task

@vercel

vercel Bot commented Feb 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
worldmonitor Ready Ready Preview, Comment Feb 13, 2026 6:05am
worldmonitor-startup Ready Ready Preview, Comment Feb 13, 2026 6:05am
worldmonitor-test Ready Ready Preview, Comment Feb 13, 2026 6:05am

Request Review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f241e75b8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src-tauri/src/main.rs
Comment on lines +105 to +109
let mut root: Map<String, Value> = if path.exists() {
let contents = std::fs::read_to_string(&path)
.map_err(|e| format!("Failed to read cache store {}: {e}", path.display()))?;
serde_json::from_str::<Value>(&contents)
.ok()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Serialize cache writes under a lock

write_cache_entry performs an unsynchronized read-modify-write of a single JSON file, so concurrent invoke('write_cache_entry', ...) calls can overwrite each other and drop previously written keys. This can happen during normal startup because multiple services (rss, earthquakes, cached-risk-scores, insights brief) call setPersistentCache in parallel, making persisted fallback data nondeterministically incomplete.

Useful? React with 👍 / 👎.

}));
}, []);

if (live.length > 0) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve successful empty earthquake payloads

This branch treats live.length === 0 as a failure and always falls back to persisted data, so a successful USGS response with zero events (or a valid cached empty result from the breaker) gets replaced with stale historical quakes. That makes the map show outdated incidents instead of the current empty state and prevents the empty snapshot from ever being persisted.

Useful? React with 👍 / 👎.

Comment thread src/services/rss.ts
const CACHE_TTL = 10 * 60 * 1000; // 10 minutes

function toSerializable(items: NewsItem[]): Array<Omit<NewsItem, 'pubDate'> & { pubDate: string }> {
return items.map(item => ({ ...item, pubDate: item.pubDate.toISOString() }));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle invalid RSS dates before ISO serialization

Persisting feed items now calls item.pubDate.toISOString() unconditionally, but malformed RSS pubDate values produce Invalid Date, and toISOString() throws RangeError. In that case fetchFeed drops into the catch path and returns stale/persistent/empty data even though parsing otherwise succeeded, so a single bad timestamp can suppress an entire feed update.

Useful? React with 👍 / 👎.

@koala73
koala73 merged commit f52f4fd into codex/add-tauri-v2-integration-and-configuration Feb 13, 2026
4 checks passed
@koala73
koala73 deleted the codex/add-fallback-logic-for-unavailable-apis branch February 15, 2026 08:09
@SebastienMelki SebastienMelki added the area: desktop Tauri desktop app label Feb 17, 2026
facusturla pushed a commit to facusturla/worldmonitor that referenced this pull request Feb 27, 2026
…el freshness badges (koala73#48)

### Motivation
- Ensure the app remains useful when cloud APIs are unreachable by
providing durable local fallbacks and clearer UI indicators for
stale/offline data.
- Persist recent feed items, latest computed risk snapshots, and
stale-tolerant map overlays for desktop builds so a packaged app can
operate without network.
- Surface data freshness and whether values are `live`, `cached`, or
`unavailable` in panels so analysts understand what they are seeing.

### Description
- Add a desktop-aware persistent cache service
(`src/services/persistent-cache.ts`) that uses Tauri `invoke` commands
(`read_cache_entry` / `write_cache_entry`) with `localStorage` as a
fallback for non-desktop runtimes.
- Extend the Tauri backend (`src-tauri/src/main.rs`) to provide
file-backed JSON cache storage under app data and register
`read_cache_entry` and `write_cache_entry` handlers.
- Wire persistent fallbacks into runtime services: RSS feeds
(`src/services/rss.ts`), cached risk scores
(`src/services/cached-risk-scores.ts`), earthquake overlay data
(`src/services/earthquakes.ts`), and the Insights world-brief snapshot
(`src/components/InsightsPanel.ts`).
- Enhance circuit-breaker semantics in `src/utils/circuit-breaker.ts` to
track `BreakerDataState` (modes: `live` / `cached` / `unavailable`) and
detect desktop offline mode so callers can show more precise status and
use cached fallbacks.
- Add panel-level data-state badges and helpers in
`src/components/Panel.ts` and apply them to `NewsPanel`,
`InsightsPanel`, and `StrategicRiskPanel`, plus styling in
`src/styles/main.css`.
- Include static resources in desktop bundle config by adding `../data`
and `../src/config` to `src-tauri/tauri.conf.json` so pre-bundled
datasets are available in production desktop builds.

### Testing
- Ran `npm run typecheck` (`tsc --noEmit`) which completed successfully.
- Started the dev server and exercised the UI; captured a screenshot
demonstrating panel freshness badges (artifact recorded during the run).
- `cargo check` could not complete in this environment due to
network/crates.io access being blocked (error: CONNECT tunnel failed /
403), so native Rust/Tauri build verification was not possible here.

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_698eb89d5b448333b14174125f76d3c4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: desktop Tauri desktop app codex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants