API Caching
It's often the case that you have at least a few entities which are accessed much more often than they are updated. Typically a site's throughput is limited by the database so the less database traffic that happens the higher that throughput will be. SocialStack has a built in caching mechanism which allows you to mark an entity as cached. This means the list of all entities of that type is obtained once during server startup and then kept up to date through the internal server mesh network.
Caching therefore works best if you cache things accessed frequently but changed rarely. As cached objects are stored in your web servers memory, be careful not to cache something huge such as a type with 10M+ rows unless you have the RAM to spare. Some built in examples are site configuration, locales and the pages of your site. These are all cached by default.
Usage
To make an entity use the cache, simply call Cache(); from within the service constructor:
public ThingService() {
// "Thing" entities will be cached.
Cache();
}
If it is a thirdparty service and you would like to avoid editing its source to allow for easier updates, you can also call Cache(); via the Events.Service.AfterStart event.
Functionality
The cache reuses objects whenever possible so when you ask a caching service to get or list objects then little to no allocations actually happen. These calls also return instantaneously as the object is coming from an already loaded in-memory data structure. In the example above, if you ask "ThingService" to get object with ID #14, that returned object is returned immediately, comes from the cache and is also reused.
Because the object is reused, avoid changing its fields anywhere other than via Update.
// private ThingService _thingService;
// This returns instantly with a reused object.
var thing14 = await _thingService.Get(context, 14);
// Because it's reused, do not edit fields!
// thing14.Name = "do not do this";
// The only correct way to update fields is via the usual update call:
thing14 = await _thingService.Update(context, thing14, (Context c, Thing updateable) => {
updateable.Name = "Updated Name";
});
Performance
Because cached services are not depending on the database and do not allocate, they have extremely high throughput. You can use service Get hundreds of millions of times per second without risking long GC pauses (not that you would ever put this much traffic on one server though!). The JSON serialisation process also avoids as many allocations as possible and can also return more than 10 million results per second via a websocket. The limiting factor is usually the network bandwidth.
Note that the use of the websocket is important if you are expecting this level of throughput being necessary. That is because the context needs to collect the user information which usually involves the database (the user service is rarely set to being cached, but you can do that too) and this context load only occurs once on a websocket.
ID Assignment
Because caching a service is primarily done for performance, enabling the cache also makes a service switch ID assignment model. This is covered in more detail on the clustering mechanics page.