-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' of https://github.com/Nebula-Software-Systems/Neb…
- Loading branch information
Showing
30 changed files
with
866 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 164 additions & 0 deletions
164
docs/documentation/InMemory/AttributeUsage/AttributeUsage.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# Using the caching attribute | ||
|
||
The attribute that is going to be used is called InMemoryCache. | ||
|
||
As of today, we are limited to using this attribute only in interface definition. | ||
|
||
An example is shown below. | ||
|
||
```csharp | ||
|
||
public interface IInMemoryStuff | ||
{ | ||
[InMemoryCache] | ||
List<SomeObject> SomeMethod(int param1, int param2, string name); | ||
|
||
[InMemoryCache] | ||
Task<List<SomeObject>> AnotherMethod(); | ||
} | ||
|
||
``` | ||
|
||
## Cache Duration | ||
|
||
There are several ways to set your cache duration. | ||
|
||
### Cache duration from attribute | ||
|
||
The easiest way to set the cache duration is by declaring it directly on the interface definition, using the _CacheDurationInSeconds_ property. | ||
|
||
```csharp | ||
|
||
public interface IInMemoryStuff | ||
{ | ||
[InMemoryCache(CacheDurationInSeconds = 120)] | ||
List<SomeObject> SomeMethod(int param1, int param2, string name); | ||
|
||
[InMemoryCache(CacheDurationInSeconds = 272)] | ||
Task<List<SomeObject>> AnotherMethod(); | ||
} | ||
|
||
``` | ||
|
||
Keep in mind the _CacheDurationInSeconds_ accepts cache durations in seconds. | ||
|
||
If no value is inserted, like the first example, the default cache duration will be applied (which is 600 seconds). | ||
|
||
### Cache duration from cache registration | ||
|
||
If you want to use another default value for your cache duration, you can do so while registring the cache. | ||
|
||
Please check [this](../CacheRegistration/CacheRegistration.md) for more information on how to do so. | ||
|
||
### Cache duration from configuration file | ||
|
||
In an effort to make our interfaces more clean while still using custom cache duration, you can leave your cache attribute definition without specifying the cache duration, but that same cache duration comes from a configuration section of _appsettings.json_. | ||
|
||
When configuring your [cache usage](../CacheRegistration/CacheRegistration.md), you can specify a specific section from your _appsettings.json_ file where you are going to read all your cache configurations from. By default, the section name is **_InMemory_**. | ||
|
||
Under the section you defined above, create a new section called _CacheSettings_, where you are going to place the your cache duration. | ||
|
||
The key you need to use here should the a template key based upon the namespace your interface implementation lives upon. For more information on what to place on the key part, please refer to [this](../CacheKeyGeneration/CacheKeyGeneration.md). | ||
|
||
The value for your cache duration should follow the _HH:MM:SS_ pattern, where HH represents Hours, MM represents Minutes and SS represent seconds. So, for example, if you want your cache to have a duration of 1 hour, 15 minutes and 30 seconds, the value should for the duration should be _01:15:30_. | ||
|
||
Below you can find an example of how this could exist in your configuration: | ||
|
||
```json | ||
"InMemory": { | ||
"CacheSettings": { | ||
"Gorold-Payment-Attributes-InMemoryStuff--AnotherMethod": "01:15:30", | ||
"Gorold-Payment-Attributes-InMemoryStuff--SomeMethod--{param1}--{param2}--{name}": "00:20:00" | ||
} | ||
} | ||
``` | ||
|
||
Let's take a closer look at the structure of the second configuration cache key (same conclusions apply for any kind of key to be inserted). | ||
|
||
``` | ||
//this is the key we are analyzing | ||
Gorold-Payment-Attributes-InMemoryStuff--SomeMethod--{param1}--{param2}--{name} | ||
Gorold-Payment-Attributes-InMemoryStuff -> Namespace where the interface, where the attribute was placed, implementation is located. Notice that we replaced all the '.' for '-'. | ||
--SomeMethod--{param1}--{param2}--{name} -> The remaining part of the key is constitued of the method where the attribute was placed, plus the methods it might contain. If no parameters exist, then we don't need to insert them on the cache key definition. If you notice closely, when you are adding cache duration for methods that take parameters, you must add such parameters inside the curly braces. You should add only the parameter name, not its value. Also notice that, unline above, we use double '-' to separate things. | ||
``` | ||
|
||
### Hierarchy in cache duration definition | ||
|
||
One might ask what happens if I define the cache duration inline, meaning in the interface definition, and also in the _appsettings.json_ file. | ||
|
||
As of today, the cache defined in the configuration file will be taken in consideration in this conflict scenario. | ||
|
||
So, this are the cache values taken: | ||
|
||
1. **_Cache defined both in the configuration file and in the interface method_**: value defined in the configuration file taken | ||
2. **_Cache only defined in the configuration file_**: value defined taken as the cache duration | ||
3. **_Cache only defined in the interface method_**: value defined taken as the cache duration | ||
4. **_Cache not defined in the configuration file nor in the interface method_**: default value for cache duration taken | ||
|
||
## Cache Groups | ||
|
||
Sometimes you may have the need to give a group of caches the same duration, because there might be some logical grouping that you want to have. For this case, we have created cache groups. | ||
|
||
Cache groups allow you to specify, in your attribute definition, the cache group it belongs. That is done via the _CacheGroup_ property. There must be a corresponding configuration section under your cache root configuration section (as we saw before, _InMemory_ was the default for that) that indicates the duration for that cache group; that should be in a section called _CacheGroupSettings_ under your root one. The duration time specificied should follow the pattern spoken about earlier, meaning following the _HH:MM:SS_ pattern | ||
|
||
Below you can find an example of cache groups in pratice, which puts the cache created on the method _SomeMethod_ inside a cache group called _GroupA_ and, according to this group's cache configuration, the cache will have a duration of 2 hours 23 minutes and 15 seconds. | ||
|
||
### Interface definition of cache group | ||
|
||
```csharp | ||
|
||
public interface InMemoryStuff | ||
{ | ||
[InMemory(CacheGroup = "GroupA")] | ||
List<SomeObject> SomeMethod(int param1, int param2, string name); | ||
} | ||
|
||
``` | ||
|
||
### Configuration definition of cache group | ||
|
||
```json | ||
"InMemory": { | ||
"CacheGroupSettings": { | ||
"GroupA" : "02:23:15" | ||
} | ||
} | ||
``` | ||
|
||
## Custom Key Names | ||
|
||
Traditionally, you want to use the automatically generated cache keys, because they are designed so that no collisions occur. The way we generate keys is also helpful because they indicate from which method you are caching data from, which can be very helpful. | ||
|
||
Despite the advantages of using our generated cache keys, you might want to set your cache keys with custom names which might be better for your, mainly because you might understand them better. | ||
|
||
To fulfill that need, we introduced a property in our attribute definition called _**CustomCacheName**_. | ||
|
||
An example of that can be seen below: | ||
|
||
### Interface definition of custom cache name | ||
|
||
```csharp | ||
|
||
public interface IInMemoryStuff | ||
{ | ||
[InMemory(CustomCacheName = "MyCustomCacheName")] | ||
List<SomeObject> SomeMethod(int param1, int param2, string name); | ||
} | ||
|
||
``` | ||
|
||
### Configuration definition of our cache duration based on our custom cache key name | ||
|
||
```json | ||
"InMemory": { | ||
"CacheGroupSettings": { | ||
"MyCustomCacheName" : "04:00:00" | ||
} | ||
} | ||
``` | ||
|
||
> :warning: Please note that, if you choose to have a custom cache key name, if you want to use the configurations to specify the cache duration, you need to place the custom cache name chosen, and not the default generated one. | ||
> :warning: When choosing your custom cache names, you must manage key collision, meaning choosing unique custom cache keys, otherwise you will have unwanted behavior in your application. |
66 changes: 66 additions & 0 deletions
66
docs/documentation/InMemory/CacheKeyGeneration/CacheKeyGeneration.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# How keys are generated for our cache | ||
|
||
As we have [discussed](../CacheKeyGeneration/CacheKeyGeneration.md) before, we must place our cache attribute on the interface method(s) that we are interested in caching, and all of this action happens on the interface itself. | ||
|
||
Cache keys, however, are generated based upon the namespace on which such interface is implemented. | ||
|
||
Let's say our interface is: | ||
|
||
```csharp | ||
namespace Gorold.Payment.Attributes | ||
{ | ||
public interface IInMemoryStuff | ||
{ | ||
[InMemoryCache] | ||
List<SomeObject> SomeMethod(int param1, int param2, string name); | ||
} | ||
} | ||
``` | ||
|
||
And the implementation lives on: | ||
|
||
```csharp | ||
namespace Gorold.Payment.Attributes | ||
{ | ||
public class InMemoryStuff : IInMemoryStuff | ||
{ | ||
public List<SomeObject> SomeMethod(int param1, int param2, string name) | ||
{ | ||
var list = new List<SomeObject>(){new SomeObject | ||
{ | ||
Name = name, | ||
Value1 = param1, | ||
Value2 = param2 | ||
}, new SomeObject | ||
{ | ||
Name = name, | ||
Value1 = param2, | ||
Value2 = param1 | ||
}}; | ||
return list; | ||
} | ||
} | ||
} | ||
``` | ||
|
||
The cache key generation formula is: | ||
|
||
``` | ||
namespace.separated.by.dot.with.class.name:method:parameters:separed:by:colon | ||
``` | ||
|
||
So if we call the method with | ||
|
||
- param1 = 10 | ||
- param2 = 20 | ||
- name = Rafael | ||
|
||
We should expect our cache key to be: | ||
|
||
- Gorold.Payment.Attributes.InMemoryStuff:SomeMethod:10:20:Rafael | ||
|
||
As you can see, there are two parts you can easily identity: one which is separated by dot (.) and another that is separated by colon (:). | ||
|
||
The first section, that is separated by dot (.), corresponds to the namespace until the method we placed the attribute (excluding it). | ||
|
||
The second section, that is separated by colon (:), corresponds to the method where the cache attribute has been placed, alongside the values of the attributes that were passed to such method. If no parameters were passed, the cache key would end at _:SomeMethod_. |
61 changes: 61 additions & 0 deletions
61
docs/documentation/InMemory/CacheRegistration/CacheRegistration.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Registring the cache usage | ||
|
||
As mentioned in the [README](../../../../README.md), the first step to start using out our cache is to register the cache usage inside the _Program.cs_ class: | ||
|
||
```csharp | ||
|
||
public class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
// ... | ||
builder.Host.UseNebulaCaching(); | ||
builder.Services.AddInMemoryChache(new Configurations | ||
{ | ||
//some amazing optional configuration options | ||
}); | ||
} | ||
} | ||
|
||
``` | ||
|
||
As mentioned above, in the _AddInMemoryChache_ method, there are some configuration options we can use when registering our cache. | ||
|
||
The following options are, as of today, supported: | ||
|
||
## ConfigurationSection | ||
|
||
String that represents the section in your _appsettings.json_ where the cache configuration will be placed. By default the value here is **_"InMemory"_**.Example of configurations placed in such section may include the cache duration for your keys (if you end up choosing this path). Please refer to [this](../AttributeUsage/AttributeUsage.md) for more information on cache duration options. | ||
|
||
## DefaultCacheDurationInSeconds | ||
|
||
Sometimes we don't want to have the hassle to define cache values for each method, and instead just use a pre-defined cache duration value. | ||
|
||
If you think the current default value for the cache duration doesn't suit you well (600 seconds), then you have the opportunity to override it by making use of the _DefaultCacheDurationInSeconds_ in the _Configurations_ object. | ||
|
||
Insert the int value that represents the new default cache duration, in seconds. | ||
|
||
Again, please refer to [this](../AttributeUsage/AttributeUsage.md) for more information on other ways to set the cache duration. | ||
|
||
## Example of a cache registration | ||
|
||
Below you can find an example of what the cache registration could look like in your _Program.cs_ class, having all we discussed in consideration: | ||
|
||
```csharp | ||
|
||
public class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
// ... | ||
builder.Host.UseNebulaCaching(); | ||
builder.Services.AddInMemoryChache(new InMemoryConfigurations | ||
{ | ||
ConfigurationSection = "InMemoryConfig", | ||
DefaultCacheDurationInSeconds = 120 | ||
}); | ||
} | ||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Documentation entry point | ||
|
||
## Registring the cache usage | ||
|
||
For a more in-depth understading of the cache registration process, please refer to [this](CacheRegistration/CacheRegistration.md). | ||
|
||
## Using the caching attribute | ||
|
||
For a more in-depth understading on the usage of of the caching attribute, please refer to [this](AttributeUsage/AttributeUsage.md). | ||
|
||
## Memory considerations | ||
|
||
For some concerns regarding memory considerations, please refer to [this](MemoryConsiderations/MemoryConsiderations.md). |
3 changes: 3 additions & 0 deletions
3
docs/documentation/InMemory/MemoryConsiderations/MemoryConsiderations.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
As you might already know, there's a limit on the amount of memory available on the machine that is running your .NET applicaton, so you must be very careful when taking the decision of taking a portion of that memory for caching purposes. | ||
|
||
Because of the constraint presented above, our in-memory solution uses a compression algorithm when storing your cached data. Of course, this comes with the cost of running the compression algorithm (and the decompression one when retrieving the cached data), but that's a worthwhile cost to pay. |
Oops, something went wrong.