### Create Default RocksCache Client Options Source: https://context7.com/dtm-labs/rockscache/llms.txt Use `NewDefaultOptions` to get a pre-configured `Options` struct with safe production defaults for delay, TTL, lock expiry, and jitter. These defaults are suitable for most production environments. ```go import ( "github.com/dtm-labs/rockscache" "github.com/redis/go-redis/v9" ) rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"}) opts := rockscache.NewDefaultOptions() // Defaults: // opts.Delay = 10s // opts.EmptyExpire = 60s // opts.LockExpire = 3s // opts.LockSleep = 100ms // opts.RandomExpireAdjustment = 0.1 // opts.WaitReplicasTimeout = 3000ms rc := rockscache.NewClient(rdb, opts) ``` -------------------------------- ### Initialize RocksCache Client Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Creates a new RocksCache client with default options. Requires a Redis client instance. ```Go import "github.com/dtm-labs/rockscache" // new a client for rockscache using the default options rc := rockscache.NewClient(redisClient, NewDefaultOptions()) ``` -------------------------------- ### Instantiate RocksCache Client with Custom Options Source: https://context7.com/dtm-labs/rockscache/llms.txt Create a RocksCache `Client` by providing a Redis client and custom `Options`. Ensure `Delay` and `LockExpire` are non-zero to prevent misconfiguration. Adjust `Delay` and `LockExpire` based on your environment's latency and database query times. ```go import ( "context" "time" "github.com/dtm-labs/rockscache" "github.com/redis/go-redis/v9" ) rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"}) opts := rockscache.NewDefaultOptions() opts.Delay = 5 * time.Second // shorten delay for lower-latency environments opts.LockExpire = 2 * time.Second // max expected DB query time opts.Context = context.Background() rc := rockscache.NewClient(rdb, opts) // rc.Rdb() returns the underlying redis.UniversalClient if direct access is needed ``` -------------------------------- ### Read Cache with RocksCache Source: https://github.com/dtm-labs/rockscache/blob/main/README.md Use Fetch to retrieve data from the cache. Provide a key, expiration time, and a function to fetch data from the source if it's not in the cache. Requires initializing a RocksCache client. ```Go import "github.com/dtm-labs/rockscache" // new a client for rockscache using the default options rc := rockscache.NewClient(redisClient, NewDefaultOptions()) // use Fetch to fetch data // 1. the first parameter is the key of the data // 2. the second parameter is the data expiration time // 3. the third parameter is the data fetch function which is called when the cache does not exist v, err := rc.Fetch("key1", 300 * time.Second, func()(string, error) { // fetch data from database or other sources return "value1", nil }) ``` -------------------------------- ### NewDefaultOptions Source: https://context7.com/dtm-labs/rockscache/llms.txt Creates a new Options struct with safe production-ready default values for the RocksCache client. These defaults include a 10-second delay for tagged deletes, a 60-second TTL for empty results, a 3-second lock expiry, and a 100ms lock retry sleep. ```APIDOC ## NewDefaultOptions ### Description Returns an Options struct pre-populated with safe production defaults: 10s delay for tagged deletes, 60s empty-result TTL, 3s lock expiry, 100ms lock-retry sleep, and 10% random expiry jitter. ### Returns - Options: A struct containing default client options. ``` -------------------------------- ### Strong Consistency Mode (Options.StrongConsistency) Source: https://context7.com/dtm-labs/rockscache/llms.txt Enables strong consistency mode by setting `Options.StrongConsistency` to `true`. In this mode, `Fetch` operations will wait for any ongoing distributed lock to be released before returning, ensuring callers always receive the most recently committed value. This is crucial for accuracy-critical paths like financial transactions or inventory management. ```APIDOC ## Strong consistency mode — `Options.StrongConsistency` When enabled, `Fetch` waits for the distributed lock to be released before returning, so callers always see the most recently committed value. This eliminates the brief window where stale data is served during a background refresh. Suitable for financial, inventory, or other accuracy-critical paths. ### Usage ```go opts := rockscache.NewDefaultOptions() opts.StrongConsistency = true rcStrong := rockscache.NewClient(rdb, opts) // All reads now block until any ongoing refresh completes balance, err := rcStrong.Fetch( fmt.Sprintf("account:%d:balance", accountID), 2*time.Minute, func() (string, error) { var b float64 db.QueryRow("SELECT balance FROM accounts WHERE id = ?", accountID).Scan(&b) return fmt.Sprintf("%.2f", b), nil }, ) fmt.Println("balance:", balance) // always fresh from DB after a TagAsDeleted ``` ``` -------------------------------- ### NewClient Source: https://context7.com/dtm-labs/rockscache/llms.txt Instantiates a new RocksCache client, binding it to a given Redis connection and a provided Options struct. It includes checks to prevent zero values for Delay and LockExpire to avoid misconfiguration. ```APIDOC ## NewClient ### Description Creates a *Client bound to a Redis connection and the provided Options. Panics if Delay or LockExpire is zero to prevent misconfiguration. ### Parameters #### Parameters - **rdb** (*redis.UniversalClient) - Required - The Redis client connection. - **opts** (*Options) - Required - The configuration options for the RocksCache client. ### Returns - *Client: A pointer to the newly created RocksCache client. ``` -------------------------------- ### Fetch Multiple Cache Keys with FetchBatch Source: https://context7.com/dtm-labs/rockscache/llms.txt Fetches values for a list of keys, collecting cache-miss indices for a batch DB query. Returns a map of original slice indices to values. Stale keys are refreshed asynchronously or synchronously based on consistency mode. ```go keys := []string{"product:1", "product:2", "product:3"} results, err := rc.FetchBatch(keys, 5*time.Minute, func(missIdxs []int) (map[int]string, error) { // Build a single DB query only for the missing keys ids := make([]int, len(missIdxs)) for i, idx := range missIdxs { // parse "product:N" → N fmt.Sscanf(keys[idx], "product:%d", &ids[i]) } rows, err := db.Query("SELECT id, name FROM products WHERE id IN (?) ", ids) if err != nil { return nil, err } defer rows.Close() data := make(map[int]string) for rows.Next() { var id int var name string rows.Scan(&id, &name) // map back to original index for _, idx := range missIdxs { var keyID int fmt.Sscanf(keys[idx], "product:%d", &keyID) if keyID == id { data[idx] = name } } } return data, nil }) if err != nil { log.Fatal(err) } for i, key := range keys { fmt.Printf("%s => %s\n", key, results[i]) } // product:1 => Widget // product:2 => Gadget // product:3 => Doohickey ``` -------------------------------- ### Batch Fetch Data with RocksCache Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Fetches multiple data entries in batches. If some keys are missing in the cache, it calls a batch fetch function to retrieve the missing data from the source. The function returns a map of indices to values for the missing data. ```Go import "github.com/dtm-labs/rockscache" // new a client for rockscache using the default options rc := rockscache.NewClient(redisClient, NewDefaultOptions()) // use FetchBatch to fetch data // 1. the first parameter is the keys list of the data // 2. the second parameter is the data expiration time // 3. the third parameter is the batch data fetch function which is called when the cache does not exist // the parameter of the batch data fetch function is the index list of those keys // missing in cache, which can be used to form a batch query for missing data. // the return value of the batch data fetch function is a map, with key of the // index and value of the corresponding data in form of string v, err := rc.FetchBatch([]string{"key1", "key2", "key3"}, 300, func(idxs []int) (map[int]string, error) { // fetch data from database or other sources values := make(map[int]string) for _, i := range idxs { values[i] = fmt.Sprintf("value%d", i) } return values, nil }) ``` -------------------------------- ### Fetch Data with RocksCache Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Fetches data from the cache. If the cache does not exist, it calls the provided function to fetch data from the source and then caches it. The expiration time for the cache is specified. ```Go // use Fetch to fetch data // 1. the first parameter is the key of the data // 2. the second parameter is the data expiration time // 3. the third parameter is the data fetch function which is called when the cache does not exist v, err := rc.Fetch("key1", 300, func()(string, error) { // fetch data from database or other sources return "value1", nil }) ``` -------------------------------- ### Enable Strong Consistency in Rockscache Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Set the `StrongConsisteny` option to `true` to enforce strong consistency for cache access. This ensures that reads and writes are immediately consistent. ```Go rc.Options.StrongConsisteny = true ``` -------------------------------- ### Fetch Single Cache Key with Fallback Function Source: https://context7.com/dtm-labs/rockscache/llms.txt Use `Fetch` to retrieve a value from the cache. If a cache miss occurs, the provided function is executed to fetch data from the source of truth, store it in Redis with a specified TTL, and return it. This method uses `singleflight` and Redis distributed locks to prevent database stampedes. ```go import ( "database/sql" "fmt" "time" "github.com/dtm-labs/rockscache" "github.com/redis/go-redis/v9" ) rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"}) rc := rockscache.NewClient(rdb, rockscache.NewDefaultOptions()) // db is your *sql.DB (or any other data source) var db *sql.DB userID := 42 cacheKey := fmt.Sprintf("user:%d", userID) value, err := rc.Fetch(cacheKey, 10*time.Minute, func() (string, error) { var name string row := db.QueryRow("SELECT name FROM users WHERE id = ?", userID) if err := row.Scan(&name); err != nil { return "", err // error propagated; cache is NOT populated } return name, nil }) if err != nil { // handle Redis or DB error } fmt.Println("user name:", value) // "Alice" // Context-aware variant (Fetch2): ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() value2, err := rc.Fetch2(ctx, cacheKey, 10*time.Minute, func() (string, error) { return "Alice", nil }) _ = value2 ``` -------------------------------- ### Fetch / Fetch2 Source: https://context7.com/dtm-labs/rockscache/llms.txt Reads a single cache key, ensuring eventual consistency. On a cache miss, it fetches data from the source of truth using a provided function, stores it in Redis with a specified TTL, and returns it. It handles concurrent requests and protects the database from stampedes. If a key has been tagged as deleted, it returns the old value while refreshing the cache in the background. Fetch2 variant supports context for deadline and cancellation. ```APIDOC ## Fetch / Fetch2 ### Description Fetches the cached value for `key`. On a cache miss the provided `fn` is called to load data from the source of truth, stored in Redis with the given TTL, and returned. Uses `singleflight` to coalesce concurrent in-process requests and a Redis distributed lock to protect the database from stampedes. When the key has been tagged-as-deleted but still holds an old value, the old value is returned immediately while `fn` refreshes the cache in the background. Fetch2 variant supports context for deadline and cancellation. ### Parameters #### Fetch Parameters - **key** (string) - Required - The cache key to fetch. - **ttl** (time.Duration) - Required - The time-to-live for the cache entry. - **fn** (func() (string, error)) - Required - A function that returns the value and an error if the cache is missed. #### Fetch2 Parameters - **ctx** (context.Context) - Required - The context for the operation. - **key** (string) - Required - The cache key to fetch. - **ttl** (time.Duration) - Required - The time-to-live for the cache entry. - **fn** (func() (string, error)) - Required - A function that returns the value and an error if the cache is missed. ### Returns - string: The cached value or the value fetched from the source of truth. - error: An error if fetching from Redis or the source of truth fails. ``` -------------------------------- ### Direct Low-Level Cache Access with RawSet/RawGet Source: https://context7.com/dtm-labs/rockscache/llms.txt Use RawSet and RawGet for direct, low-level access to the underlying Redis hash's value field, bypassing consistency logic. Useful for pre-warming caches or migration scripts. ```go ctx := context.Background() // Pre-warm a key without going through the fetch lock err := rc.RawSet(ctx, "config:feature-flags", `{"darkMode":true}`, 24*time.Hour) if err != nil { log.Fatal(err) } raw, err := rc.RawGet(ctx, "config:feature-flags") if err != nil { log.Fatal(err) } fmt.Println(raw) // {"darkMode":true} ``` -------------------------------- ### Manual Distributed Lock with LockForUpdate/UnlockForUpdate Source: https://context7.com/dtm-labs/rockscache/llms.txt Acquire or release the internal update lock explicitly for a key using LockForUpdate and UnlockForUpdate. Intended for custom update flows requiring coordination outside the standard Fetch lifecycle. ```go ctx := context.Background() owner := "my-service-instance-uuid" // Acquire lock before a complex multi-step update if err := rc.LockForUpdate(ctx, "inventory:sku-999", owner); err != nil { log.Fatalf("could not acquire lock: %v", err) // another owner holds it } // Perform DB update and directly set cache value _, err := db.Exec("UPDATE inventory SET qty = qty - 1 WHERE sku = 'sku-999'") if err != nil { rc.UnlockForUpdate(ctx, "inventory:sku-999", owner) log.Fatal(err) } // Write new value while holding the lock, then release rc.RawSet(ctx, "inventory:sku-999", `{"qty":49}`, 5*time.Minute) rc.UnlockForUpdate(ctx, "inventory:sku-999", owner) ``` -------------------------------- ### Enable Strong Consistency Mode in Rockscache Source: https://context7.com/dtm-labs/rockscache/llms.txt When enabled, Fetch waits for the distributed lock to be released before returning, ensuring callers always see the most recently committed value. This eliminates the window where stale data is served during a background refresh. Suitable for accuracy-critical paths. ```go opts := rockscache.NewDefaultOptions() opts.StrongConsistency = true rcStrong := rockscache.NewClient(rdb, opts) // All reads now block until any ongoing refresh completes balance, err := rcStrong.Fetch( fmt.Sprintf("account:%d:balance", accountID), 2*time.Minute, func() (string, error) { var b float64 db.QueryRow("SELECT balance FROM accounts WHERE id = ?", accountID).Scan(&b) return fmt.Sprintf("%.2f", b), nil }, ) fmt.Println("balance:", balance) // always fresh from DB after a TagAsDeleted ``` -------------------------------- ### Batch Delete Cache Entries with RocksCache Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Marks multiple cache entries as deleted in a batch operation using a list of keys. ```Go rc.TagAsDeletedBatch(keys) ``` -------------------------------- ### FetchBatch / FetchBatch2 Source: https://context7.com/dtm-labs/rockscache/llms.txt Fetches values for a list of keys in a single call. It collects cache-miss indices and passes them to a provided function for batch database queries. The function returns a map of original slice indices to their corresponding values. Stale keys are refreshed asynchronously or synchronously based on the consistency mode. ```APIDOC ## FetchBatch / FetchBatch2 — Read multiple cache keys in one call Fetches values for a list of keys. Cache-miss indices are collected and passed as a slice to `fn`, allowing a single batch DB query. Returns a `map[int]string` where keys are the original slice indices. Stale keys are refreshed asynchronously in eventual-consistency mode, or synchronously in strong-consistency mode. ### Usage ```go keys := []string{"product:1", "product:2", "product:3"} results, err := rc.FetchBatch(keys, 5*time.Minute, func(missIdxs []int) (map[int]string, error) { // Build a single DB query only for the missing keys ids := make([]int, len(missIdxs)) for i, idx := range missIdxs { // parse "product:N" → N fmt.Sscanf(keys[idx], "product:%d", &ids[i]) } rows, err := db.Query("SELECT id, name FROM products WHERE id IN (?)", ids) if err != nil { return nil, err } defer rows.Close() data := make(map[int]string) for rows.Next() { var id int var name string rows.Scan(&id, &name) // map back to original index for _, idx := range missIdxs { var keyID int fmt.Sscanf(keys[idx], "product:%d", &keyID) if keyID == id { data[idx] = name } } } return data, nil }) if err != nil { log.Fatal(err) } for i, key := range keys { fmt.Printf("%s => %s\n", key, results[i]) } // product:1 => Widget // product:2 => Gadget // product:3 => Doohickey ``` ``` -------------------------------- ### Invalidate Multiple Cache Keys Atomically with TagAsDeletedBatch Source: https://context7.com/dtm-labs/rockscache/llms.txt Applies the tag-as-deleted pattern to a slice of keys in a single Lua script execution. Useful after bulk database updates. ```go updatedIDs := []int{1, 2, 3} cacheKeys := make([]string, len(updatedIDs)) for i, id := range updatedIDs { cacheKeys[i] = fmt.Sprintf("product:%d", id) } // After bulk DB update: _, err := db.Exec("UPDATE products SET price = price * 1.1 WHERE id IN (1,2,3)") if err == nil { if delErr := rc.TagAsDeletedBatch(cacheKeys); delErr != nil { log.Printf("batch invalidation error: %v", delErr) } } ``` ```go // Context-aware variant: ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) deferr cancel() _ = rc.TagAsDeletedBatch2(ctx, cacheKeys) ``` -------------------------------- ### Downgrade Cache Read/Delete with Rockscache Source: https://context7.com/dtm-labs/rockscache/llms.txt Configure Rockscache to bypass Redis entirely by setting DisableCacheRead and DisableCacheDelete to true. This routes traffic directly to the database, maintaining strong consistency during Redis degradation. ```go opts := rockscache.NewDefaultOptions() // Full downgrade: bypass Redis entirely opts.DisableCacheRead = true // Fetch calls fn directly, skipping Redis opts.DisableCacheDelete = true // TagAsDeleted is a no-op rcDegraded := rockscache.NewClient(rdb, opts) // Business code stays identical — no if/else branching needed value, err := rcDegraded.Fetch("user:42", 10*time.Minute, func() (string, error) { return queryDB(42) // always called when DisableCacheRead=true }) _ = value _ = err ``` -------------------------------- ### TagAsDeletedBatch / TagAsDeletedBatch2 Source: https://context7.com/dtm-labs/rockscache/llms.txt Atomically invalidates multiple cache keys using a single Lua script execution. This is particularly useful after bulk database updates, such as mass updates or import jobs. The `TagAsDeletedBatch2` variant is context-aware. ```APIDOC ## TagAsDeletedBatch / TagAsDeletedBatch2 — Invalidate multiple cache keys atomically Applies the tag-as-deleted pattern to a slice of keys in a single Lua script execution. Useful after bulk database updates (e.g., admin mass-updates, import jobs). ### Usage ```go updatedIDs := []int{1, 2, 3} cacheKeys := make([]string, len(updatedIDs)) for i, id := range updatedIDs { cacheKeys[i] = fmt.Sprintf("product:%d", id) } // After bulk DB update: _, err := db.Exec("UPDATE products SET price = price * 1.1 WHERE id IN (1,2,3)") if err == nil { if delErr := rc.TagAsDeletedBatch(cacheKeys); delErr != nil { log.Printf("batch invalidation error: %v", delErr) } } // Context-aware variant: ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() _ = rc.TagAsDeletedBatch2(ctx, cacheKeys) ``` ``` -------------------------------- ### Delete Cache Entry with RocksCache Source: https://github.com/dtm-labs/rockscache/blob/main/helper/README-en.md Marks a cache entry as deleted using its key. This is part of the cache invalidation strategy. ```Go rc.TagAsDeleted(key) ``` -------------------------------- ### TagAsDeleted / TagAsDeleted2 Source: https://context7.com/dtm-labs/rockscache/llms.txt Marks a cache key as deleted by setting its `lockUntil` field to 0 and scheduling expiry. This operation should be performed after a corresponding database write to ensure cache-database consistency. The `TagAsDeleted2` variant supports context and replica acknowledgement. ```APIDOC ## TagAsDeleted / TagAsDeleted2 — Invalidate a single cache key Marks a key as deleted by setting its `lockUntil` field to 0 and scheduling expiry after `Options.Delay`. Must be called **after** the corresponding database write to guarantee cache/DB consistency. If `DisableCacheDelete` is true (downgrade mode) the function is a no-op. ### Usage ```go // After a successful DB update: err := db.Exec("UPDATE users SET name = ? WHERE id = ?", "Bob", userID) if err == nil { // Invalidate the cache; rockscache guarantees any in-flight stale write is discarded if delErr := rc.TagAsDeleted(cacheKey); delErr != nil { log.Printf("cache invalidation failed (will self-heal after TTL): %v", delErr) } } // Context-aware variant with replica acknowledgement: opts := rockscache.NewDefaultOptions() opts.WaitReplicas = 1 // wait for at least 1 replica opts.WaitReplicasTimeout = 500 * time.Millisecond rc2 := rockscache.NewClient(rdb, opts) ctx := context.Background() if err := rc2.TagAsDeleted2(ctx, cacheKey); err != nil { log.Printf("replica sync failed: %v", err) } ``` ``` -------------------------------- ### Invalidate Single Cache Key with TagAsDeleted Source: https://context7.com/dtm-labs/rockscache/llms.txt Marks a cache key as deleted by setting its lockUntil field to 0. Must be called after the corresponding database write. If DisableCacheDelete is true, this is a no-op. ```go // After a successful DB update: err := db.Exec("UPDATE users SET name = ? WHERE id = ?", "Bob", userID) if err == nil { // Invalidate the cache; rockscache guarantees any in-flight stale write is discarded if delErr := rc.TagAsDeleted(cacheKey); delErr != nil { log.Printf("cache invalidation failed (will self-heal after TTL): %v", delErr) } } ``` ```go // Context-aware variant with replica acknowledgement: opts := rockscache.NewDefaultOptions() opts.WaitReplicas = 1 // wait for at least 1 replica opts.WaitReplicasTimeout = 500 * time.Millisecond rc2 := rockscache.NewClient(rdb, opts) ctx := context.Background() if err := rc2.TagAsDeleted2(ctx, cacheKey); err != nil { log.Printf("replica sync failed: %v", err) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.