GM.Caching
1.0.0
dotnet add package GM.Caching --version 1.0.0
NuGet\Install-Package GM.Caching -Version 1.0.0
<PackageReference Include="GM.Caching" Version="1.0.0" />
<PackageVersion Include="GM.Caching" Version="1.0.0" />
<PackageReference Include="GM.Caching" />
paket add GM.Caching --version 1.0.0
#r "nuget: GM.Caching, 1.0.0"
#:package GM.Caching@1.0.0
#addin nuget:?package=GM.Caching&version=1.0.0
#tool nuget:?package=GM.Caching&version=1.0.0
<p align="center"> <img src="https://raw.githubusercontent.com/gmetskhvarishvili/GM.Caching/master/icon.png" alt="GM.Caching" width="140" height="140" /> </p>
GM.Caching
A small, provider-agnostic caching abstraction for .NET. Depend on one interface —
ICacheService — with typed get/set, GetOrCreateAsync (single-flight, no cache stampede),
and absolute/sliding expiration. Ships an in-memory implementation; add a distributed backend with
GM.Caching.Redis. Targets .NET 10.
Packages
The two packages version and release together (lockstep):
| Package | What it gives you |
|---|---|
GM.Caching |
ICacheService, CacheEntryOptions, and an in-memory implementation over IMemoryCache (AddGMCaching()). |
GM.Caching.Redis |
A Redis implementation over StackExchange.Redis (AddGMRedisCaching()) — same interface, distributed. |
dotnet add package GM.Caching # in-memory
dotnet add package GM.Caching.Redis # + Redis backend
Quick start
In-memory
using GM.Caching;
builder.Services.AddGMCaching(); // optionally: o => o.KeyPrefix = "myapp:"
Redis
using GM.Caching.Redis;
builder.Services.AddGMRedisCaching(o =>
{
o.ConnectionString = "localhost:6379";
o.KeyPrefix = "myapp:";
});
// or bind from configuration: builder.Services.AddGMRedisCaching(builder.Configuration, "Redis");
Use it
Inject ICacheService — the same code works with either backend:
public class WeatherService(ICacheService cache, IWeatherApi api)
{
public Task<Forecast> GetAsync(string city) =>
cache.GetOrCreateAsync(
$"forecast:{city}",
ct => api.FetchAsync(city, ct),
CacheEntryOptions.Absolute(TimeSpan.FromMinutes(10)));
}
GetOrCreateAsync is single-flight: if many callers ask for the same missing key at once, the
factory runs once and everyone gets that result — no stampede on your database or upstream API.
The interface
Task<T?> GetAsync<T>(string key, CancellationToken ct = default);
Task SetAsync<T>(string key, T value, CacheEntryOptions? options = null, CancellationToken ct = default);
Task<T> GetOrCreateAsync<T>(string key, Func<CancellationToken, Task<T>> factory, CacheEntryOptions? options = null, CancellationToken ct = default);
Task<bool> ExistsAsync(string key, CancellationToken ct = default);
Task RemoveAsync(string key, CancellationToken ct = default);
CacheEntryOptions.Absolute(ttl) / CacheEntryOptions.Sliding(window) set per-entry expiration;
CacheServiceOptions.KeyPrefix and DefaultAbsoluteExpiration apply provider-wide. The Redis
provider JSON-serializes values and refreshes the key TTL on read for sliding entries.
Repository layout
GM.Caching/ # ICacheService, options, in-memory implementation
GM.Caching.Redis/ # Redis implementation (StackExchange.Redis)
tests/GM.Caching.Tests/ # xUnit tests for the in-memory cache
Building & testing
dotnet build -c Release
dotnet test -c Release
Releasing
Versioning is automated from Conventional Commits —
see CONTRIBUTING.md. Both packages share one version (Directory.Build.props)
and publish together to nuget.org on each release.
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Caching.Memory (>= 10.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Options (>= 10.0.0)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on GM.Caching:
| Package | Downloads |
|---|---|
|
GM.RealTime.Persistence
Cache-backed IConnectionRegistry for GM.RealTime: stores user↔connection and group membership in GM.Caching (Redis-ready) and guards the read-modify-write with GM.DistributedLock, so presence is correct and shared across server nodes. Register with AddGMRealTimeCacheStore(). |
|
|
GM.RateLimiting
Distributed rate limiting for the GM.* ecosystem. A provider-agnostic IRateLimiterService with policy-based checks (TryAcquireAsync(key, policy)) and three per-policy algorithms — fixed window, sliding window, and token bucket. Counters live in GM.Caching so limits hold across every service instance (unlike ASP.NET Core's per-process limiter), and the check-and-increment is made atomic by a swappable store (default backed by GM.DistributedLock). Composable key strategies (per-user / per-API-key / per-IP / per-endpoint), policies from appsettings or fluent code, and a 429-friendly result (limit / remaining / retry-after). One call — AddGMRateLimiting() — to wire it up. |
|
|
GM.FeatureManagement
Feature flags for the GM.* ecosystem. A provider-agnostic IFeatureManager (IsEnabledAsync / GetVariantAsync) with targeting — percentage rollout, user/tenant overrides, and environment gating — evaluated against a context you pass in. Flag definitions come from a pluggable IFeatureDefinitionProvider (appsettings by default; swap in a hosted service like LaunchDarkly / Azure App Configuration or a GM.EntityFramework-backed admin UI later without touching consumers). Definitions are cached via GM.Caching with a configurable TTL so changes propagate without a redeploy but don't hit the backing store on every check. Wire it up with AddGMFeatureManagement(). The [FeatureGate] attribute and GM.Mediator gating behavior ship in the GM.FeatureManagement.AspNetCore / .Mediator packages. |
|
|
GM.Idempotency
Idempotency-key management for the GM.* ecosystem. A provider-agnostic IIdempotencyService (IsProcessed / MarkAsProcessed / TryGetCachedResult, plus a race-safe ExecuteAsync check-and-set) backed by GM.Caching for TTL-based dedup-key storage and guarded by GM.DistributedLock so two near-simultaneous duplicates cannot both pass the "not yet processed" gate. Stores enough of the original result to replay it safely. Flexible key strategy (caller-supplied or derived/hashed) and one call — AddGMIdempotency() — to wire it up. HTTP middleware and GM.Mediator behavior ship in the GM.Idempotency.Http / .Mediator packages. |
|
|
GM.Secrets
A provider-agnostic secrets abstraction for the GM.* ecosystem. ISecretsService (GetSecret / GetRequiredSecret / typed GetSecret<T>) over a pluggable ISecretsProvider, with config-driven provider selection and optional TTL caching via GM.Caching — so remote lookups (Key Vault, Secrets Manager, Vault) are cheap and rotation happens automatically on cache expiry. Consumers depend only on the interface; the backend is chosen by configuration. Add a provider with GM.Secrets.Environment / GM.Secrets.Configuration. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 315 | 8/2/2026 |