Package com.mcawful

Class CustomPanelManifestCache

java.lang.Object
com.mcawful.CustomPanelManifestCache

public final class CustomPanelManifestCache extends Object
Memoization layer for CustomPanelManifestCollector's merged JSON response. Holds the last-built CustomPanelManifestCache.CachedResponse (UTF-8 bytes + strong ETag + filesystem signature + last-checked timestamp) in a single volatile reference and rebuilds it lazily when the caller-supplied signature changes.

This file is intentionally domain-agnostic: it knows nothing about manifests, paths, or JSON shape. The collector hands it two callbacks — one that produces the current "fingerprint" of the underlying source (any string that compares-equal when content is unchanged) and one that produces the serialized bytes when a rebuild is needed. That keeps cache-invalidation policy, hashing, and ETag generation in one small, easy-to-audit class while the collector stays focused on validating and merging community manifests. Conditional If-None-Match / 304 handling is done in HttpServerPageHandler.sendCachedBytes(io.netty.channel.ChannelHandlerContext, io.netty.handler.codec.http.FullHttpRequest, byte[], java.lang.String, java.lang.String).

Concurrency: HTTP threads call getOrRefresh(java.util.function.Supplier<java.lang.String>, java.util.function.Supplier<byte[]>) freely. The cache is a single volatile reference replaced atomically; under concurrent rebuilds the worst case is duplicate work (both threads run the supplier), and only one of the resulting CustomPanelManifestCache.CachedResponse objects becomes the next published value — never a torn read.

Author:
mcawful
  • Method Details

    • getOrRefresh

      public static CustomPanelManifestCache.CachedResponse getOrRefresh(Supplier<String> signatureSupplier, Supplier<byte[]> byteBuilder)
      Returns a memoized CustomPanelManifestCache.CachedResponse. Recomputes the signature at most once per CACHE_SIGNATURE_TTL_MILLIS; only invokes byteBuilder when the signature actually changes. Safe under concurrent calls — the cache is a single volatile reference replaced atomically.

      Both suppliers may be invoked on the calling thread. signatureSupplier runs first (and only after the TTL has elapsed); byteBuilder runs only when the signature differs from the previously cached one. Suppliers should never return null.

      Parameters:
      signatureSupplier - produces the current source-fingerprint string; equality with the last cached value short-circuits the rebuild
      byteBuilder - produces the freshly-serialized bytes when a rebuild is needed
      Returns:
      current cached response, recomputed on demand when the signature changes
    • computeStrongEtag

      public static String computeStrongEtag(byte[] bytes)
      Parameters:
      bytes - response body to fingerprint
      Returns:
      strong ETag header value for those bytes