Repository navigation
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 = IntegritySHA256verifies 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.Freshenretains the body digest, and private metadata never becomes an HTTP response header. - Shared staging admission:
StagingBudget,StagingLease, andStageKindlet 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.ErrStagingBudgetExceededsupportserrors.Is. HandlerTempDirselects the staging directory; Linux/macOS retain an anonymous file descriptor through background publication. - Trusted logical identities:
HandlerOptions.RequestKeylets 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:
MissCoordinatorandMissLeaselet applications coordinate misses across handler instances. Storage is rechecked after acquiring ownership, and the lease is retained through asynchronous publication. OptionalContextStorepreserves 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 theX-Cache-Stagingtrailer.ADMITTEDdescribes 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
Varypolicy changes. Preserve the actual upstream selection identity when client validators participate inVary, 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
Varykeys, distinguish absent and empty values, and honor combinedVaryresponse fields. - Calculate
Expiresfreshness relative to the response date and treat malformedExpiresas 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/ExtendedCacheinterfaces remain unchanged.CacheConfigandHandlerOptionsgain fields; applications using positional struct literals should switch to keyed literals. Varykeys 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-Varybase keys are unchanged. No manual cache purge is required, but allow for temporary origin traffic while variant caches warm again.- Enabling
IntegritySHA256makes 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. NewVFSCacherequires open readers to retain their contents across same-path replacement. For ordinary OS files, useNewDiskCache, 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
/v4module.
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