Commit Graph

5 Commits

Author SHA1 Message Date
Maurice db0fbc1ccd fix(storage): stop deleting covers, place images and journey photos another row may still show
Replacing a trip or list cover, changing or deleting a place or saved-place
image and deleting a journey photo removed the bytes at once, without asking
whether a trip copy, a journey, a saved place or another photo row still
named them (#2924). Those paths now leave the object in place and the reclaim
job removes it once no row names it. A journey photo the user deletes takes
its local photo row with it when nothing else links it, so its bytes become
reclaimable instead of being kept by a row nobody sees.

A place image copied from a trip file is still dropped at once when the
update that would name it fails: that copy was never anyone else's.

Size and warning baselines follow the shrunk files.
2026-11-01 13:59:28 +01:00
Maurice c28604b891 planner: the details refresh reads through a repository, and the form drops what moved out
The fresh lookup behind New place details goes through placeDetailsRepo
(online-only, like the service identity) instead of api/ directly. The form
loses the Translate type and the comment that moved with the head band's
pills, which takes it under its line limit and out of the size baseline; the
maps service suite's test-size entry follows its shorter count.
2026-10-31 03:25:56 +00:00
Vini 7277e35a96 serve each country's regions from its own file, so the server no longer holds them all
The Atlas server no longer keeps the admin-1 regions of every country in memory. Each country's regions are now a pre-gzipped file of their own, sent to the map as they are.

**Why:** `GET /addons/atlas/regions/geo?countries=…` built `admin1Store` (every country's region text, kept until restart), then joined the requested countries, `JSON.parse`d them, and Nest stringified them again. On the 512 MB – 1 GB boxes TREK runs on, the first z≥5 view could OOM the server (same shape as #1576).

**What changes:**
- `server/assets/atlas/admin1/<ISO_A2>.geojson.gz`: 198 files, 14.85 MB, the same 3,447 features as `admin1.geojson.gz`.
- New `GET /addons/atlas/regions/geo/:code` with a Zod contract (`regionGeoParamsSchema` in `@trek/shared`: two letters, any case). It sends the country's file as it is, with `Content-Encoding: gzip` and the current 1-day `Cache-Control`, as `countries/geo` does. A country without regions gets an empty FeatureCollection. Anything that is not two letters gets a 400.
- `useAtlas.ts` fetches one URL per uncached country and still rebuilds the layer once. Each country has a stable URL, so a country evicted by `REGION_CACHE_MAX` comes back from the browser cache.
- `getRegionFeatures` reads only the country it needs. `admin1Store` is removed.
- `?countries=` keeps working for cached PWA clients. It joins the per-country files as bytes, without a parse.
- The migrations are untouched. `admin1.geojson.gz` still ships, only for `Migration20200101021500` and `Migration20200101031500`. This costs ~15 MB of disk in the image and no RAM. `build-atlas-geo.mjs` writes both, and ATLAS-BUNDLE-008 keeps them equal.

**Memory** (real `atlas-geo` module, first z≥5 view over Europe = 49 country codes, JS heap + Buffers):

| | peak | kept after |
|---|---|---|
| before, first view (builds the store) | +372 MB | +61 MB |
| before, later views | +115 MB | 0 |
| after, `/regions/geo/:code` | +4.7 MB | 0 |
| after, legacy `?countries=` | +59 MB | 0 |

**Tests:**
- New: `atlas-region-files.test.ts` (moved from `atlas.service.test.ts`, plus join and dedupe cases), the `regionGeoParamsSchema` spec, ATLAS-BUNDLE-007 (the file format the byte join depends on), ATLAS-BUNDLE-008 (bundle and per-country files are equal), ATLAS-016/017/018 (the new route over HTTP, including the 400).
- The `getVisitedRegions` tests (ATLAS-UNIT-019..024) used to pass only when `getRegionGeo`'s `beforeAll` had built the store first. They now also pass on their own.
- The shared, server and client gates pass. Baselines go down only where this change removed code (`no-console`, `no-explicit-any`, `no-swallowed-catch`, file sizes).

**Trade-offs:**
- A first zoom over Europe sends ~49 small parallel requests instead of 1. Over HTTP/1.1 the browser queues them 6 at a time. The total bytes are the same (4.4 MB gz).
- The per-country URLs are unversioned and cached for a day, like `countries/geo`. After an upgrade that changes a country's regions, a browser can show the old shapes for up to 24 h.

Approved on Discord in #github-pr: <paste the thread link here>
Related: #1576, #2559

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

- [ ] I have read the [Contributing Guidelines](https://github.com/liketrek/TREK/wiki/Contributing)
- [ ] My branch is [up to date with `dev`](https://github.com/liketrek/TREK/wiki/Development-environment#3-keep-your-fork-up-to-date)
- [x] This PR targets the `dev` branch, not `main` *(wiki-only PRs are exempt)*
- [x] I have tested my changes locally
- [x] I have added/updated tests that prove my fix is effective or that my feature works
- [x] I have updated documentation if needed
2026-10-31 00:40:23 +00:00
Maurice cbca3b2851 test(maps): the overpass place names cases get a suite of their own, the service suite back under its size 2026-10-21 13:53:24 +02:00
Maurice 4427c435a8 ci(server): module mocks, hand-built services and test file length in tests/ may only shrink
lint:test-mocks counts vi.mock/vi.doMock of src/config, src/nest/realtime and src/db per file under tests/, lint:test-new-service counts new XService(/new XRepository( there with every class whose constructor takes nothing allowed (derived from src/ and tests/helpers/), and lint:size holds files under tests/ to 2000 lines against their own baseline. Both counters share scripts/lib/count-ratchet.mjs, which gains a prepare hook for a check that reads the tree first. The three run as steps of the existing server lint job; the CLAUDE.md files and the module guide describe the test helpers they point to.
2026-10-10 20:16:12 +02:00