Skip to content

RadarStore: use mounted data_dir so deploys don't wipe radars#37

Merged
fleveque merged 1 commit into
mainfrom
fix/radar-store-data-dir
May 25, 2026
Merged

RadarStore: use mounted data_dir so deploys don't wipe radars#37
fleveque merged 1 commit into
mainfrom
fix/radar-store-data-dir

Conversation

@fleveque

Copy link
Copy Markdown
Owner

Bug

After the radar PR shipped, every Pulse deploy wiped users' radar listings — they had to re-opt-in (re-toggle Share Radar in Quantic, or wait for the next `radar.updated` event) to see their radar reappear. Portfolios survived deploys fine.

Root cause

RadarStore was the odd one out among DETS-using modules: it called `:code.priv_dir(:pulse)` directly to locate `radars.dets`, which resolves inside the release directory. Kamal rebuilds the release per image, so the file was always empty after a deploy.

Every other DETS user (`Pulse.Store`, `Pulse.Analytics`, `Pulse.RadarAnalytics`) reads `data_dir` from app env, which `config/runtime.exs` overrides via the `DATA_DIR` env var → `/app/data` in prod, a Kamal-mounted volume that persists across deploys.

Fix

Make RadarStore.init/1 read the configurable `data_dir` and join `radars.dets` onto it. One-line equivalence with the other modules.

  • Prod: resolves to `/app/data/radars.dets` (mounted volume — survives deploys).
  • Dev: stays at `priv/data/radars.dets` (default config).
  • Test: `config/test.exs` already overrides `data_dir` to `priv/data/test`.

Migration note for this deploy

This deploy will start with an empty `/app/data/radars.dets` because the file was never written to that location before. The radar workers currently in memory (re-opted-in after the last deploy) live only in the old `priv/data/` path inside the running container, which goes away when the new image takes over.

Two options to preserve current radar state across this deploy:

  1. Easiest — accept one more re-opt cycle: deploy this PR, then ask affected users to toggle Share Radar off/on once. From then on, radars survive every future deploy.
  2. Manual save — before the new container takes over, copy the in-container file to the volume:
    ```
    kamal app exec --reuse -- cp /app/lib/pulse-/priv/data/radars.dets /app/data/radars.dets
    ```
    (Path inside the release tree — check with `kamal app exec --reuse -- find /app -name radars.dets` first.)

Test plan

  • mix test — 44 / 44
  • mix format --check-formatted — clean
  • mix compile --warnings-as-errors — clean
  • Manual after deploy: verify `/app/data/radars.dets` exists and grows as users opt in
  • Manual: kill + restart the Pulse container, confirm `RadarStore.restore_all` restores the workers

🤖 Generated with Claude Code

After the radar PR shipped, every deploy wiped users' radar listings —
they had to re-opt-in to repopulate. Portfolios survived because
Pulse.Store reads `data_dir` from config and `config/runtime.exs`
points that at `DATA_DIR=/app/data`, a Kamal-mounted volume. RadarStore
was the odd one out: it called `:code.priv_dir(:pulse)` directly,
which resolves inside the release directory — rebuilt per image, so
the file was always empty after a deploy.

Match the pattern used by `Pulse.Store`, `Pulse.Analytics`, and
`Pulse.RadarAnalytics`: read `data_dir` from app env and join
`radars.dets` onto it. In prod that resolves to
`/app/data/radars.dets` (volume-backed); in dev it stays at
`priv/data/radars.dets`; in test the data_dir is already overridden
in `config/test.exs`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fleveque fleveque merged commit 8ffb899 into main May 25, 2026
1 check passed
@fleveque fleveque deleted the fix/radar-store-data-dir branch May 25, 2026 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant