File Storage¶
The File Storage module provides a standard interface for file and blob operations. Swap implementations via DI (Azure Blob, S3, local filesystem).
Quick Start¶
using Deepstaging.Effects;
using Deepstaging.Storage;
[EffectsModule(typeof(IFileStore))]
public sealed partial class StorageEffects;
[Runtime]
[Uses(typeof(StorageEffects))]
public sealed partial class AppRuntime;
The generator produces Eff<RT, A> wrappers for all six operations on IFileStore.
Effect Interface¶
IFileStore¶
| Method | Returns | Description |
|---|---|---|
UploadAsync(key, content, contentType) |
Task<FileMetadata> |
Upload a file to storage |
DownloadAsync(key) |
Task<Stream> |
Download a file as a stream |
DeleteAsync(key) |
Task |
Delete a file |
ExistsAsync(key) |
Task<bool> |
Check if a file exists |
GetMetadataAsync(key) |
Task<FileMetadata?> |
Get file metadata |
GetPresignedUrlAsync(key, expiry) |
Task<string> |
Generate a time-limited direct URL |
FileMetadata¶
public record FileMetadata(
string Key,
string Filename,
string ContentType,
long Size,
string? ETag,
DateTimeOffset CreatedAt);
Usage¶
// Upload and generate a download link
from metadata in StorageEffects.FileStore.UploadAsync<AppRuntime>(
"invoices/2024/inv-001.pdf", pdfStream, "application/pdf")
from url in StorageEffects.FileStore.GetPresignedUrlAsync<AppRuntime>(
metadata.Key, TimeSpan.FromMinutes(15))
select new { metadata.Key, DownloadUrl = url };
Resilience¶
Apply resilience via a wrapper interface extending IFileStore:
public interface IResilientFileStore : IFileStore
{
[Retry(MaxAttempts = 3)]
[Timeout(30_000)]
new Task<FileMetadata> UploadAsync(string key, Stream content, string contentType);
}
See the Effects module resilience section for details on [Retry], [Timeout], and [CircuitBreaker].
Pluggable Implementations¶
Register a concrete IFileStore implementation in DI. The effect module delegates to whichever implementation is registered: