Skip to content

lifecycle: publish per-instance status tags and an error counter #376

Description

@linkdata

Summary

Have each Jaws instance publish stable dependency tags for its own status metrics. JaWS owns these tags and dirties them itself; applications only attach a published tag to an Element that renders the corresponding metric.

Start with:

  • active Requests;
  • registered Sessions; and
  • a new per-instance atomic error count.

The maintenance loop can sample these metrics, retain the previous sample, and dirty a metric's published tag when the sampled value changes.

Public contract

Expose stable, comparable tags along the lines of:

func (jw *Jaws) ActiveRequestCountTag() any
func (jw *Jaws) SessionCountTag() any
func (jw *Jaws) ErrorCountTag() any

The exact names and concrete representation are open, but each tag must be:

  • unique to both the Jaws instance and the metric;
  • stable for that instance's lifetime; and
  • valid anywhere an ordinary JaWS dependency tag is accepted.

Applications do not maintain counters, install lifecycle callbacks, poll, or call Dirty. They read RequestCounts, SessionCount, or ErrorCount normally and register the tag published by that same Jaws instance.

Maintenance sampling

On each maintenance pass:

  1. perform normal Request and Session maintenance;
  2. take one per-instance snapshot of active Requests, registered Sessions, and the atomic error count;
  3. compare each value with its previous maintenance sample;
  4. retain the new sample; and
  5. after releasing core locks, dirty each published tag whose value changed.

These tags are coalesced state invalidations, not event streams. Several changes between maintenance passes may produce one update, and a value that changes and returns to its previous value between samples need not produce an update. A resulting getter must observe the latest sampled value.

This also gives the feature an explicit update cadence: status Elements converge within the maintenance interval plus the normal dirty-update interval.

Error counter

Add an ErrorCount() uint64-style accessor backed by a per-Jaws atomic counter. Increment it exactly once at a defined point in the JaWS error-reporting path so delegated Request.Log and MustLog calls cannot double-count. Logger latency and a panic in Logger.Error must not affect the count.

Document whether non-nil reports without a configured Logger and reports after shutdown count. The maintenance sampler only needs an atomic load and treats the value like the other metrics.

Additional metric

Pending() is the other existing first-class per-instance lifecycle gauge worth supporting. A published pending-Request tag can use the same maintenance sampling mechanism without adding lifecycle callbacks.

The total value from RequestCounts may also be useful for a status panel. It could have its own tag or share a request-status tag with active and pending counts; keeping one request-status tag makes the public API smaller, while separate tags avoid unrelated rerenders.

Serving state is not useful as an on-change UI tag because stopping Serve also stops delivery. Uptime would dirty continuously, and internal queue depths, subscriptions, and dirty backlogs do not currently have public metric contracts.

Acceptance criteria

  • Real multi-Request tests show that remaining live pages update a tagged active-Request count after another Request connects and disconnects.
  • Session tests cover count changes from creation, AutoSession, close, and maintenance expiry.
  • Concurrent logging tests verify exact atomic counting and error-tag updates under the race detector.
  • Sampling and dirtying preserve the Jaws.mu -> Request.mu -> Session.mu ordering and never call dirty dispatch while a core lock is held.
  • Cross-instance tests prove that changing one Jaws instance cannot dirty Elements registered with another instance's corresponding tag.
  • Documentation states the sampling/coalescing behavior and distinguishes active Requests (running page/WebSocket loops, so tabs count separately) from registered Sessions (which include the normal disconnect grace period).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgoPull requests that update go code

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions