Skip to content

v4.1.0 — Cache integrity, staging, coordination and safe upgrades

Latest

Choose a tag to compare

@soulteary soulteary released this 12 Oct 23:02
v4.1.0

This minor release adds optional cache integrity, temporary-storage admission, and application coordination APIs, alongside the cache correctness fixes merged in #22 and #23 and safe migration of persisted Vary entries in #25.

New capabilities

  • Verified cache entries: opt-in CacheConfig.Integrity = IntegritySHA256 verifies the body, size, key, HTTP status/headers, and private generation metadata before returning a hit. Corrupt entries become misses and are discarded only if they still match the observed generation. Freshen retains the body digest, and private metadata never becomes an HTTP response header.
  • Shared staging admission: StagingBudget, StagingLease, and StageKind let an application account for overlapping handler response copies and native disk body/header stages. Admission is nonblocking; a refused stage preserves the previous committed entry and the client still receives the complete origin response. ErrStagingBudgetExceeded supports errors.Is. Handler TempDir selects the staging directory; Linux/macOS retain an anonymous file descriptor through background publication.
  • Trusted logical identities: HandlerOptions.RequestKey lets an application select a cache key without rewriting the upstream URL. The same policy applies to unsafe-method invalidation targets, with same-origin restrictions retained. Policy failures return 400.
  • Fill ownership hooks: MissCoordinator and MissLease let applications coordinate misses across handler instances. Storage is rechecked after acquiring ownership, and the lease is retained through asynchronous publication. Optional ContextStore preserves ownership/fencing context values during background writes; failed or expired acquisition returns 503 instead of issuing an uncoordinated fill.
  • Staging visibility: with a handler budget, early admission refusal is reported as X-Cache: SKIP. Admitted HTTP/1.1 and HTTP/2 body responses expose the final handler-stage result through the X-Cache-Staging trailer. ADMITTED describes handler staging only; subsequent asynchronous cache storage can still fail.

Cache correctness

  • Reuse full conditional validation responses without discarding their bodies, while preserving the client's original ETag/date conditions, range handling, redirects, errors, and trailers.
  • Rebuild discovery and variant entries when the normalized Vary policy changes. Preserve the actual upstream selection identity when client validators participate in Vary, including HEAD-to-GET fallback.
  • Fence selected predecessors before validation/replacement so failed, uncacheable, or unstorable replacements cannot leave an old response reusable. Explicit invalidation remains effective even when a client allows max-stale.
  • Protect multi-key publication, reject freshening a replaced generation, and bind opaque-backend freshness evidence to each retrieval. This also covers equal/decreasing clocks, native disk restart, and coordinated peer publication.
  • Reserve concurrent capacity growth, including metadata, so overlapping stores cannot exceed MaxSize. Generic VFS readers coordinate with same-key publication while unrelated keys remain streamable.
  • Preserve every request field line in Vary keys, distinguish absent and empty values, and honor combined Vary response fields.
  • Calculate Expires freshness relative to the response date and treat malformed Expires as already stale. Internal coordinated rechecks retain integrity/LRU behavior without inflating built-in public cache hit/miss counters.

Upgrade notes

  • Integrity verification, staging budgets, logical key policies, and cross-instance coordination are disabled by default. Existing exported function/method signatures and the required Cache/ExtendedCache interfaces remain unchanged. CacheConfig and HandlerOptions gain fields; applications using positional struct literals should switch to keyed literals.
  • Vary keys use a separate versioned namespace, preventing old raw header values from colliding with the new field-line encoding. Previously persisted variants become safe misses and are refetched lazily; non-Vary base keys are unchanged. No manual cache purge is required, but allow for temporary origin traffic while variant caches warm again.
  • Enabling IntegritySHA256 makes legacy entries without private digests miss and adds a complete body read to each retrieval. It detects accidental corruption, not authenticity against an attacker who can rewrite records and recompute hashes. Previously verified records are still checked when read in the default mode; new default-mode writes use the legacy format.
  • With a handler staging budget, HTTP/1.1 body responses use chunked framing so the final admission trailer can be delivered; HTTP/2 retains Content-Length. Budgeted HTTP/1.0, HEAD, and bodyless origin responses bypass new staging. Existing hits remain usable, and responses without a handler budget retain their framing.
  • Coordination hooks do not implement a distributed lock, shared LRU accounting, cross-process storage atomicity, or backend fencing. Applications sharing a disk directory must provide storage-operation locks and set DisableStagingSweep: true; orphan stages then require offline cleanup with all instances stopped. Expiring remote ownership additionally requires fenced publication.
  • NewVFSCache requires open readers to retain their contents across same-path replacement. For ordinary OS files, use NewDiskCache, whose atomic rename preserves open readers. Custom VFS backends remain responsible for immutable read handles and accounting for their own write buffers.

Dependencies and compatibility

  • Pin the released vfs-kit v1.4.5, replacing the interim prerelease commit dependency. This includes the fix that prevents an old read-only memory handle from restoring stale data when it closes.
  • logger-kit/v3 and metrics-kit/v3 remain at v3.0.2; Prometheus client_golang remains at v1.25.0.
  • The module path remains github.com/soulteary/httpcache-kit/v4; the minimum Go version remains 1.27.2.
  • The English and Chinese quick-start examples now import the current /v4 module.

Regression coverage was expanded for conditional responses, Vary selection, corruption, staging refusal/cleanup, cancellation, ownership expiry, concurrent mutation/publication, capacity pressure, restart, and peer-instance freshness.

Validation

  • The refreshed Linux race report records 455 passing tests, one skipped test, and 95.78% statement coverage (2404 of 2510 statements).
  • Go Report Card is A+ (100%), with all six checks complete and zero reported issues.
  • Full race tests, static analysis, lint, dependency security scanning, module consistency, module-path checks, and root/Prometheus package isolation pass.

Full changelog: v4.0.2...v4.1.0