### Install Foundatio.Minio Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/minio.md Install the Minio package using the .NET CLI. ```bash dotnet add package Foundatio.Minio ``` -------------------------------- ### Install Foundatio.Aliyun Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/aliyun.md Install the Aliyun file storage provider using the .NET CLI. ```bash dotnet add package Foundatio.Aliyun ``` -------------------------------- ### Install Foundatio Aliyun Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio Aliyun package for OSS storage. ```bash # Aliyun OSS (Storage) dotnet add package Foundatio.Aliyun ``` -------------------------------- ### Unit Test Example Source: https://github.com/foundatiofx/foundatio/blob/main/AGENTS.md Demonstrates the Arrange-Act-Assert pattern for a unit test. Ensure necessary setup and assertions are included. ```csharp [Fact] public async Task GetAsync_WithExpiredKey_ReturnsNull() { // Arrange var cache = new InMemoryCacheClient(); await cache.SetAsync("key", "value", TimeSpan.FromMilliseconds(1)); await Task.Delay(10); // Act var result = await cache.GetAsync("key"); // Assert Assert.Null(result); } ``` -------------------------------- ### Install Foundatio.Kafka Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/kafka.md Install the Foundatio.Kafka NuGet package using the .NET CLI. ```bash dotnet add package Foundatio.Kafka ``` -------------------------------- ### Install Foundatio.AWS Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/aws.md Install the Foundatio.AWS NuGet package using the .NET CLI. ```bash dotnet add package Foundatio.AWS ``` -------------------------------- ### Install Foundatio MinIO Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio MinIO package for S3-compatible storage. ```bash # MinIO (S3-compatible Storage) dotnet add package Foundatio.Minio ``` -------------------------------- ### Install Foundatio Kafka Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio Kafka package for messaging. ```bash # Kafka (Messaging) dotnet add package Foundatio.Kafka ``` -------------------------------- ### Install Foundatio SSH/SFTP Storage Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio SSH/SFTP package for storage. ```bash # SSH/SFTP (Storage) dotnet add package Foundatio.Storage.SshNet ``` -------------------------------- ### Install Foundatio.Storage.SshNet Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/sshnet.md Use the .NET CLI to add the Foundatio.Storage.SshNet package to your project. ```bash dotnet add package Foundatio.Storage.SshNet ``` -------------------------------- ### Install Foundatio RabbitMQ Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio RabbitMQ package for messaging. ```bash # RabbitMQ (Messaging) dotnet add package Foundatio.RabbitMQ ``` -------------------------------- ### Install Foundatio Azure Storage Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio Azure Storage package for queues and blobs. ```bash # Azure Storage (Queues, Blobs) dotnet add package Foundatio.AzureStorage ``` -------------------------------- ### Queue Job Implementation Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/jobs.md Example of implementing an IQueueJob for processing items from a queue. Use this for background worker patterns. ```csharp public class EmailJob : QueueJobBase { private readonly IEmailService _emailService; public EmailJob(IEmailService emailService, IQueue queue) : base(queue) { _emailService = emailService; } public override async Task ProcessQueueEntryAsync(IQueueEntry entry) { try { await _emailService.SendAsync(entry.Value.To, entry.Value.Subject, entry.Value.Body); return JobResult.Success; } catch (Exception ex) { return JobResult.FromException(ex); } } } ``` -------------------------------- ### Good Path Examples Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/storage.md Illustrates well-structured and meaningful file paths for organizing storage. ```plaintext // ✅ Good: Organized, meaningful paths "documents/invoices/2024/01/invoice-12345.pdf" "users/user-123/avatars/profile.jpg" "temp/uploads/session-abc/file.tmp" // ❌ Bad: Flat, unclear paths "file1.pdf" "12345.pdf" "abc123" ``` -------------------------------- ### Install Redis Hybrid Cache Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/hybrid-cache.md Install the Foundatio.Redis package for Redis-based hybrid cache integration. ```bash dotnet add package Foundatio.Redis ``` -------------------------------- ### Install Foundatio AWS Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio AWS package for SQS and S3. ```bash # AWS (SQS, S3) dotnet add package Foundatio.AWS ``` -------------------------------- ### Install Foundatio.RabbitMQ Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/rabbitmq.md Add the Foundatio.RabbitMQ NuGet package to your .NET project. ```bash dotnet add package Foundatio.RabbitMQ ``` -------------------------------- ### Install Foundatio Azure Packages Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/azure.md Install the necessary Foundatio packages for Azure Storage or Azure Service Bus using the .NET CLI. ```bash # Azure Storage (Blob, Storage Queues) dotnet add package Foundatio.AzureStorage # Azure Service Bus (Queues, Messaging) dotnet add package Foundatio.AzureServiceBus ``` -------------------------------- ### appsettings.json Example for Foundatio Configuration Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/configuration.md Illustrates how to structure Foundatio settings in appsettings.json, including cache, queue, storage, and resilience options. ```json { "Foundatio": { "Cache": { "Type": "Redis", "Connection": "localhost:6379", "MaxItems": 1000 }, "Queue": { "Type": "Redis", "WorkItemTimeout": "00:05:00", "Retries": 3 }, "Storage": { "Type": "Azure", "ConnectionString": "...", "ContainerName": "files" }, "Resilience": { "MaxAttempts": 5, "InitialDelay": "00:00:01", "UseJitter": true } } } ``` -------------------------------- ### Add Foundatio Package Source: https://github.com/foundatiofx/foundatio/blob/main/README.md Install the Foundatio NuGet package to begin using its features. ```bash dotnet add package Foundatio ``` -------------------------------- ### Install Foundatio Azure Service Bus Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio Azure Service Bus package for queues and messaging. ```bash # Azure Service Bus (Queues, Messaging) dotnet add package Foundatio.AzureServiceBus ``` -------------------------------- ### Start Development Server Source: https://github.com/foundatiofx/foundatio/blob/main/docs/README.md Starts the VitePress development server with hot-reload enabled. The site will be accessible at http://localhost:5173. ```bash npm run docs:dev ``` -------------------------------- ### Install Foundatio Redis Implementation Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md Install the Foundatio Redis implementation package for distributed caching, messaging, and queues. ```bash # Redis implementations dotnet add package Foundatio.Redis ``` -------------------------------- ### Install Foundatio.Extensions.Hosting Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/jobs.md Add the Foundatio.Extensions.Hosting NuGet package to your project to integrate Foundatio jobs with ASP.NET Core's IHostedService. ```bash dotnet add package Foundatio.Extensions.Hosting ``` -------------------------------- ### In-Memory Queuing Example Source: https://github.com/foundatiofx/foundatio/blob/main/README.md Shows how to use InMemoryQueue for enqueuing and dequeuing work items. ```csharp // Queuing IQueue queue = new InMemoryQueue(); await queue.EnqueueAsync(new WorkItem { Data = "Hello" }); var entry = await queue.DequeueAsync(); ``` -------------------------------- ### Common Environment Variables for Foundatio Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/configuration.md Example environment variables for configuring Redis, Azure Storage, and AWS connections. ```bash # Redis connection FOUNDATIO_REDIS_CONNECTION=localhost:6379 # Azure Storage FOUNDATIO_AZURE_STORAGE_CONNECTION=DefaultEndpointsProtocol=https;... # AWS AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_REGION=us-east-1 ``` -------------------------------- ### QueueStats Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/types.md Shows how to retrieve and display statistics for a queue, including the number of queued, working, and deadlettered items. ```csharp var queue = new InMemoryQueue(); var stats = await queue.GetQueueStatsAsync(); Console.WriteLine($"Queued: {stats.Queued}"); Console.WriteLine($"Working: {stats.Working}"); Console.WriteLine($"Deadletter: {stats.Deadletter}"); ``` -------------------------------- ### In-Memory File Storage Example Source: https://github.com/foundatiofx/foundatio/blob/main/README.md Illustrates saving a file using the InMemoryFileStorage. ```csharp // File Storage IFileStorage storage = new InMemoryFileStorage(); await storage.SaveFileAsync("docs/readme.txt", "Hello World"); ``` -------------------------------- ### JobOptions Configuration Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/jobs.md Demonstrates how to configure JobOptions for a continuous job. This includes setting the job name, interval, and iteration limit. ```csharp var options = new JobOptions { Name = "ProcessImports", Interval = TimeSpan.FromMinutes(1), IterationLimit = 100 }; await job.RunContinuousAsync(options); ``` -------------------------------- ### Add MessagePack Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/serialization.md Installs the Foundatio.MessagePack package for MessagePack binary serialization. ```bash dotnet add package Foundatio.MessagePack ``` -------------------------------- ### Add Newtonsoft.Json Package Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/serialization.md Installs the Foundatio.JsonNet package for Newtonsoft.Json integration. ```bash dotnet add package Foundatio.JsonNet ``` -------------------------------- ### In-Memory Caching Example Source: https://github.com/foundatiofx/foundatio/blob/main/README.md Demonstrates basic usage of the InMemoryCacheClient for setting and retrieving cached data. ```csharp // Caching ICacheClient cache = new InMemoryCacheClient(); await cache.SetAsync("user:123", user, TimeSpan.FromMinutes(5)); var cached = await cache.GetAsync("user:123"); ``` -------------------------------- ### FileSpec Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/types.md Demonstrates how to retrieve file metadata using FileSpec and display its properties like path, size, and modification date. ```csharp var storage = new InMemoryFileStorage(); var info = await storage.GetFileInfoAsync("config.json"); if (info != null) { Console.WriteLine($"Path: {info.Path}"); Console.WriteLine($"Size: {info.Size} bytes"); Console.WriteLine($"Modified: {info.Modified}"); } ``` -------------------------------- ### Foundatio With Retry Setup Source: https://github.com/foundatiofx/foundatio/blob/main/benchmarks/RESILIENCE_BENCHMARK_RESULTS.md Configures Foundatio's resilience policy for three total attempts with no delay. ```csharp // With Retry: 3 attempts total _foundatioWithRetry = new ResiliencePolicyBuilder() .WithMaxAttempts(3) .WithDelay(TimeSpan.Zero) .Build(); ``` -------------------------------- ### RedisQueue Features Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/redis.md Demonstrates how to get queue statistics and start continuous processing of work items. ```csharp // Get queue statistics var stats = await queue.GetQueueStatsAsync(); Console.WriteLine($"Queued: {stats.Queued}"); Console.WriteLine($"Working: {stats.Working}"); Console.WriteLine($"Dead Letter: {stats.Deadletter}"); // Process continuously await queue.StartWorkingAsync(async (entry, token) => { await ProcessWorkItemAsync(entry.Value); }); ``` -------------------------------- ### File Storage Stream Access Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/types.md Demonstrates how to use StreamMode to open file streams for writing or reading with Foundatio's file storage. ```csharp var storage = new InMemoryFileStorage(); // Write mode using (var stream = await storage.GetFileStreamAsync("data.txt", StreamMode.Write)) { // stream is non-null, ready for writing } // Read mode using (var stream = await storage.GetFileStreamAsync("data.txt", StreamMode.Read)) { if (stream != null) { // stream exists and is ready for reading } } ``` -------------------------------- ### GetPagedFileListAsync Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Demonstrates how to retrieve files using GetPagedFileListAsync, including iterating through paginated results and filtering by a search pattern. ```csharp var storage = new InMemoryFileStorage(); // Get all files var result = await storage.GetPagedFileListAsync(pageSize: 100); foreach (var file in result.Files) { Console.WriteLine($"{file.Path} ({file.Size} bytes)"); } // Paginate through results while (result.HasMoreResults) { result = await result.GetNextPageAsync(); foreach (var file in result.Files) { Console.WriteLine($"{file.Path}"); } } // Get .txt files only var txtFiles = await storage.GetPagedFileListAsync(pageSize: 50, searchPattern: "*.txt"); ``` -------------------------------- ### Complete Foundatio Dependency Injection Setup Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/dependency-injection.md Demonstrates a comprehensive configuration of Foundatio services, including in-memory caching with dynamic sizing, folder-based storage, in-memory messaging and queuing, cache-based locking, and various resilience policies. Also shows how to register a custom serializer. ```csharp public static void ConfigureFoundatio(IServiceCollection services, IWebHostEnvironment env) { services.AddLogging(builder => builder.AddConsole()); services.AddFoundatio() // Caching with memory limits .Caching.UseInMemory(builder => builder .MaxItems(10000) .WithDynamicSizing(maxMemorySize: 500_000_000) // 500 MB .CloneValues(true) ) // Storage based on environment .Storage.UseFolder(env.IsDevelopment() ? "./data" : "/app/data") // Messaging .Messaging.UseInMemory() // Queuing with custom settings .Queueing.UseInMemory(builder => builder .WorkItemTimeout(TimeSpan.FromMinutes(10)) .MaxAttempts(3) ) // Distributed locking .Locking.UseCache() // Resilience policies .AddResilience(builder = { // Retry with exponential backoff builder.WithRetryPolicy( maxAttempts: 3, delay: TimeSpan.FromMilliseconds(100) ); // Circuit breaker builder.WithCircuitBreaker( failureThreshold: 0.5, samplingDuration: TimeSpan.FromSeconds(30) ); // Timeout builder.WithTimeout(TimeSpan.FromSeconds(10)); }) // Custom serializer .AddSerializer(new SystemTextJsonSerializer()); } // Usage services.AddFoundatio().Caching.UseInMemory(); var provider = services.BuildServiceProvider(); var cache = provider.GetRequiredService(); ``` -------------------------------- ### Register All Foundatio Services with Extension Method Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/dependency-injection.md Use the AddFoundatio() extension method to register all default Foundatio services, which typically use in-memory implementations. This is the quickest way to get started. ```csharp using Foundatio; builder.Services.AddFoundatio(); // Adds default in-memory implementations ``` -------------------------------- ### Publish Message with Options Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/types.md Example of publishing a message with options for correlation ID, delivery delay, and custom properties. ```csharp var bus = new InMemoryMessageBus(); var options = new MessageOptions { CorrelationId = "trace-123", DeliveryDelay = TimeSpan.FromSeconds(10), Properties = new Dictionary { { "Environment", "Production" } } }; await bus.PublishAsync(new UserEvent { UserId = 123 }, options); ``` -------------------------------- ### Install Dependencies Source: https://github.com/foundatiofx/foundatio/blob/main/docs/README.md Installs project dependencies using npm. Ensure Node.js 18.x or higher is installed. ```bash npm install ``` -------------------------------- ### Complete Foundatio Configuration Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/configuration.md Demonstrates a full Foundatio service configuration including caching, storage, messaging, queuing, locking, resilience policies, and custom serialization. ```csharp var services = new ServiceCollection(); services.AddLogging(builder => builder.AddConsole()); services.AddFoundatio() // Caching with memory limit .Caching.UseInMemory(builder => builder .MaxItems(5000) .WithDynamicSizing(maxMemorySize: 100_000_000) .CloneValues(true) ) // Storage using local filesystem .Storage.UseFolder("/app/data") // Messaging (in-memory for single instance) .Messaging.UseInMemory() // Queuing with custom retry settings .Queueing.UseInMemory(builder => builder .WorkItemTimeout(TimeSpan.FromMinutes(5)) .MaxAttempts(3) ) // Distributed locking backed by cache .Locking.UseCache() // Resilience policies with retry and circuit breaker .AddResilience(builder => { builder.WithRetryPolicy(maxAttempts: 3, delay: TimeSpan.FromMilliseconds(100)); builder.WithCircuitBreaker(failureThreshold: 0.5, samplingDuration: TimeSpan.FromSeconds(30)); builder.WithTimeout(TimeSpan.FromSeconds(10)); }) // Custom serializer .AddSerializer( sp => new SystemTextJsonSerializer(), sp => sp.GetRequiredService() ); var serviceProvider = services.BuildServiceProvider(); ``` -------------------------------- ### Configure Application with In-Memory Services Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/in-memory.md Example of configuring an ASP.NET Core application's services to use Foundatio's in-memory providers. ```csharp var builder = WebApplication.CreateBuilder(args); builder.Services.AddFoundatioInMemory(); builder.Services.AddFoundatioQueue("work-items"); builder.Services.AddFoundatioQueue("emails"); var app = builder.Build(); ``` -------------------------------- ### Initialize and Use MinioFileStorage Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/minio.md Initialize MinioFileStorage with a connection string and demonstrate saving and retrieving files. ```csharp using Foundatio.Storage; var storage = new MinioFileStorage(o => o.ConnectionString = "endpoint=play.min.io;accessKey=minioadmin;secretKey=minioadmin;bucket=my-bucket"); await storage.SaveFileAsync("documents/report.pdf", pdfStream); var stream = await storage.GetFileStreamAsync("documents/report.pdf", StreamMode.Read); ``` -------------------------------- ### Get File Information Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/storage.md Explains how to check for file existence and retrieve metadata like path, size, modification, and creation times. ```csharp // Check if file exists bool exists = await storage.ExistsAsync("file.pdf"); // Get file info var fileSpec = await storage.GetFileInfoAsync("file.pdf"); if (fileSpec != null) { Console.WriteLine($"Path: {fileSpec.Path}"); Console.WriteLine($"Size: {fileSpec.Size} bytes"); Console.WriteLine($"Modified: {fileSpec.Modified}"); Console.WriteLine($"Created: {fileSpec.Created}"); } ``` -------------------------------- ### Implement and Run a Job Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/jobs.md Shows how to implement an IJob, register it in DI, and run it once or continuously. Ensure you have the necessary services injected. ```csharp // 1. Implement IJob public class ProcessOrdersJob : JobBase { private readonly IOrderService _orderService; private readonly ILogger _logger; public ProcessOrdersJob(IOrderService orderService, ILogger logger) { _orderService = orderService; _logger = logger; } public override async Task RunAsync(CancellationToken cancellationToken = default) { try { _logger.LogInformation("Starting order processing"); var pending = await _orderService.GetPendingOrdersAsync(cancellationToken); foreach (var order in pending) { if (cancellationToken.IsCancellationRequested) break; await _orderService.ProcessOrderAsync(order, cancellationToken); } return JobResult.Success; } catch (Exception ex) { _logger.LogError(ex, "Order processing failed"); return JobResult.FromException(ex); } } } // 2. Register in DI services.AddSingleton(); // 3. Execute once var job = serviceProvider.GetRequiredService(); var result = await job.RunAsync(); // 4. Or run continuously await job.RunContinuousAsync( interval: TimeSpan.FromMinutes(5), iterationLimit: -1 ); ``` -------------------------------- ### Initialize AliyunFileStorage Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/aliyun.md Instantiate AliyunFileStorage with a connection string. This is the primary method for setting up the storage client. ```csharp using Foundatio.Storage; var storage = new AliyunFileStorage(o => o.ConnectionString = connectionString); await storage.SaveFileAsync("documents/report.pdf", pdfStream); var stream = await storage.GetFileStreamAsync("documents/report.pdf", StreamMode.Read); ``` -------------------------------- ### Configure Aliyun Connection String Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/aliyun.md Set up the AliyunFileStorage by providing the required connection string, including endpoint, access key ID, access key secret, and bucket name. ```csharp var storage = new AliyunFileStorage(o => { o.ConnectionString = "endpoint=oss-cn-hangzhou.aliyuncs.com;accessKeyId=xxx;accessKeySecret=yyy;bucket=my-bucket"; }); ``` -------------------------------- ### Mermaid Diagram Example Source: https://github.com/foundatiofx/foundatio/blob/main/docs/README.md Example of a simple Mermaid diagram in Markdown, illustrating a cache flow. ```txt ┌─────────┐ ┌──────────────┐ ┌──────────────┐ │ Request │────▶│ Local Cache │────▶│ Redis Cache │ └─────────┘ └──────────────┘ └──────────────┘ │ │ ▼ ▼ Cache Hit? Cache Hit? ``` -------------------------------- ### Switching to Production Cache Client Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/in-memory.md Demonstrates how to conditionally register an in-memory cache client in development and a Redis client in production. ```csharp // Easy to swap implementations if (builder.Environment.IsDevelopment()) { services.AddSingleton(); } else { services.AddSingleton(sp => new RedisCacheClient(options => { options.ConnectionMultiplexer = ConnectionMultiplexer.Connect("redis:6379"); })); } ``` -------------------------------- ### Process Import Job Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/types.md Example of a job that processes imports, handling success and timeout exceptions. ```csharp public async Task ProcessImport() { try { await _service.ImportAsync(); return JobResult.Success; } catch (TimeoutException ex) { return JobResult.FromException(ex, "Import timed out"); } } ``` -------------------------------- ### GetFileContentsAsync Extension Method Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Example of using the GetFileContentsAsync extension method to read and print the content of a file. ```csharp var storage = new InMemoryFileStorage(); string content = await storage.GetFileContentsAsync("readme.md"); Console.WriteLine(content); ``` -------------------------------- ### SaveFileAsync Extension Method Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Example of using the SaveFileAsync extension method to save markdown content to a file. ```csharp var storage = new InMemoryFileStorage(); await storage.SaveFileAsync("readme.md", "# Project\n\nDescription here"); ``` -------------------------------- ### Create RedisHybridCacheClient (Convenience) Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/hybrid-cache.md Shows how to use the convenience constructor for RedisHybridCacheClient, which bundles Redis distributed and in-memory caching. Requires Foundatio.Redis.Cache package. ```csharp using Foundatio.Redis.Cache; using StackExchange.Redis; var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379"); // All-in-one Redis hybrid cache var hybridCache = new RedisHybridCacheClient( redisConfig => redisConfig.ConnectionMultiplexer(redis), localConfig => localConfig.MaxItems(1000) ); ``` -------------------------------- ### Preview Production Build Source: https://github.com/foundatiofx/foundatio/blob/main/docs/README.md Locally previews the production build of the static site. ```bash npm run docs:preview ``` -------------------------------- ### Complete Foundatio Sample Application Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/getting-started.md This C# snippet demonstrates setting up and using Foundatio's InMemory implementations for caching, messaging, storage, locking, and queues. It includes subscribing to messages, storing a file, queuing work, and processing the queue with distributed locking. ```csharp using Foundatio.Caching; using Foundatio.Lock; using Foundatio.Messaging; using Foundatio.Queues; using Foundatio.Storage; // Setup services var cache = new InMemoryCacheClient(); var messageBus = new InMemoryMessageBus(); var storage = new InMemoryFileStorage(); var locker = new CacheLockProvider(cache, messageBus); var queue = new InMemoryQueue(); // Subscribe to messages await messageBus.SubscribeAsync(msg => { Console.WriteLine($"Work completed: {msg.ItemId}"); }); // Store a file await storage.SaveFileAsync("config.json", "{\"setting\": \"value\"}"); // Queue work await queue.EnqueueAsync(new WorkItem { Id = "item-1" }); // Process queue with locking while (true) { var entry = await queue.DequeueAsync(TimeSpan.FromSeconds(5)); if (entry == null) break; // Acquire lock for this item await using var lck = await locker.AcquireAsync($"work:{entry.Value.Id}"); if (lck != null) { // Cache progress await cache.SetAsync($"progress:{entry.Value.Id}", "processing"); // Do work... // Complete entry await entry.CompleteAsync(); // Publish completion event await messageBus.PublishAsync(new WorkCompleted { ItemId = entry.Value.Id }); } else { // Couldn't get lock, abandon for retry await entry.AbandonAsync(); } } public record WorkItem { public string Id { get; init; } } public record WorkCompleted { public string ItemId { get; init; } } ``` -------------------------------- ### RedisQueue Configuration Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/queues.md Shows how to configure and instantiate a Redis-backed queue. Requires the Foundatio.Redis package. ```csharp // dotnet add package Foundatio.Redis using Foundatio.Redis.Queues; var queue = new RedisQueue(o => { o.ConnectionMultiplexer = redis; o.Name = "work-items"; o.WorkItemTimeout = TimeSpan.FromMinutes(5); }); ``` -------------------------------- ### Start Background Queue Worker Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/queues.md Starts a background worker that continuously dequeues and processes items. Supports manual or automatic completion of entries. ```csharp Task StartWorkingAsync(Func, CancellationToken, Task> handler, bool autoComplete = false, CancellationToken cancellationToken = default) ``` ```csharp var queue = new InMemoryQueue(); // Manual completion await queue.StartWorkingAsync(async (entry, token) => { try { await ProcessWorkItem(entry.Value, token); await entry.CompleteAsync(); } catch { await entry.AbandonAsync(); } }, autoComplete: false); // Auto-completion (handler must not throw) await queue.StartWorkingAsync(async (entry, token) => { await ProcessWorkItem(entry.Value, token); }, autoComplete: true); ``` -------------------------------- ### Get Queue Statistics Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/queues.md Gets current queue statistics including counts for queued, working, and dead-lettered items. Returns a QueueStats object. ```csharp var stats = await queue.GetQueueStatsAsync(); Console.WriteLine($"Queued: {stats.Queued}"); Console.WriteLine($"Working: {stats.Working}"); Console.WriteLine($"Deadletter: {stats.Deadletter}"); ``` -------------------------------- ### FolderFileStorage Constructor and Usage Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Constructor for FolderFileStorage, which uses the local file system. Includes an example of saving a stream to a file within a specified folder. ```csharp var storage = new FolderFileStorage(new FolderFileStorageOptions { Folder = "/app/data" }); await storage.SaveFileAsync("documents/file.txt", stream); ``` -------------------------------- ### Saga/Process Manager Example Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/messaging.md Implement a Saga or Process Manager to coordinate multi-step asynchronous processes. This example shows an OrderSaga that subscribes to events and publishes subsequent events to manage the order lifecycle. ```csharp public class OrderSaga { private readonly IMessageBus _messageBus; public OrderSaga(IMessageBus messageBus) { _messageBus = messageBus; // Step 1: Order created -> Reserve inventory _messageBus.SubscribeAsync(async order => { await ReserveInventoryAsync(order.OrderId); await _messageBus.PublishAsync(new InventoryReserved { OrderId = order.OrderId }); }); // Step 2: Inventory reserved -> Process payment _messageBus.SubscribeAsync(async evt => { await ProcessPaymentAsync(evt.OrderId); await _messageBus.PublishAsync(new PaymentProcessed { OrderId = evt.OrderId }); }); // Step 3: Payment processed -> Ship order _messageBus.SubscribeAsync(async evt => { await ShipOrderAsync(evt.OrderId); }); } } ``` -------------------------------- ### GetThrottlingLockProvider Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/locks.md Gets or creates a throttling lock provider for a resource. ```APIDOC ## GetThrottlingLockProvider ### Description Gets or creates a throttling lock provider for a resource. ### Method Not specified (likely IThrottlingLockProvider) ### Endpoint Not applicable (SDK method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **resource** (string) - Required - The resource identifier. - **maxLocks** (int) - Required - The maximum number of locks allowed. - **period** (TimeSpan) - Required - The time period for the throttling. ### Response #### Success Response - **IThrottlingLockProvider** - The throttling lock provider instance. ### Example ```csharp var factory = new ThrottlingLockProviderFactory(cache); var throttle = factory.GetThrottlingLockProvider("api_calls", maxLocks: 10, period: TimeSpan.FromSeconds(1)); // Allow only 10 concurrent calls var @lock = await throttle.AcquireAsync("caller_123"); if (@lock != null) { using (@lock) { await CallExpensiveApi(); } } ``` ``` -------------------------------- ### StartWorkingAsync Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/queues.md Starts a background worker that continuously dequeues and processes items. ```APIDOC ## StartWorkingAsync ### Description Starts a background worker that continuously dequeues and processes items. ### Method Not applicable (method on an object instance) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **handler** (Func, CancellationToken, Task>) - Required - The async function invoked for each dequeued entry. - **autoComplete** (bool) - Optional - If true, automatically calls `CompleteAsync` after the handler completes successfully. If false, the handler must explicitly complete or abandon the entry. - **cancellationToken** (CancellationToken) - Optional - Token to stop the background worker. ### Request Example ```csharp var queue = new InMemoryQueue(); // Manual completion await queue.StartWorkingAsync(async (entry, token) => { try { await ProcessWorkItem(entry.Value, token); await entry.CompleteAsync(); } catch { await entry.AbandonAsync(); } }, autoComplete: false); // Auto-completion (handler must not throw) await queue.StartWorkingAsync(async (entry, token) => { await ProcessWorkItem(entry.Value, token); }, autoComplete: true); ``` ### Response #### Success Response None (void Task) #### Response Example None ``` -------------------------------- ### Build Foundatio Project Source: https://github.com/foundatiofx/foundatio/blob/main/AGENTS.md Builds the Foundatio solution using the dotnet CLI. Ensure you are in the project directory. ```bash dotnet build Foundatio.slnx ``` -------------------------------- ### Zero-Configuration Development with In-Memory Providers Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/why-foundatio.md Start developing immediately without setting up external dependencies like Redis or Azure Storage. Foundatio's in-memory providers work out of the box. ```csharp // Works out of the box - no Redis, no Azure, no AWS var cache = new InMemoryCacheClient(); var queue = new InMemoryQueue(); var messageBus = new InMemoryMessageBus(); var storage = new InMemoryFileStorage(); ``` -------------------------------- ### Distributed Locking Example Source: https://github.com/foundatiofx/foundatio/blob/main/README.md Demonstrates acquiring a distributed lock using CacheLockProvider. ```csharp // Distributed Locks ILockProvider locker = new CacheLockProvider(cache, messageBus); await using var handle = await locker.AcquireAsync("resource-key"); ``` -------------------------------- ### Run Foundatio Jobs Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/jobs.md Demonstrates how to run jobs once, continuously with an interval, or with a specific iteration limit. Ensure you have obtained the job instance via dependency injection. ```csharp var job = serviceProvider.GetRequiredService(); // Run once await job.RunAsync(); // Run continuously with a 5-minute pause between iterations await job.RunContinuousAsync( interval: TimeSpan.FromMinutes(5), cancellationToken: stoppingToken); // Run exactly 100 iterations then stop await job.RunContinuousAsync( iterationLimit: 100, cancellationToken: stoppingToken); ``` -------------------------------- ### RemoveByPrefixAsync Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/caching.md Removes all cache entries whose keys start with the specified prefix. ```APIDOC ## RemoveByPrefixAsync ### Description Removes all cache entries whose keys start with the specified prefix. ### Method Task ### Endpoint N/A (Method Signature) ### Parameters #### Path Parameters - **prefix** (string) - Optional - The prefix to match. If null or empty, all cache entries will be removed (flush). ### Response #### Success Response - **int** - The number of entries that were removed. ### Request Example ```csharp var cache = new InMemoryCacheClient(); await cache.SetAsync("user:123:name", "John"); await cache.SetAsync("user:123:email", "john@example.com"); await cache.SetAsync("user:456:name", "Jane"); int removed = await cache.RemoveByPrefixAsync("user:123:"); Console.WriteLine(removed); // 2 ``` ``` -------------------------------- ### Shared Options Base Example Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/configuration.md Illustrates how to configure options for cache and queue components using the shared options base, including logger factory and serializer. ```csharp var loggerFactory = new LoggerFactory(); var cacheOptions = new InMemoryCacheClientOptions { LoggerFactory = loggerFactory, Serializer = new SystemTextJsonSerializer() }; var queueOptions = new InMemoryQueueOptions { LoggerFactory = loggerFactory, Serializer = new SystemTextJsonSerializer() }; ``` -------------------------------- ### Connect to Redis (Basic) Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/redis.md Establishes a basic connection to a Redis instance using StackExchange.Redis. ```csharp using StackExchange.Redis; var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379"); ``` -------------------------------- ### Register CacheLockProvider with DI Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/in-memory.md Example of registering CacheLockProvider as an ILockProvider in a dependency injection container. ```csharp services.AddSingleton(sp => new CacheLockProvider( sp.GetRequiredService(), sp.GetRequiredService())); ``` -------------------------------- ### Implementing Resilience with ResiliencePolicy Source: https://github.com/foundatiofx/foundatio/blob/main/docs/index.md Demonstrates setting up a resilience policy with a maximum number of attempts and exponential backoff delay. Requires Foundatio.Resilience. ```csharp using Foundatio.Resilience; var policy = new ResiliencePolicyBuilder() .WithMaxAttempts(3) .WithExponentialDelay(TimeSpan.FromSeconds(1)) .Build(); await policy.ExecuteAsync(async ct => { await SomeUnreliableOperationAsync(ct); }); ``` -------------------------------- ### GetQueueStatsAsync Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/queues.md Gets current queue statistics including counts for queued, working, and dead-lettered items. ```APIDOC ## GetQueueStatsAsync ### Description Gets current queue statistics including counts for queued, working, and dead-lettered items. ### Method `Task GetQueueStatsAsync()` ### Returns `Task` — Queue statistics object containing item counts. ### Example ```csharp var stats = await queue.GetQueueStatsAsync(); Console.WriteLine($"Queued: {stats.Queued}"); Console.WriteLine($"Working: {stats.Working}"); Console.WriteLine($"Deadletter: {stats.Deadletter}"); ``` ``` -------------------------------- ### Initialize RedisCacheClient Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/caching.md Configures a distributed cache client using Redis. Requires the Foundatio.Redis package and a running Redis instance. ```csharp // dotnet add package Foundatio.Redis using Foundatio.Redis.Cache; using StackExchange.Redis; var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379"); var cache = new RedisCacheClient(o => o.ConnectionMultiplexer = redis); await cache.SetAsync("user:123", user, TimeSpan.FromHours(1)); ``` -------------------------------- ### Polly No Retry Setup Source: https://github.com/foundatiofx/foundatio/blob/main/benchmarks/RESILIENCE_BENCHMARK_RESULTS.md Configures Polly with an empty pipeline, effectively disabling resilience strategies. ```csharp // No Retry: Empty pipeline _pollyNoRetry = new ResiliencePipelineBuilder().Build(); ``` -------------------------------- ### Singleton Connection Multiplexer Best Practice Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/redis.md Illustrates the recommended approach of using a single instance of IConnectionMultiplexer for efficiency. ```csharp // ✅ Singleton connection services.AddSingleton( ConnectionMultiplexer.Connect("redis:6379")); // ❌ Creating new connections var redis = ConnectionMultiplexer.Connect("redis:6379"); ``` -------------------------------- ### Foundatio No Retry Setup Source: https://github.com/foundatiofx/foundatio/blob/main/benchmarks/RESILIENCE_BENCHMARK_RESULTS.md Configures Foundatio's resilience policy for a single attempt with no delay. ```csharp // No Retry: 1 attempt, no delay _foundatioNoRetry = new ResiliencePolicyBuilder() .WithMaxAttempts(1) .WithDelay(TimeSpan.Zero) .Build(); ``` -------------------------------- ### GetFileInfoAsync Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Gets metadata about a file without retrieving its contents. Returns file path, size, and timestamps. ```APIDOC ## GetFileInfoAsync ### Description Gets metadata about a file without retrieving its contents. Returns file path, size, and timestamps. ### Method `Task GetFileInfoAsync(string path)` ### Parameters #### Path Parameters - **path** (string) - Required - The path to the file. ### Response #### Success Response - **FileSpec?** - File metadata (path, size, created date, modified date), or null if the file does not exist. ### Request Example ```csharp var storage = new InMemoryFileStorage(); await storage.SaveFileAsync("data.txt", new MemoryStream(Encoding.UTF8.GetBytes("content"))); var info = await storage.GetFileInfoAsync("data.txt"); if (info != null) { Console.WriteLine($"Size: {info.Size} bytes"); Console.WriteLine($"Modified: {info.Modified}"); } ``` ``` -------------------------------- ### GetFileStreamAsync Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/api-reference/storage.md Gets a stream for reading from or writing to a file. Supports both read and write modes, and handles cancellation. ```APIDOC ## GetFileStreamAsync ### Description Gets a stream for reading from or writing to a file. Supports both read and write modes, and handles cancellation. ### Method `Task GetFileStreamAsync(string path, StreamMode streamMode, CancellationToken cancellationToken = default)` ### Parameters #### Path Parameters - **path** (string) - Required - The path to the file. Use forward slashes for directory separators. - **streamMode** (StreamMode) - Required - Whether to open the stream for reading or writing. #### Query Parameters - **cancellationToken** (CancellationToken) - Optional - Token to cancel the operation. ### Response #### Success Response - **Stream?** - A stream for the file, or null if the file does not exist (read mode only). ### Request Example ```csharp var storage = new InMemoryFileStorage(); // Write to a file using (var stream = await storage.GetFileStreamAsync("docs/readme.txt", StreamMode.Write)) { if (stream != null) { var bytes = Encoding.UTF8.GetBytes("Hello World"); await stream.WriteAsync(bytes); } } // Read from a file using (var stream = await storage.GetFileStreamAsync("docs/readme.txt", StreamMode.Read)) { if (stream != null) { using var reader = new StreamReader(stream); string content = await reader.ReadToEndAsync(); Console.WriteLine(content); } } ``` ``` -------------------------------- ### Basic Queue Operations with InMemoryQueue Source: https://github.com/foundatiofx/foundatio/blob/main/docs/index.md Shows how to enqueue and dequeue a simple work item using the in-memory queue implementation. Requires Foundatio.Queues. ```csharp using Foundatio.Queues; IQueue queue = new InMemoryQueue(); await queue.EnqueueAsync(new SimpleWorkItem { Data = "Hello" }); var workItem = await queue.DequeueAsync(); ``` -------------------------------- ### Build Static Site Source: https://github.com/foundatiofx/foundatio/blob/main/docs/README.md Builds the static site for production deployment. The output will be placed in the .vitepress/dist directory. ```bash npm run docs:build ``` -------------------------------- ### Register Foundatio Services Source: https://github.com/foundatiofx/foundatio/blob/main/_autodocs/configuration.md Register Foundatio services in the DI container. This is the initial setup for all Foundatio modules. ```csharp services.AddFoundatio() .Caching.UseInMemory() .Storage.UseFolder("/app/data") .Messaging.UseInMemory() .Queueing.UseInMemory() .Locking.UseCache(); ``` -------------------------------- ### AzureServiceBusQueue Configuration Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/queues.md Demonstrates setting up an Azure Service Bus queue. Requires the Foundatio.AzureServiceBus package. ```csharp // dotnet add package Foundatio.AzureServiceBus using Foundatio.AzureServiceBus.Queues; var queue = new AzureServiceBusQueue(o => { o.ConnectionString = "..."; o.Name = "work-items"; }); ``` -------------------------------- ### Registering and Running Work Item Jobs with DI Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/jobs.md Shows how to register job-related services with dependency injection and then run a job using JobRunner with multiple instances for parallel processing. ```csharp // DI registration services.AddSingleton>(sp => new InMemoryQueue()); services.AddSingleton(sp => new InMemoryMessageBus()); services.AddSingleton(sp => sp.GetRequiredService()); services.AddScoped(); services.AddSingleton(sp => { var handlers = new WorkItemHandlers(); handlers.Register( () => sp.GetRequiredService()); return handlers; }); // Run with multiple instances for parallel processing var job = serviceProvider.GetRequiredService(); await new JobRunner(job, serviceProvider, instanceCount: 2).RunAsync(stoppingToken); ``` -------------------------------- ### Use Scoped Storage for Tenant Isolation Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/storage.md Example of creating a ScopedFileStorage instance to ensure storage isolation between tenants. ```csharp // Each tenant has isolated storage var tenantStorage = new ScopedFileStorage(baseStorage, tenantId); ``` -------------------------------- ### Configure Cache Options Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/configuration.md Register and use the Options pattern to configure application settings. This example shows how to configure cache settings, allowing for different implementations based on the 'Type' option. ```csharp // Define options class public class CacheOptions { public string Type { get; set; } = "InMemory"; public int MaxItems { get; set; } = 1000; public string RedisConnection { get; set; } } // Register and use builder.Services.Configure( builder.Configuration.GetSection("Cache")); builder.Services.AddSingleton(sp => { var options = sp.GetRequiredService>().Value; return options.Type == "Redis" ? new RedisCacheClient(...) : new InMemoryCacheClient(o => o.MaxItems = options.MaxItems); }); ``` -------------------------------- ### In-Memory CacheClient Unit Test Source: https://github.com/foundatiofx/foundatio/blob/main/docs/guide/implementations/in-memory.md Example of a unit test using InMemoryCacheClient to verify caching and retrieval functionality. ```csharp public class CacheTests { [Fact] public async Task ShouldCacheAndRetrieveValue() { // Arrange var cache = new InMemoryCacheClient(); // Act await cache.SetAsync("key", "value"); var result = await cache.GetAsync("key"); // Assert Assert.Equal("value", result); } } ```