Cache System

Overview

The cache system uses a dual-layer architecture to minimize network requests and improve performance.

Exports:

  • lighty_loaders::utils::cache::Cache

  • lighty_loaders::utils::cache::CachedData

Two-Layer Architecture

Layer 1: Raw Version Cache

Stores complete, unparsed data from external APIs.

Purpose: Avoid redundant API calls Key: Version identifier (String) Value: Raw data (e.g., JSON struct) TTL: 1 hour (configurable via Query::cache_ttl())

Example keys:

  • "vanilla-1.21.1"

  • "fabric-1.21.1-0.16.9"

  • "quilt-1.21.1-0.27.1"

Layer 2: Query Cache

Stores extracted, processed metadata for specific queries.

Purpose: Avoid re-parsing/re-processing raw data Key: QueryKey<Q> (version + query type) Value: Arc<VersionMetaData> TTL: 1 hour (configurable via Query::cache_ttl_for_query())

Example keys:

Data Flow

spinner

Cache Implementation

CachedData Structure

Cache Type

TTL Configuration

Default TTL

Per-Query TTL

Cache Behavior

First Request (Cold Cache)

What happens:

  1. Check query cache → Miss

  2. Check raw cache → Miss

  3. Fetch from Mojang API → https://piston-meta.mojang.com/...

  4. Parse JSON → VanillaMetaData

  5. Store in raw cache (key: "vanilla-1.21.1")

  6. Extract metadata → Version

  7. Store in query cache (key: QueryKey { version: "vanilla-1.21.1", query: VanillaBuilder })

  8. Return Arc<VersionMetaData>

Second Request (Warm Cache)

What happens:

  1. Check query cache → Hit!

  2. Return cached Arc<VersionMetaData>

Different Query (Partial Cache)

What happens:

  1. Check query cache (key: QueryKey { version: "vanilla-1.21.1", query: Libraries }) → Miss

  2. Check raw cache (key: "vanilla-1.21.1") → Hit!

  3. Extract libraries from cached raw data

  4. Store in query cache

  5. Return Arc<VersionMetaData>

After TTL Expiry

What happens:

  1. Check query cache → Expired (TTL exceeded)

  2. Check raw cache → Expired (TTL exceeded)

  3. Fetch from API again

  4. Store both caches

  5. Return data

Event Integration

Cache hits/misses emit events:

Performance Metrics

Typical Latencies

Operation
Cold Cache
Warm Cache
Improvement

Vanilla metadata

~500ms

~1ms

500x

Fabric metadata

~800ms

~1ms

800x

Libraries only

~300ms

~1ms

300x

Multiple queries

~500ms first, ~1ms rest

~1ms all

Massive

Cache Hit Rates

In typical usage:

  • First launch: 0% hit rate (cold cache)

  • Subsequent launches: 95%+ hit rate

  • After 1 hour: Gradual decrease as caches expire

Thread Safety

All cache operations are thread-safe:

  • Uses Arc<RwLock<HashMap>>

  • Read locks for queries (multiple concurrent reads allowed)

  • Write locks for insertions (exclusive access)

  • No deadlocks (short-lived locks)

Memory Management

Cache Size

Caches grow with unique versions:

  • Each version has 1 raw cache entry

  • Each version/query combination has 1 query cache entry

Example:

  • 5 versions × 1 query each = 5 raw + 5 query entries

  • 1 version × 6 queries = 1 raw + 6 query entries

Cleanup

Expired entries are not automatically removed. They're replaced on next access or remain until process ends.

For long-running processes, consider periodic cleanup (not currently implemented).

Cache Keys

Raw Cache Keys

Format: "{loader}-{minecraft_version}[-{loader_version}]"

Examples:

  • "vanilla-1.21.1"

  • "fabric-1.21.1-0.16.9"

  • "quilt-1.21.1-0.27.1"

  • "neoforge-1.21.1-21.1.80"

Query Cache Keys

Examples:

Debugging Cache

Enable Tracing

Logs:

Monitor Events

Best Practices

1. Reuse VersionBuilder

Don't create new instances for same version:

Bad:

Good (but cache works anyway):

2. Use Specific Queries When Possible

If you only need libraries, use get_libraries():

3. TTL Configuration

Adjust TTL based on data stability:

  • Stable releases: Longer TTL (24 hours)

  • Snapshots: Shorter TTL (30 minutes)

  • Development: Very short TTL (5 minutes)

Last updated