Skip to content

Reduce session expiry scans and add an optional admission cap - #407

Merged
linkdata merged 6 commits into
mainfrom
fix/session-maintenance-396
Sep 25, 2026
Merged

linkdata merged 6 commits into
mainfrom
fix/session-maintenance-396

Conversation

@linkdata

@linkdata linkdata commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

Closes #396.

Changes

  • Sweep expired Sessions every tenth maintenance pass. Request retirement still runs every pass, and Session.Close unregisters immediately.
  • Add an opt-in global Jaws.MaxSessions cap. Admission refuses new Sessions at the limit without evicting existing ones; expired Sessions count until cleanup.
  • Add an opt-in Jaws.MaxSessionsPerIP cap on all registered Sessions per client address bucket. SessionMiddleware returns HTTP 429 when that bucket is full and global capacity remains. Existing Sessions continue to work.
  • Return HTTP 503 from SessionMiddleware when the global cap or another creation failure prevents a required Session. NewSession returns nil without closing an existing cookie Session when admission or cookie publication fails.
  • Document that AutoSession may leave a Request without a Session at the cap; use the middleware where a Session is required.

Both caps default to zero (disabled). Set the per-IP cap below the global cap to reserve capacity for other address buckets. NewSession needs a free slot under each enabled cap to rotate a Session; a refused rotation retains the old Session. Visitors in one bucket share a quota, while clients using multiple addresses can still fill the global cap. Rate-limit Session-creating routes at the proxy.

Verification

  • go generate ./... (no generated changes)
  • go vet ./..., staticcheck ./..., golangci-lint run (via go run ...@v2.14.0), gosec -quiet ./..., go build ./..., gofumpt -l
  • JAWS_REQUIRE_NODE=1 go test -race ./... and JAWS_REQUIRE_NODE=1 go test ./...
  • Focused race tests for capacity refusal, HTTP 429/503, cookie publication, address buckets, rotation at the per-IP cap, and ten-tick expiry sweeping
  • Root-package race coverage: deleteSessionIfCurrentLocked 100% (99.7% package-wide)

Benchmark

BenchmarkJawsMaintenanceSessions measures sequential maintenance passes with 10,000 live Sessions. Apple M5 Max, -count=6 -benchtime=300ms -cpu=1, compared with benchstat:

Before After Change
182.11 µs/op 17.69 µs/op −90.28% (p=0.002)

@linkdata
linkdata merged commit 15e7de2 into main Sep 25, 2026
7 checks passed
@linkdata
linkdata deleted the fix/session-maintenance-396 branch September 25, 2026 16:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session registry has no cap, and every maintenance tick rescans it under jw.mu

1 participant