### Install Protobuf Package Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/protobuf.md Installation commands for the Protobuf extension package via CLI or project file. ```bash dotnet add package StackExchange.Redis.Extensions.Protobuf ``` ```xml ``` -------------------------------- ### Install StackExchange.Redis.Extensions.System.Text.Json via Package Manager Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/system.text.json.md Use this command to install the package using the Package Manager Console. ```bash Install-Package StackExchange.Redis.Extensions.System.Text.Json ``` -------------------------------- ### Install StackExchange.Redis.Extensions.System.Text.Json via Paket Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/system.text.json.md Use this command to add the package reference using Paket. ```bash paket add StackExchange.Redis.Extensions.System.Text.Json ``` -------------------------------- ### Install Compression Package Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/compressors.md Install one of the available compression packages using the .NET CLI. Choose the package that corresponds to your desired compression algorithm. ```bash # Pick one: dotnet add package StackExchange.Redis.Extensions.Compression.LZ4 dotnet add package StackExchange.Redis.Extensions.Compression.Snappier dotnet add package StackExchange.Redis.Extensions.Compression.ZstdSharp dotnet add package StackExchange.Redis.Extensions.Compression.GZip dotnet add package StackExchange.Redis.Extensions.Compression.Brotli ``` -------------------------------- ### Install Package Manager Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/newtonsoft-json.net.md Use this command to install the Newtonsoft extension via the Package Manager Console. ```bash Install-Package StackExchange.Redis.Extensions.Newtonsoft ``` -------------------------------- ### Install ASP.NET Core Package Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/README.md Install the specific NuGet package for ASP.NET Core integration. This package provides the necessary extensions for seamless integration. ```bash dotnet add package StackExchange.Redis.Extensions.AspNetCore ``` ```xml ``` -------------------------------- ### Creating User Instances Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/usage/work-with-multiple-items.md Example data structures for User and Company objects used in subsequent operations. ```csharp var user1 = new User { Username = "imperugo", FirstName = "Ugo", LastName = "Lattanzi", Email = "ugo@example.com", Company = new Company { Name = "My Super Company", Vat = "IT12345678911", Address = "somewhere road 12" } }; var user2 = new User { Username = "mario.rossi", FirstName = "Mario", LastName = "Rossi", Email = "mario@example.com", Company = new Company { Name = "My Super Company", Vat = "IT12345678911", Address = "somewhere road 12" } }; ``` -------------------------------- ### Install MsgPack Package Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/msgpack.md Commands and configuration for adding the MsgPack serialization package to your project. ```bash Install-Package StackExchange.Redis.Extensions.MsgPack ``` ```bash dotnet add package StackExchange.Redis.Extensions.MsgPack ``` ```xml ``` ```bash paket add StackExchange.Redis.Extensions.MsgPack ``` -------------------------------- ### Install StackExchange.Redis.Extensions.System.Text.Json via .NET CLI Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/system.text.json.md Use this command to add the package reference using the .NET CLI. ```bash dotnet add package StackExchange.Redis.Extensions.System.Text.Json ``` -------------------------------- ### Install .NET CLI Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/newtonsoft-json.net.md Use this command to add the Newtonsoft extension to your project using the .NET CLI. ```bash dotnet add package StackExchange.Redis.Extensions.Newtonsoft ``` -------------------------------- ### Install Paket CLI Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/newtonsoft-json.net.md Use this command to add the Newtonsoft extension to your project using the Paket CLI. ```bash paket add StackExchange.Redis.Extensions.Newtonsoft ``` -------------------------------- ### Install MemoryPack Package Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/memoryPack.md Use these commands to add the MemoryPack extension package to your project. ```bash dotnet add package StackExchange.Redis.Extensions.MemoryPack ``` ```xml ``` -------------------------------- ### Interpret healthy startup logs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Example log output indicating successful pool initialization and client creation. ```text info: StackExchange.Redis.Extensions.Core[1001] Redis connection pool initialized: 5 connections to localhost:6379 in 234ms info: StackExchange.Redis.Extensions.Core[3001] Redis client created: Default (database: 0) ``` -------------------------------- ### Install Package Reference Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/newtonsoft-json.net.md Add this XML snippet to your project file to include the Newtonsoft extension as a package reference. ```xml ``` -------------------------------- ### Define Redis Configuration in JSON Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/configuration/json-configuration.md Example structure for a Redis configuration file compatible with .NET binding. ```json { "Redis": { "Password": "my_super_secret_password", "AllowAdmin": true, "Ssl": false, "ConnectTimeout": 6000, "ConnectRetry": 2, "Database": 0, "ServiceName": "my-sentinel", "Hosts": [ { "Host": "192.168.0.10", "Port": "6379" }, { "Host": "192.168.0.11", "Port": "6381" } ], "MaxValueLength": 1024, "PoolSize": 5, "KeyPrefix": "_my_key_prefix_" } } ``` -------------------------------- ### Install StackExchange.Redis.Extensions Packages Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Use the dotnet CLI to add the necessary packages for core functionality, System.Text.Json serialization, and ASP.NET Core integration. ```bash dotnet add package StackExchange.Redis.Extensions.Core dotnet add package StackExchange.Redis.Extensions.System.Text.Json dotnet add package StackExchange.Redis.Extensions.AspNetCore ``` -------------------------------- ### Interpret pool initialization failure logs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Example log output showing a failure during the pool initialization process. ```text fail: StackExchange.Redis.Extensions.Core[1006] Redis pool initialization failed at connection 2 of 5. Cleaning up 2 previously created connections ``` -------------------------------- ### Register MsgPack Serializer Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/msgpack.md Configuration examples for registering the MsgPack serializer with dependency injection containers. ```csharp services.AddSingleton(); ``` ```csharp container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); ``` -------------------------------- ### Redis Server Information JSON Response Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/expose-redis-information.md Example JSON output for the /redis/info endpoint. ```json { "redis_version": "7.2.4", "redis_mode": "standalone", "os": "Linux 6.1.0 x86_64", "arch_bits": "64", "tcp_port": "6379", "uptime_in_seconds": "34131", "uptime_in_days": "0", "connected_clients": "2", "used_memory_human": "1.65M", "used_memory_peak_human": "1.75M", "maxmemory_policy": "noeviction", "role": "master", "connected_slaves": "0", "cluster_enabled": "0" } ``` -------------------------------- ### Redis Connection Information JSON Response Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/expose-redis-information.md Example JSON output for the /redis/connectionInfo endpoint. ```json { "RequiredPoolSize": 5, "ActiveConnections": 1, "InvalidConnections": 0, "ReadyNotUsedYet": 4 } ``` -------------------------------- ### Manage Redis Keys Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Provides examples for conditional renaming, checking key types before operations, and migrating keys using dump and restore. ```csharp // Rename with condition await redis.KeyRenameAsync("temp:data", "final:data", When.NotExists); // Check type before operations var type = await redis.KeyTypeAsync("my-key"); // RedisType.String, Set, Hash, ... // Dump and restore (migrate between databases) var dump = await redis.KeyDumpAsync("source-key"); await redis.KeyRestoreAsync("dest-key", dump, TimeSpan.FromHours(24)); ``` -------------------------------- ### Set and Get Hash Fields Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Demonstrates how to set and retrieve individual fields within a Redis hash. Supports setting multiple fields and retrieving them. ```csharp await redis.HashSetAsync("user:1", "name", "Ugo"); await redis.HashSetAsync("user:1", "email", "ugo@example.com"); var name = await redis.HashGetAsync("user:1", "name"); ``` -------------------------------- ### Manage Redis Keys: Rename, Type, Dump, Restore Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Provides examples for key management operations including renaming, checking key type, and migrating keys between databases using dump and restore. ```csharp await redis.KeyRenameAsync("old-key", "new-key"); var type = await redis.KeyTypeAsync("my-key"); // RedisType.String, Set, Hash, ... var dump = await redis.KeyDumpAsync("my-key"); await redis.KeyRestoreAsync("my-key-copy", dump, TimeSpan.FromHours(1)); ``` -------------------------------- ### Inject IRedisDatabase into a service Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/usage/add-and-retrieve-complex-object-to-redis.md Shows the required dependency injection setup for using the library within a service. ```csharp public class MyService(IRedisDatabase redis) { // use redis directly } ``` -------------------------------- ### Interpret subscription handler failure logs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Example log output showing an exception thrown within a subscription handler. ```text fail: StackExchange.Redis.Extensions.Core[4001] Error processing subscription message on channel orders:new System.InvalidOperationException: Failed to process order ``` -------------------------------- ### Define User and Company data models Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/usage/README.md These classes serve as the base data structures for serialization examples throughout the library. ```csharp public class User { public string Username { get; set; } = string.Empty; public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public CultureInfo? Culture { get; set; } public string? TimeZoneId { get; set; } public bool EmailConfirmed { get; set; } public Company Company { get; set; } = new(); } public class Company { public string Name { get; set; } = string.Empty; public string Vat { get; set; } = string.Empty; public string Address { get; set; } = string.Empty; public string District { get; set; } = string.Empty; public string Zipcode { get; set; } = string.Empty; public string City { get; set; } = string.Empty; public string Phone { get; set; } = string.Empty; public string Fax { get; set; } = string.Empty; public string Country { get; set; } = string.Empty; } ``` -------------------------------- ### Interpret degraded mode logs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Example log output indicating that all connections are currently disconnected. ```text warn: StackExchange.Redis.Extensions.Core[1003] All Redis connections are disconnected. Using connection 12345678 in degraded mode ``` -------------------------------- ### Interpret connection flap logs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Example log output showing a socket failure followed by a successful reconnection. ```text fail: StackExchange.Redis.Extensions.Core[2001] Redis connection failed: SocketFailure warn: StackExchange.Redis.Extensions.Core[2002] Redis connection restored to localhost:6379 ``` -------------------------------- ### Register Protobuf Serializer Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/protobuf.md Methods for registering the Protobuf serializer in ASP.NET Core or manual dependency injection setups. ```csharp builder.Services.AddStackExchangeRedisExtensions(redisConfiguration); ``` ```csharp services.AddSingleton(); ``` -------------------------------- ### Create Consumer Group for Redis Stream Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/streams.md Initializes a consumer group for a stream, allowing multiple consumers to process messages. Specify the starting point ('0-0' for all messages, '$' for new messages only). ```csharp // Start reading from the beginning of the stream await redis.StreamCreateConsumerGroupAsync("orders", "processors", "0-0"); // Start reading only new messages await redis.StreamCreateConsumerGroupAsync("orders", "processors", "$"); ``` -------------------------------- ### Inject and Use IRedisDatabase in Minimal API Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/README.md Inject the IRedisDatabase service into your minimal API handlers or controllers to perform Redis operations. This example demonstrates fetching a user object by key. ```csharp app.MapGet("/users/{key}", async (string key, IRedisDatabase redis) => { var user = await redis.GetAsync(key); return user is not null ? Results.Ok(user) : Results.NotFound(); }); ``` -------------------------------- ### Inject and Use IDistributedCache Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/distributed-cache.md Inject IDistributedCache into your services to perform caching operations. Example shows getting and setting session data with expiration options. ```csharp public class SessionService(IDistributedCache cache) { public async Task GetSessionAsync(string sessionId) { return await cache.GetAsync($"session:{sessionId}"); } public async Task SetSessionAsync(string sessionId, byte[] data) { await cache.SetAsync($"session:{sessionId}", data, new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20), AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(4), }); } } ``` -------------------------------- ### Get Geohash Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/geospatial.md Retrieves the geohash string for a specific member. ```csharp var hash = await redis.GeoHashAsync("stores", "NYC Store"); // e.g., "dr5regw3pp0" ``` -------------------------------- ### Configure Multiple Redis Instances Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/azure-managed-identity.md Demonstrates how to register multiple Redis configurations, applying Managed Identity only to the Azure-hosted instance. ```csharp var azureConfig = new RedisConfiguration { Name = "AzureRedis", Hosts = new[] { new RedisHost { Host = "prod.redis.cache.windows.net", Port = 6380 } }, Ssl = true, IsDefault = true, }; azureConfig.ConfigurationOptionsAsyncHandler = async opts => { await opts.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential()); return opts; }; var localConfig = new RedisConfiguration { Name = "LocalRedis", Hosts = new[] { new RedisHost { Host = "localhost", Port = 6379 } }, }; services.AddStackExchangeRedisExtensions(new[] { azureConfig, localConfig }); ``` -------------------------------- ### Register and Inject Keyed Redis Databases (.NET 8+) Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Demonstrates registering multiple Redis instances with named configurations and injecting them into services using keyed services. Each instance has an isolated connection pool. ```csharp // Register with named configurations builder.Services.AddStackExchangeRedisExtensions(new[] { new RedisConfiguration { Name = "cache", IsDefault = true, /* ... */ }, new RedisConfiguration { Name = "session", /* ... */ }, }); // Inject by name using [FromKeyedServices] public class MyService( [FromKeyedServices("cache")] IRedisDatabase cacheDb, [FromKeyedServices("session")] IRedisDatabase sessionDb) { // Each resolves to its own Redis instance with isolated connection pool } ``` -------------------------------- ### Load Separate Configuration File Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/configuration/json-configuration.md Configures the builder to load Redis settings from a dedicated JSON file instead of the default appsettings.json. ```csharp builder.Configuration .SetBasePath(builder.Environment.ContentRootPath) .AddJsonFile("Configuration/redis.json", optional: false, reloadOnChange: true) .AddJsonFile($"Configuration/redis.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables(); var redisConfiguration = builder.Configuration .GetSection("Redis") .Get(); ``` -------------------------------- ### Basic Redis Operations with StackExchange.Redis.Extensions Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Demonstrates common Redis operations including storing and retrieving objects, setting expiry times, performing bulk operations, and searching for keys using the injected IRedisDatabase service. ```csharp public class MyService(IRedisDatabase redis) { public async Task Example() { // Store an object await redis.AddAsync("user:1", new User { Name = "Ugo", Age = 38 }); // Retrieve it var user = await redis.GetAsync("user:1"); // Store with expiry await redis.AddAsync("session:abc", sessionData, TimeSpan.FromMinutes(30)); // Bulk operations var items = new[] { Tuple.Create("key1", "value1"), Tuple.Create("key2", "value2"), }; await redis.AddAllAsync(items, TimeSpan.FromHours(1)); // Search keys var keys = await redis.SearchKeysAsync("user:*"); } } ``` -------------------------------- ### Configure Redis in appsettings.json Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Define your Redis connection settings, including host, port, password, and pool size, in the appsettings.json file. ```json { "Redis": { "Password": "", "AllowAdmin": true, "Ssl": false, "ConnectTimeout": 5000, "SyncTimeout": 5000, "Database": 0, "Hosts": [ { "Host": "localhost", "Port": 6379 } ], "PoolSize": 5, "IsDefault": true } } ``` -------------------------------- ### Basic appsettings.json Configuration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/configure/SKILL.md Defines the basic Redis connection settings in appsettings.json. Ensure this structure matches your Redis server's accessibility. ```json { "Redis": { "Password": "", "AllowAdmin": true, "Ssl": false, "ConnectTimeout": 5000, "SyncTimeout": 5000, "Database": 0, "Hosts": [{ "Host": "localhost", "Port": 6379 }], "PoolSize": 5, "IsDefault": true } } ``` -------------------------------- ### Optional Compression Registration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/configure/SKILL.md Adds optional compression to your Redis setup. LZ4 is recommended for the lowest latency in caching scenarios. ```csharp // Optional compression: builder.Services.AddRedisCompression(); ``` -------------------------------- ### Enable Transparent Compression Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/migration-v11-to-v12.md Register a compressor to enable transparent data compression. ```csharp services.AddStackExchangeRedisExtensions(config); services.AddRedisCompression(); // one line! ``` -------------------------------- ### Register Redis Services in Program.cs Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/README.md Register the StackExchange.Redis.Extensions services in your ASP.NET Core application's Program.cs file using the minimal hosting model. Ensure you have a Redis configuration section in your appsettings.json. ```csharp var builder = WebApplication.CreateBuilder(args); var redisConfiguration = builder.Configuration .GetSection("Redis") .Get(); builder.Services.AddStackExchangeRedisExtensions(redisConfiguration); var app = builder.Build(); app.UseRedisInformation(); app.Run(); ``` -------------------------------- ### Resolve Named Redis Instances with IRedisClientFactory Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/multipleServers.md Use `IRedisClientFactory` to explicitly get an `IRedisClient` instance by its registered name, then retrieve the default database from it. ```csharp public class MyClass(IRedisClientFactory clientFactory) { public Task MyMethod() { var redisClient = clientFactory.GetRedisClient("session"); var db = redisClient.GetDefaultDatabase(); // do your stuff here } } ``` -------------------------------- ### Implement Custom Compressor Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/compressors.md Implement the `ICompressor` interface to provide a custom compression algorithm. Register your custom compressor with the DI container. ```csharp public class MyCompressor : ICompressor { public byte[] Compress(byte[] data) { /* your compression */ } public byte[] Decompress(byte[] compressedData) { /* your decompression */ } } services.AddRedisCompression(new MyCompressor()); ``` -------------------------------- ### Logging Configuration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md How to configure the ILogger for StackExchange.Redis.Extensions. ```APIDOC ## Logging Setup ### Description Logging is automatically handled when using ASP.NET Core Dependency Injection. For manual configuration, you must provide a `LoggerFactory` to the `RedisConfiguration` object. ### Configuration Example ```csharp var config = new RedisConfiguration { LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole()), // ... other config }; ``` ### Filtering Use the `StackExchange.Redis.Extensions.Core` category in your `appsettings.json` to control log verbosity. ```json { "Logging": { "LogLevel": { "Default": "Warning", "StackExchange.Redis.Extensions.Core": "Information" } } } ``` ``` -------------------------------- ### Read Messages from Redis Stream Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/streams.md Reads messages from a specified stream, starting from a given message ID. Supports reading all messages from the beginning ('0-0') or with a count limit. ```csharp // Read all messages from the beginning var entries = await redis.StreamReadAsync("orders", "0-0"); // Read with limit var latest = await redis.StreamReadAsync("orders", "0-0", count: 10); ``` -------------------------------- ### Program.cs DI Registration with System.Text.Json Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/configure/SKILL.md Registers StackExchange.Redis.Extensions with dependency injection using the System.Text.Json serializer. This is the recommended approach for general-purpose use. ```csharp var redisConfig = builder.Configuration.GetSection("Redis").Get(); builder.Services.AddStackExchangeRedisExtensions(redisConfig); ``` -------------------------------- ### Enable Transparent Compression Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/asp.net-core/README.md Optionally enable transparent compression for Redis data by calling AddRedisCompression after registering the main Redis services. Ensure you have installed a compressor package like StackExchange.Redis.Extensions.Compressors.LZ4. ```csharp builder.Services.AddStackExchangeRedisExtensions(redisConfiguration); builder.Services.AddRedisCompression(); ``` -------------------------------- ### Multiple Redis Instances with Keyed DI (.NET 8+) Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/configure/SKILL.md Configures multiple Redis instances and registers them for keyed dependency injection, available from .NET 8 onwards. Each instance can have a distinct name and configuration. ```csharp var configs = new[] { new RedisConfiguration { Name = "Cache", IsDefault = true, /* ... */ }, new RedisConfiguration { Name = "Session", /* ... */ }, }; builder.Services.AddStackExchangeRedisExtensions(configs); // Option 1: Keyed DI Services (.NET 8+) public class MyService( [FromKeyedServices("Cache")] IRedisDatabase cacheDb, [FromKeyedServices("Session")] IRedisDatabase sessionDb) { } ``` -------------------------------- ### Create a complex object instance Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/usage/add-and-retrieve-complex-object-to-redis.md Defines a sample User object with a nested Company object for caching. ```csharp var user = new User { Username = "imperugo", FirstName = "Ugo", LastName = "Lattanzi", Email = "ugo@example.com", Company = new Company { Name = "My Super Company", Vat = "IT12345678911", Address = "somewhere road 12" } }; ``` -------------------------------- ### Configure Multiple Redis Servers Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/multipleServers.md Register multiple Redis configurations with `AddStackExchangeRedisExtensions`. Use `IsDefault` to mark the default instance and `Name` to identify other instances. ```csharp var configurations = new[] { new RedisConfiguration { AbortOnConnectFail = true, KeyPrefix = "MyPrefix__", Hosts = new[] { new RedisHost { Host = "localhost", Port = 6379 } }, AllowAdmin = true, ConnectTimeout = 5000, Database = 0, PoolSize = 5, IsDefault = true }, new RedisConfiguration { AbortOnConnectFail = true, KeyPrefix = "MyPrefix__", Hosts = new[] { new RedisHost { Host = "localhost", Port = 6389 } }, AllowAdmin = true, ConnectTimeout = 5000, Database = 0, PoolSize = 2, Name = "Secndary Instance" } }; services.AddStackExchangeRedisExtensions(configurations); ``` -------------------------------- ### Enable Logging for StackExchange.Redis.Extensions Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/diagnose/SKILL.md Configure your application's logging settings to capture information from the StackExchange.Redis.Extensions library. Set the log level for 'StackExchange.Redis.Extensions.Core' to 'Information' or a more verbose level to see detailed logs. ```json { "Logging": { "LogLevel": { "StackExchange.Redis.Extensions.Core": "Information" } } } ``` -------------------------------- ### Manage Vectors in Redis VectorSet Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/vectorset.md Provides methods for checking existence, getting cardinality, dimensions, random members, info, approximate vectors, HNSW graph neighbors, and removing members from a Redis VectorSet. ```csharp // Check if a member exists var exists = await redis.VectorSetContainsAsync("products", "shoe-123"); // Get cardinality var count = await redis.VectorSetLengthAsync("products"); // Get vector dimensions var dims = await redis.VectorSetDimensionAsync("products"); // Get a random member var random = await redis.VectorSetRandomMemberAsync("products"); // Get multiple random members var randoms = await redis.VectorSetRandomMembersAsync("products", 5); // Get info about the VectorSet var info = await redis.VectorSetInfoAsync("products"); // Get the approximate vector for a member using var vector = await redis.VectorSetGetApproximateVectorAsync("products", "shoe-123"); // Get HNSW graph neighbors var links = await redis.VectorSetGetLinksAsync("products", "shoe-123"); var linksWithScores = await redis.VectorSetGetLinksWithScoresAsync("products", "shoe-123"); // Remove a member await redis.VectorSetRemoveAsync("products", "shoe-123"); ``` -------------------------------- ### Implement Distributed Cache with Redis Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Demonstrates using `IDistributedCache` with Redis for session management. Configure sliding and absolute expirations for cache entries. ```csharp // Registered via: builder.Services.AddRedisDistributedCache() public class SessionService(IDistributedCache cache) { public async Task SetAsync(string sessionId, byte[] data) { await cache.SetAsync($"session:{sessionId}", data, new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20), AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(4), }); } } ``` -------------------------------- ### Configure Compression Level Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/compressors.md Configure the compression level for specific algorithms. This allows tuning the balance between compression ratio and speed. ```csharp // LZ4 — max compression services.AddRedisCompression(new LZ4Compressor(LZ4Level.L12_MAX)); // GZip — optimal balance services.AddRedisCompression(new GZipCompressor(CompressionLevel.Optimal)); // Zstandard — level 1-22 (default: 3) services.AddRedisCompression(new ZstdSharpCompressor(compressionLevel: 6)); ``` -------------------------------- ### Configure Logging for Redis Extensions Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/diagnose/SKILL.md Enable debug logging for StackExchange.Redis.Extensions to diagnose performance issues by observing connection selection behavior. ```json { "Logging": { "LogLevel": { "StackExchange.Redis.Extensions.Core": "Debug" } } } ``` -------------------------------- ### Register Compression in DI Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/compressors.md After registering StackExchange.Redis.Extensions, add the compression service using the chosen compressor. This enables automatic compression for all Redis operations. ```csharp // After AddStackExchangeRedisExtensions services.AddStackExchangeRedisExtensions(redisConfig); services.AddRedisCompression(); ``` -------------------------------- ### Bulk Cache Operations with Expiry Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Add multiple product items to the cache in a single operation, with each item expiring after 1 hour. ```csharp public async Task CacheBulkAsync(IRedisDatabase redis, Dictionary products) { var items = products.Select(p => Tuple.Create($"product:{p.Key}", p.Value)).ToArray(); await redis.AddAllAsync(items, TimeSpan.FromHours(1)); } ``` -------------------------------- ### Key Management Operations Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Demonstrates various key management operations in Redis. ```APIDOC ## RedisDatabase.KeyRenameAsync ### Description Renames a key if the destination key does not exist. ### Method Signature `await redis.KeyRenameAsync("temp:data", "final:data", When.NotExists);` ### Parameters - **sourceKey** (string) - The original key name. - **destinationKey** (string) - The new key name. - **when** (When) - Condition for renaming (e.g., `When.NotExists`). ``` ```APIDOC ## RedisDatabase.KeyTypeAsync ### Description Retrieves the type of a given key. ### Method Signature `var type = await redis.KeyTypeAsync("my-key");` ### Parameters - **key** (string) - The key to check. ### Returns - **RedisType** - The type of the key (e.g., String, Set, Hash). ``` ```APIDOC ## RedisDatabase.KeyDumpAsync and RedisDatabase.KeyRestoreAsync ### Description Dumps the RDB serialization of a key and restores it to another key, useful for migrating data between databases. ### Method Signature `var dump = await redis.KeyDumpAsync("source-key");` `await redis.KeyRestoreAsync("dest-key", dump, TimeSpan.FromHours(24));` ### Parameters for KeyDumpAsync - **key** (string) - The key to dump. ### Parameters for KeyRestoreAsync - **destinationKey** (string) - The key to restore to. - **value** (byte[]) - The serialized value obtained from `KeyDumpAsync`. - **expiry** (TimeSpan) - Optional - The expiration time for the restored key. ``` -------------------------------- ### Sentinel Configuration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/configure/SKILL.md Sets up a Redis configuration to connect to a Sentinel cluster for high availability. Specify the service name and Sentinel host/port pairs. ```csharp var config = new RedisConfiguration { ServiceName = "mymaster", Hosts = new[] { new RedisHost { Host = "sentinel1", Port = 26379 }, new RedisHost { Host = "sentinel2", Port = 26379 }, }, IsDefault = true, }; ``` -------------------------------- ### Register StackExchange.Redis.Extensions via Dependency Injection Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/dependency-injection.md Use this extension method to register the Redis client factory and a specific serializer implementation. Requires an ISerializer implementation and a redis configuration factory. ```csharp /// /// Add StackExchange.Redis with its serialization provider. /// /// The service collection. /// The redis configration. /// The typof of serializer. . public static IServiceCollection AddStackExchangeRedisExtensions( this IServiceCollection services, Func> redisConfigurationFactory) where T : class, ISerializer { services.AddSingleton(); services.AddSingleton(); services.AddSingleton((provider) => provider .GetRequiredService() .GetDefaultRedisClient()); services.AddSingleton((provider) => provider .GetRequiredService() .GetDefaultRedisClient() .GetDefaultDatabase()); services.AddSingleton(redisConfigurationFactory); return services; } ``` -------------------------------- ### Search and Store Results Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/geospatial.md Executes a search and stores the resulting members in a new Redis key. ```csharp // Store search results in a new key var count = await redis.GeoSearchAndStoreAsync( "stores", "nearby-nyc", "NYC Store", new GeoSearchCircle(100, GeoUnit.Miles)); ``` -------------------------------- ### Create and Read from Redis Stream Consumer Group Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Demonstrates the workflow for creating a consumer group for a Redis stream, reading messages, and acknowledging them. Each worker should have a unique ID. ```csharp await redis.StreamCreateConsumerGroupAsync("orders", "processors"); var entries = await redis.StreamReadGroupAsync("orders", "processors", "worker-1"); foreach (var entry in entries) { // Process the message await redis.StreamAcknowledgeAsync("orders", "processors", entry.Id!); } ``` -------------------------------- ### Define RedisConfiguration instances Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/configuration/c-configuration.md Defines an array of RedisConfiguration objects to configure multiple Redis connections, including Sentinel settings and server enumeration strategies. ```csharp var configurations = new[] { new RedisConfiguration() { AbortOnConnectFail = true, KeyPrefix = "_my_key_prefix_", Hosts = new RedisHost[] { new RedisHost(){Host = "192.168.0.10", Port = 6379}, new RedisHost(){Host = "192.168.0.11", Port =6379}, new RedisHost(){Host = "192.168.0.12", Port =6379} }, ServiceName = "my-sentinel", // In case you are using Sentinel AllowAdmin = true, ConnectTimeout = 3000, Database = 0, Ssl = true, Password = "my_super_secret_password", ServerEnumerationStrategy = new ServerEnumerationStrategy() { Mode = ServerEnumerationStrategy.ModeOptions.All, TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any, UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw }, MaxValueLength = 1024, PoolSize = 5, IsDefault = true, Name = "My Primary Connection" }, new RedisConfiguration() { AbortOnConnectFail = true, KeyPrefix = "_my_key_prefix_", Hosts = new RedisHost[] { new RedisHost(){Host = "202.147.6.91", Port = 6379}, new RedisHost(){Host = "202.147.6.92", Port =6379}, }, ServiceName = "my-sentinel", // In case you are using Sentinel AllowAdmin = true, ConnectTimeout = 3000, Database = 3, Ssl = true, Password = "my_super_secret_password", ServerEnumerationStrategy = new ServerEnumerationStrategy() { Mode = ServerEnumerationStrategy.ModeOptions.All, TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any, UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw }, MaxValueLength = 1024, PoolSize = 2, Name = "My Secondary Connection" } }: ``` -------------------------------- ### Register RedisConfiguration in DI containers Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/configuration/c-configuration.md Registers the configuration instance into dependency injection containers. ```csharp services.AddSingleton(redisConfiguration); ``` ```csharp container.Register(Component.For().Instance(redisConfiguration)); ``` -------------------------------- ### Set Hash Field with Expiry and Query TTL Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Shows how to set a hash field with a specific time-to-live and then query its remaining TTL. Requires Redis 7.4+. ```csharp await redis.HashSetWithExpiryAsync("user:1", "session", sessionData, TimeSpan.FromMinutes(30)); var ttl = await redis.HashFieldGetTimeToLiveAsync("user:1", new[] { "session" }); ``` -------------------------------- ### Update NuGet Packages Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/migration-v11-to-v12.md Commands to update core, serializer, and optional compression packages to version 12.1.0. ```bash # Update core packages dotnet add package StackExchange.Redis.Extensions.Core --version 12.1.0 dotnet add package StackExchange.Redis.Extensions.AspNetCore --version 12.1.0 # Update your serializer (pick the one you use) dotnet add package StackExchange.Redis.Extensions.System.Text.Json --version 12.1.0 # or: Newtonsoft, MsgPack, Protobuf, MemoryPack, ServiceStack, Utf8Json # Optional: add compression (new in v12) dotnet add package StackExchange.Redis.Extensions.Compression.LZ4 --version 12.1.0 ``` -------------------------------- ### Configure RedisConfiguration manually Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Set the LoggerFactory manually when not using ASP.NET Core dependency injection. ```csharp var config = new RedisConfiguration { LoggerFactory = LoggerFactory.Create(builder => builder.AddConsole()), // ... other config }; ``` -------------------------------- ### Enable Compression with LZ4 Compressor Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/README.md Enables transparent compression for all Redis operations using the LZ4 compressor. Ensure a serializer like SystemTextJsonSerializer is configured. ```csharp // Enable transparent compression with any serializer services.AddStackExchangeRedisExtensions(config); services.AddRedisCompression(); // That's it! // All operations automatically compress/decompress await redis.AddAsync("large-data", myLargeObject); // stored compressed var obj = await redis.GetAsync("large-data"); // decompressed automatically ``` -------------------------------- ### Configure Redis Client with Connection Pooling Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/configuration/connection-pool.md This configuration sets up a Redis client with connection pooling enabled. It specifies connection details, pool size, and the connection selection strategy. Ensure 'ConnectionSelectionStrategy' is set to 'LeastLoaded' or 'RoundRobin' for pooling. ```csharp var redisConfiguration = new RedisConfiguration() { AbortOnConnectFail = false, KeyPrefix = "MyPrefix__", Hosts = [ new RedisHost { Host = "localhost", Port = 6379 } ], AllowAdmin = true, ConnectTimeout = 3000, Database = 0, PoolSize = 2, ConnectionSelectionStrategy = ConnectionSelectionStrategy.LeastLoaded, ServerEnumerationStrategy = new() { Mode = ServerEnumerationStrategy.ModeOptions.All, TargetRole = ServerEnumerationStrategy.TargetRoleOptions.Any, UnreachableServerAction = ServerEnumerationStrategy.UnreachableServerActionOptions.Throw } }; ``` -------------------------------- ### KeyPrefix Effect on Channels Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/pubsub.md When KeyPrefix is configured, it is automatically applied to Pub/Sub channel names. Do not manually add the prefix. ```csharp // Config: KeyPrefix = "myapp:" await redis.PublishAsync("orders", message); // Actual Redis channel: "myapp:orders" ``` -------------------------------- ### Cache-Aside Pattern Implementation Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Implement the cache-aside pattern to retrieve data from a cache or repository. Data is cached for 30 minutes. ```csharp public class ProductService(IRedisDatabase redis, IProductRepository repo) { public async Task GetProductAsync(int id) { var key = $"product:{id}"; var cached = await redis.GetAsync(key); if (cached is not null) return cached; var product = await repo.GetByIdAsync(id); if (product is not null) await redis.AddAsync(key, product, TimeSpan.FromMinutes(30)); return product; } } ``` -------------------------------- ### Use Redis Streams Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/migration-v11-to-v12.md Add, read, and acknowledge entries in Redis Streams. ```csharp await redis.StreamAddAsync("orders", "payload", orderData); var entries = await redis.StreamReadGroupAsync("orders", "processors", "worker-1", ">"); await redis.StreamAcknowledgeAsync("orders", "processors", entries[0].Id.ToString()); ``` -------------------------------- ### Filter logs via appsettings.json Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/logging.md Control log verbosity for the library by setting the log level for the StackExchange.Redis.Extensions.Core category. ```json { "Logging": { "LogLevel": { "Default": "Warning", "StackExchange.Redis.Extensions.Core": "Information" } } } ``` -------------------------------- ### Add Redis Instrumentation with OpenTelemetry Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/openTelemetry.md Use this method to add Redis instrumentation to your services. It requires configuring the instrumentation to add individual connections from the connection pool. ```csharp services .AddRedisInstrumentation() .ConfigureRedisInstrumentation((sp, instrumentation) => { var redisClient = sp.GetRequiredService(); foreach (var connection in redisClient.ConnectionPoolManager.GetConnections()) instrumentation.AddConnection(connection); }); ``` -------------------------------- ### Register NewtonsoftSerializer with Castle.Windsor Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/newtonsoft-json.net.md Register the NewtonsoftSerializer as a singleton component for JSON serialization when using Castle.Windsor. ```aspnet container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); ``` -------------------------------- ### Register SystemTextJsonSerializer with Castle.Windsor Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/serializers/system.text.json.md Register the SystemTextJsonSerializer as a singleton component for Castle.Windsor dependency injection. ```csharp container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); ``` -------------------------------- ### IDistributedCache Integration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/claude-plugin/skills/scaffold/SKILL.md Shows how to use `IDistributedCache` for session management. ```APIDOC ## SessionService.SetAsync ### Description Sets session data in the distributed cache with specified sliding and absolute expiration. ### Method Signature `public async Task SetAsync(string sessionId, byte[] data)` ### Parameters - **sessionId** (string) - Required - The unique identifier for the session. - **data** (byte[]) - Required - The session data to store. ### Request Body Example ```csharp { "sessionId": "user123", "data": [0x01, 0x02, 0x03] // Example byte array } ``` ### Cache Entry Options - **SlidingExpiration**: `TimeSpan.FromMinutes(20)` - **AbsoluteExpirationRelativeToNow**: `TimeSpan.FromHours(4)` ``` -------------------------------- ### Recommendations Use Case with VectorSet Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/vectorset.md Retrieves the approximate vector for a viewed product and then searches for similar products using VectorSet similarity search. Useful for generating product recommendations. ```csharp // Find products similar to what the user just viewed using var vector = await redis.VectorSetGetApproximateVectorAsync("products", viewedProductId); if (vector is not null) { using var similar = await redis.VectorSetSimilaritySearchAsync("products", VectorSetSimilaritySearchRequest.ByVector(vector.Span.ToArray()) with { Count = 10 }); } ``` -------------------------------- ### Retrieving Multiple Items Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/usage/work-with-multiple-items.md Fetches multiple values from Redis by their keys in one roundtrip. ```csharp var users = await redis.GetAllAsync(["key1", "key2"]); ``` -------------------------------- ### Manual Compression Registration Source: https://github.com/imperugo/stackexchange.redis.extensions/blob/master/doc/compressors.md Manually register a `CompressedSerializer` if not using the DI extensions. This involves creating instances of your chosen serializer and compressor. ```csharp var serializer = new CompressedSerializer( new SystemTextJsonSerializer(), new LZ4Compressor() ); services.AddSingleton(serializer); ```