fix(sync): survive push heap exhaustion and instrument the push path

Run 4 (2026-07-13): remote.push() consumed ~6 MB of PSRAM over 66 s and
the UI thread aborted on Frame::new_white's per-draw vec![0xFF; 26928].
Run 5 confirmed the UI now survives, but the push still exhausts both
pools (a ~7 KB inflateInit fails inside the pack build) and the heap
telemetry never fired — hence the telemetry rework.

- display/editor: Editor::draw_into() renders into a caller-owned
  Frame; main.rs keeps two boot-time frames (shown/back) and mem::swaps
  on success, so steady-state repaints never allocate.
- git_sync: odb cache capped at 1 MB via raw libgit2-sys opts (git2
  0.20 doesn't wrap the total cap); log_push_heap at pre-push,
  post-push and push-failure with largest-PSRAM-block and per-pool
  min-evers; pack_progress logging is now time-gated (2 s) — the
  count gate (+256 objects) never fired because AddingObjects reports
  total=0 and a small push inserts only dozens of objects.
- editor: empty/whitespace snippets file parses as 0 snippets instead
  of a JSON error at boot.
- build.rs: refuse a git-feature build with unset TW_* publish vars —
  a bare `cargo build --features git` baked empty creds and produced a
  firmware whose :sync could never work.
This commit is contained in:
Julien Calixte
2026-07-13 21:04:18 +02:00
parent 05706478a2
commit f79d13453a
6 changed files with 182 additions and 23 deletions

View File

@@ -110,7 +110,7 @@ esp-idf-svc = { git = "https://github.com/esp-rs/esp-idf-svc.git" }
# do; `build-light` doesn't, so the component is an empty no-op). git2/libgit2-sys
# run in system mode (LIBGIT2_NO_VENDOR=1) purely for the Rust bindings, with
# default features off to avoid dragging in openssl-sys/libssh2-sys.
git = ["dep:git2"]
git = ["dep:git2", "dep:libgit2-sys"]
[dependencies]
anyhow = "1"
@@ -124,6 +124,11 @@ keymap = { path = "../keymap" }
editor = { path = "../editor" }
display = { path = "../display" }
git2 = { version = "0.20", default-features = false, optional = true }
# Already in the tree under git2 (same system-mode build); named directly for
# the raw `git_libgit2_opts` calls git2 doesn't wrap — the odb-cache cap
# (GIT_OPT_SET_CACHE_MAX_SIZE) and cache telemetry (GIT_OPT_GET_CACHED_MEMORY)
# that git_sync sets against the run-4 push OOM (2026-07-13).
libgit2-sys = { version = "0.18", default-features = false, optional = true }
esp-idf-svc = { version = "0.52.1", features = ["critical-section", "embassy-time-driver", "embassy-sync"] }
# Remove `generic-queue-8` if you plan to use `embassy-time` WITH `embassy-executor`
embassy-time = { version = "0.5", features = ["generic-queue-8"] }