1 — Timeseries split

- writer.py: timeseries is now written to {id}.timeseries.json as a separate file. The detail JSON gets a timeseries_url field instead. finalize_pending and cleanup_pending handle the extra file.
  - merge.py (merge_one): symlinks the .timeseries.json file alongside the detail JSON. merge_all already handles it transparently (the .timeseries.json stem doesn't match any activity
  ID in to_merge, so it falls through to the symlink branch).
  - types.ts: timeseries is now timeseries?: Timeseries | null, and timeseries_url?: string | null added.
  - dataloader.ts: new loadTimeseries(url, detailUrl, base) function that resolves paths correctly in both single- and multi-user modes (uses the fetched detail URL's directory as the base).
  - ActivityDetail.svelte: loads timeseries separately after detail loads; uses detail.timeseries for IDB activities (embedded) or fetches via detail.timeseries_url for server activities. Charts show a pulse placeholder while loading.

 2 — GZip

  - GZipMiddleware (min 1 KB) added to both bincio/serve/server.py and bincio/edit/server.py — all API JSON responses are now gzip-compressed.
  - For static files (the big timeseries JSONs), nginx should be configured with gzip on; gzip_types application/json application/geo+json; — no code change needed on the server side.

  Net effect: opening an activity page now fetches ~1.4 KB (detail) instead of ~586 KB. The timeseries fetches ~60–150 KB gzip-compressed shortly after (it loads concurrently with the map rendering).
This commit is contained in:
Davide Scaini
2026-04-09 14:01:02 +02:00
parent 76b7b9ac7e
commit 8118f6f316
7 changed files with 90 additions and 11 deletions
+8
View File
@@ -109,6 +109,14 @@ def merge_one(data_dir: Path, activity_id: str) -> None:
needs_merge = has_sidecar or bool(image_files)
# Symlink the timeseries file (never merged — always points to the extract output)
ts_src = acts_dir / f"{activity_id}.timeseries.json"
ts_dest = merged_acts / f"{activity_id}.timeseries.json"
if ts_dest.exists() or ts_dest.is_symlink():
ts_dest.unlink()
if ts_src.exists():
ts_dest.symlink_to(ts_src.resolve())
# Remove the old dest (symlink or file) before writing the new one
if dest.exists() or dest.is_symlink():
dest.unlink()