Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/kubagdynia/cachedrive

CacheDrive - Simple in-memory caching provider with the ability to store objects in files.
https://github.com/kubagdynia/cachedrive

cache dotnet-core file-cache memory-cache

Last synced: 8 days ago
JSON representation

CacheDrive - Simple in-memory caching provider with the ability to store objects in files.

Awesome Lists containing this project

README

        

# CacheDrive

[![CI](https://img.shields.io/github/actions/workflow/status/kubagdynia/CacheDrive/dotnet.yml?branch=main)](https://github.com/kubagdynia/CacheDrive/actions?query=branch%3Amain) [![NuGet Version](https://img.shields.io/nuget/v/CacheDrive.svg?style=flat)](https://www.nuget.org/packages/CacheDrive/)

Simple in-memory caching provider with the ability to store objects in files.

### Project structure

- CacheDrive - CacheDrive library
- CacheDrive.ExampleConsoleApp - console application with example use of the Cache Drive library
- CacheDrive.Tests - unit tests

### Installation

Use NuGet Package Manager
```
Install-Package CacheDrive
```
or .NET CLI
```
dotnet add package CacheDrive
```

or just copy into the project file to reference the package
```

```

### How to use

- Register a CacheDrive library, e.g.
```csharp
var services = new ServiceCollection();

IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();

services.RegisterCacheDrive(configuration, configurationSectionName: "CacheSettings");

var serviceProvider = services.BuildServiceProvider();

// rest of the app

serviceProvider.Dispose();
```
- Optionally add the configuration in appsettings.json
```json
{
"CacheSettings": {
"CacheEnabled": true,
"CacheFolderName": "cache",
"CacheExpirationType": "Minutes",
"CacheExpiration": 60,
"CacheType": "MemoryAndFile",
"InitializeOnStartup": true,
"FlushOnExit": true,
"HashKeySalt": "Secret123Secret"
}
}
```
- You can also specify configurations when registering the cacheDrive library
```csharp
services.RegisterCacheDrive(settings: new CacheSettings
{
CacheEnabled = true,
CacheFolderName = "cache",
CacheExpirationType = CacheExpirationType.Minutes,
CacheExpiration = 60,
CacheType = CacheType.MemoryAndFile,
InitializeOnStartup = true,
FlushOnExit = true,
HashKeySalt = "Secret123Secret"
});
```
- Then by injecting ICacheService you can start using write and read from the cache
```csharp
public class App
{
private readonly ICacheService _cacheService;

public App(ICacheService cacheService)
{
_cacheService = cacheService;
}

public async Task Run()
{
// SetAsync, GetAsync and TryGetValue
string cacheKey1 = "testKey";
await cacheService.SetAsync(cacheKey1, "test text...");
var cachedValue1 = await cacheService.GetAsync(cacheKey1);
Console.WriteLine($"GetAsync - cached value: {cachedValue1}");

Console.WriteLine(cacheService.TryGetValue(cacheKey1, out string cachedValue2)
? $"TryGetValue OK - cached value: {cachedValue2}"
: $"TryGetValue NOK - cached value: {cachedValue2}");

Console.WriteLine();

// Set, Get
string cacheKey3 = "testKey2";
cacheService.Set(cacheKey3, 1234567);
int cachedValue3 = cacheService.Get(cacheKey3);
Console.WriteLine($"Get - cached value: {cachedValue3} ");

// ************ with hashKey

Console.WriteLine();
Console.WriteLine("with hashKey");
Console.WriteLine();

// SetAsync, GetAsync and TryGetValue with hashKey
string cacheKey2 = "testKey";
await cacheService.SetAsync(cacheKey2, "test text...", hashKey: true);
var cachedValueWithHashKey1 = await cacheService.GetAsync(cacheKey2, hashKey: true);
Console.WriteLine($"GetAsync with hashKey - cached value: {cachedValueWithHashKey1}");

Console.WriteLine(cacheService.TryGetValue(cacheKey2, hashKey: true, out string cachedValueWithHashKey2)
? $"TryGetValue with haskkey OK - cached value: {cachedValueWithHashKey2}"
: $"TryGetValue with haskkey NOK - cached value: {cachedValueWithHashKey2}");

// Set, Get with hashKey

Console.WriteLine();

string cacheKey4 = "testKey2";
cacheService.Set(cacheKey4, 1234567, hashKey: true);
int cachedValueWithHashKey3 = cacheService.Get(cacheKey4, hashKey: true);
Console.WriteLine($"Get with hashKey - cached value: {cachedValueWithHashKey3} ");
}
}
```

If the **CacheType** is set to **MemoryAndFile** in the configuration, all cache keys that have not expired will be written to files when the application terminates (the name of the directory where the files will be saved can be set in the configuration). When the application starts, the cache will be loaded from the files. If the **CacheType** is set to **Memory**, the cache will be stored only in memory.

A file with a string value might look like this:

[email protected]
```
{"key":"string@testKey","cached":"2024-09-04T09:39:08.5120076Z","expires":"2024-09-04T10:39:08.512008Z","contents":{"key":"testKey","value":"test text..."}}
```

If HashKeySalt is configured, the file may look like this:

string@6B86A0C7C5CEAC4414D7D3BD15DFDDA0616C7626B66F80360F438145B8CF7B9C.json
```
{"key":"string@6B86A0C7C5CEAC4414D7D3BD15DFDDA0616C7626B66F80360F438145B8CF7B9C","cached":"2024-09-04T09:39:08.5222015Z","expires":"2024-09-04T10:39:08.5222015Z","contents":{"key":"6B86A0C7C5CEAC4414D7D3BD15DFDDA0616C7626B66F80360F438145B8CF7B9C","value":"test text..."}}
```

### ICacheService API Explanation

```csharp
public interface ICacheService
{
///
/// Initializes the cache, such as loading data from a file, database, and so on.
/// Should be run before the cache is used, usually at application startup.
/// Can be used many times, each time adding or overwriting data if they have the same keys.
///
Task InitializeAsync();

///
/// Dumps cached data into files, database, and so on.
/// Usually it should be run before the application terminates.
/// Can be used many times, each time saving data that are new or has been changed.
///
Task FlushAsync();

///
/// Returns whether an object with the specified key exists in the cache.
///
/// The key of the value to check.
/// true if the key was found in the cache, otherwise, false.
bool HasItem(string key);

///
/// Returns whether an object with the specified key exists in the cache.
///
/// The key of the value to check.
/// Whether the key should be hashed. Can be used for long keys.
/// true if the key was found in the cache, otherwise, false.
bool HasItem(string key, bool hashKey);

///
/// Attempts to get the value associated with the specified key from the cache.
///
/// The key of the value to get.
///
/// When this method returns, value contains the object from
/// the cache with the specified key or the default value of
/// , if the operation failed.
///
/// true if the key was found in the cache, otherwise, false.
bool TryGetValue(string key, out T value);

///
/// Attempts to get the value associated with the specified key from the cache.
///
/// The key of the value to get.
/// Whether the key should be hashed. Can be used for long keys.
///
/// When this method returns, value contains the object from
/// the cache with the specified key or the default value of
/// , if the operation failed.
///
/// true if the key was found in the cache, otherwise, false.
bool TryGetValue(string key, bool hashKey, out T value);

///
/// Get the value associated with the specified key from the cache.
///
/// The key of the value to get.
/// The value contains the object from the cache with the specified
/// key or the default value of T, if the operation failed.
///
T Get(string key);

///
/// Get the value associated with the specified key from the cache.
///
/// The key of the value to get.
/// Whether the key should be hashed. Can be used for long keys.
/// The value contains the object from the cache with the specified
/// key or the default value of T, if the operation failed.
///
T Get(string key, bool hashKey);

///
/// Get the value associated with the specified key from the cache.
///
/// The key of the value to get.
/// The value contains the object from the cache with the specified
/// key or the default value of T, if the operation failed.
///
Task GetAsync(string key);

///
/// Get the value associated with the specified key from the cache.
///
/// The key of the value to get.
/// Whether the key should be hashed. Can be used for long keys.
/// The value contains the object from the cache with the specified
/// key or the default value of T, if the operation failed.
///
Task GetAsync(string key, bool hashKey);

///
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
///
/// The key to be added or whose value should be updated.
/// The value to add or update.
/// After how many seconds a given value will expire in the cache. Optional parameter.
/// By default, the value is taken from the configuration.
void Set(string key, T value, int expirySeconds = 0);

///
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
///
/// The key to be added or whose value should be updated.
/// The value to add or update.
/// Whether the key should be hashed. Can be used for long keys.
/// After how many seconds a given value will expire in the cache. Optional parameter.
/// By default, the value is taken from the configuration.
void Set(string key, T value, bool hashKey, int expirySeconds = 0);

///
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
///
/// The key to be added or whose value should be updated.
/// The value to add or update.
/// After how many seconds a given value will expire in the cache. Optional parameter.
/// By default, the value is taken from the configuration.
Task SetAsync(string key, T value, int expirySeconds = 0);

///
/// Adds a value to the cache if the key does not already exist, or updates if the key already exists.
///
/// The key to be added or whose value should be updated.
/// The value to add or update.
/// Whether the key should be hashed. Can be used for long keys.
/// After how many seconds a given value will expire in the cache. Optional parameter.
/// By default, the value is taken from the configuration.
Task SetAsync(string key, T value, bool hashKey, int expirySeconds = 0);

///
/// Deletes the object associated with the given key.
///
/// The key of the element to be remove.
/// true if an object was removed successfully; otherwise, false.
bool Delete(string key);

///
/// Deletes the object associated with the given key.
///
/// The key of the element to be remove.
/// Whether the key should be hashed. Can be used for long keys.
/// true if an object was removed successfully; otherwise, false.
bool Delete(string key, bool hashKey);

///
/// Deletes the object associated with the given key.
///
/// The key of the element to be remove.
/// true if an object was removed successfully; otherwise, false.
Task DeleteAsync(string key);

///
/// Deletes the object associated with the given key.
///
/// The key of the element to be remove.
/// Whether the key should be hashed. Can be used for long keys.
/// true if an object was removed successfully; otherwise, false.
Task DeleteAsync(string key, bool hashKey);

///
/// Returns the number of objects in the cache.
///
/// The number of objects in the cache.
int CountCachedObjects();

///
/// Removes all keys and values from the cache
///
void ClearCache();

///
/// Removes all expired keys and values from the cache
///
void ClearExpiredObjects();
}
```

### Configuration

```csharp
public class CacheSettings
{
///
/// Determines whether cache is enabled.
/// Default value is true.
///
public bool CacheEnabled { get; set; } = true;

///
/// Cache folder name.
/// Default value is "cache".
///
public string CacheFolderName { get; set; } = "cache";

///
/// In what units do we specify cache expiration.
/// Default value is Minutes.
///
public CacheExpirationType CacheExpirationType { get; set; } = CacheExpirationType.Minutes;

///
/// After what time the objects in the cache will expire. Based on CacheExpirationType.
/// Default value is 60.
///
public int CacheExpiration { get; set; } = 60;

///
/// Method of storing the cache.
/// Memory - only in memory.
/// MemoryAndFile - In memory while the application is running and in files after the application is closed.
/// Default value is Memory.
///
public CacheType CacheType { get; set; } = CacheType.Memory;

///
/// Initialize cache automatically on startup.
/// Default value is true.
///
public bool InitializeOnStartup { get; set; } = true;

///
/// Before exit, flush the cache data to a files if necessary.
/// Default value is true.
///
public bool FlushOnExit { get; set; } = true;

///
/// Salt, which will be added to the key hash.
/// Default value is an empty string, which means that adding salt is disabled.
///
public string HashKeySalt { get; set; } = "";
}
```

### Code Examples

- CacheDrive.ExampleConsoleApp
https://github.com/kubagdynia/CacheDrive/tree/main/CacheDrive.ExampleConsoleApp
- IpGeolocation
https://github.com/kubagdynia/IpGeolocation/blob/main/IpGeolocation/Services/IpGeolocationService.cs

### Technologies
List of technologies, frameworks and libraries used for implementation:
- [.NET 7.0 or .NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) (platform)
- [NUnit](https://nunit.org/) (testing framework)

### License
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).