Microsoft Orleans: Grain Caches
Holy moly it’s been a while. Time for some more Orleans goodness, hopefully? Caches!
What are caches and what do they do? As usual, going to lean on Wikipedia to help me out:
In computing, a cache is a hardware or software component that stores data so that future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation or a copy of data stored elsewhere.
So basically a means of getting data faster, sign me up!
Often, you’ll see multiple levels of caching on varying pieces of infrastructure, whether those pieces are all contained within a single piece of hardware (like a computer), or spread across multiple pieces of hardware (like a network). We have the need for speed, and caches gonna give it to ya… ideally!
https://aws.amazon.com/builders-library/caching-challenges-and-strategies/ has a lot of good information, but just to name a few:
- Stale data
- Inconsistent data across caches
- In the case of local caches - memory and/or additional CPU pressure on a system that is otherwise acting as a webserver
- In the case of external caches - additional system complexity, additional hop to get to data (though seemingly still better than having to rerun some sort of querying/aggregating of data from potentially numerous data sources when not caching)
So, it’s been a while since I’ve written anything, much less about Orleans. It’s Hacktoberfest though so I at least gotta try to get that shirt!
Like in past posts where I’m demonstrating something Orleansly, we’ll be working from my github repo starting here https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.62.0. Prior to us creating another
IOrleansFunction, we actually need to write the thing we’re be demonstrating, the cache!
A cache abstraction can (and perhaps should?) have more methods available to it than what we’ll be doing in this post, but this isn’t meant to be a full fledged solution.
The above should look pretty straight forward, but just to go over it anyway:
TValueis the type of value our cache will be storing
IGrainWithStringKeystates that cache will have a string primary key
AddOrUpdate- for adding/updating
values based on a string
key(not to be confused with the grain primary key)
Getfor retrieving a
valuefrom the cache based on a string
In case it isn’t obvious, we have two “keys” in the above declaration. A grain “primary” key, and a “key value pair” key. What’s the difference? Well by having the primary key be a string, we can get different grain instances for each individual string key we provide. Why would we do that? You may have different caches with different value types you want to store, bring up a different cache per customer, or a bit of both.
As for the implementation of the grain, I’m leaning heavily on an LRU cache from the package https://github.com/bitfaster/BitFaster.Caching/.
Again this should all be pretty self explanatory, just a plain old consuming of a cache and not (currently) worrying about things like parameterizing configuration, providing cache eviction methods, persisting the cache to disk in any way, etc.
Keeping this one pretty short and sweet, I implemented within the final code (found here https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.63.0) our
IOrleansFunction so it can be played around with. I might have another post or two this month elaborating on this some more, just cuz I need to do some more PRs! (And get back into the habit of writing, but this is at least the 50th time I’ve said that)
- Code (beginning) https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.62.0
- Code (end) https://github.com/Kritner-Blogs/OrleansGettingStarted/releases/tag/v0.63.0
- Photo by “ashin_k_suresh” on Unsplash.
Microsoft Orleans: Grain Caches