Skip to content

8.0.4

Latest

Choose a tag to compare

@hugithordarson hugithordarson released this 04 Sep 13:21
· 3 commits to master since this release

The theme of this release: the page cache became one honest, observable, self-defending thing β€” and AjaxSlim finished its pre-adoption hardening.

Page cache: measured and self-defending

  • Reuse statistics β€” every restore records the instance's idle time and LRU depth into app-wide histograms on the session cache overview page, with a reverse-cumulative "broken by bound" column that reads directly as "a TTL or cap at this bound would have broken N restores". Restores broken by session expiry β€” invisible to in-cache counters β€” are counted too, at the restoreSessionWithID choke point. A notable-reaches list names the pages users actually come back for.
  • ERXPageCachePressureValve β€” caches trim themselves under real memory pressure instead of paying an always-on TTL: when a GC completes with old gen still above 85%, sessions are trimmed to 50% of the page cache cap (LRU-first); above 90%, to 25%. Never below a session's current page. Push-based (collection-usage notifications β€” no polling, no forced GCs), throttled, loudly logged, surfaced on the overview page and the startup banner. Thresholds and fractions are properties; er.extensions.ERXPageCachePressureValve.enabled=false opts out. It also finally subscribes to ERXLowMemoryHandler's long-unsubscribed low-memory notifications.

AjaxSlim

  • AjaxExpansion β€” the disclosure-section element rebuilt on native <details>/<summary>: four bindings, instant client-side toggling, and open state that survives morphs of enclosing containers (each toggle pings the server, so every re-render carries the correct open attribute). Legacy effect bindings and lazy content loading are gone.
  • AjaxModalContainer closes on backdrop click β€” clicks inside the dialog's box, and drags that merely end outside, never dismiss.
  • Pre-adoption hardening: an open modal survives morphs of enclosing regions; a full-document ajax response (the expired-session shape) is diverted to the error contract instead of being swallowed or morphed into a container; AjaxSelfUpdatingContainer.action no longer fires when the container is merely another trigger's render target; field observers no longer fire into a real form submission; focus survives tabbing out of a field that triggers a morph, including multi-container updates.
  • Full .apiext adoption β€” typed cross-binding constraints, defaults, deprecations, unknown-attribute and content policies on every element.

Development mode

  • /eval β€” a JShell REPL inside the running app (loopback-only), and /problems β€” the rendered binding-error boxes as JSON; both aligned with ng-objects' dev endpoints. Dev-loop machinery consolidated under er.extensions.dev; apps report runtime and pid to the dev server; the launch banner prints external direct-connect URLs.

Dependencies

  • Releases now depend only on published artifacts: parsley pinned to 1.6.0, and the ng-core compile dependency severed by temporarily vendoring four small dev-mode classes into er.extensions.dev.ng (each file documents its deletion condition). Also: json 20260719, junit 6.1.3, vermilingua 1.1.7.

Smaller things

  • The empty-update 500 explains itself instead of shrugging; experimental SVG-aware ERXWOImage (opt-in); ERXWOTextField cleanups; RouteTable names its unhandled-response userInfo key.