CacheBox is a tool that adds caching to your application to speed things up. It is not dependent on a single cache which makes it very powerful when your application needs frequent change.
A Cache is like short-term memory. It is typically faster than the original data source. Accessing data from RAM is always faster than accessing it from the hard drive. Caching means saving frequently accessed data in-memory (short -term memory).
Getting started
CacheBox is a great box product that is easy to implement and use. In this blog, we will focus on how to integrate a Default provider in a Preside Application. Preside is based on the ColdBox Framework, making it a good example of how to integrate a CacheBox basic provider.
Why use Cache?
Cache is a tool all modern applications need. As developers, we want the best page speed for our applications. One way to obtain that is by implementing cache. You always want to show the most current information, therefore it is important to be careful when using cache. Let’s take a library website as an example, books come and go and inventory changes rapidly, book stocks go up and down and new content is added regularly. Applying cache in this situation needs to be planned carefully, you gain speed but lose clients if stock and inventory is not up to date.
There are a few things we should take into account when we work with cache
- The lifetime for the cache
- It is recommended to not have a very high timeout to autoflush the cache. If we save a big query in the cache, refreshing the query after 5 or 10 minutes is no problem. By doing so, we have freshly cached information is as close as possible to the real database.
- Cache flushing after persistent actions
- We should have control when we cache an object, if there is any persistent action with that object it should remove the specific or generic cache. For instance. If we save book stock in cache and someone adds, edit, or removes any book from the database, the specific or generic cache should be removed to refresh.
- Clear cache on demand
- It is always handy to present an option to the user superadmin to flush the cache on demand. This way the user can renew the cache dataset when needed.
Integrations
To integrate a CacheBox provider there is a few steps to follow:
- Declare CacheBox provider
- Inject the CacheBox provider or use it.
- Use the mainly cacheProvider functions.
- get
- set
- delete
- flush
- Integrated advanced provider. Couchbase.
Declare CacheBox provider
Add the next settings in your application/config/Cachebox.cfc
In this example we are using the default ColdBox cache provider. Feel free to use another provider or even build your own if it is need.
component extends="preside.system.config.Cachebox" {
function configure() {
super.configure( argumentCollection=arguments );
cachebox.caches.mycache = {
provider = "preside.system.coldboxModifications.cachebox.CacheProvider"
, properties = {
objectDefaultTimeout = 300
, objectDefaultLastAccessTimeout = 30
, useLastAccessTimeouts = true
, reapFrequency = 20
, freeMemoryPercentageThreshold = 0
, evictionPolicy = "LFU"
, evictCount = 500
, maxObjects = 2000
, objectStore = "ConcurrentStore"
}
}
}
Inject the CacheBox provider or use it There are 2 ways to use the recently added CacheBox provider.
- Using dependency injection
property name="myCache" inject="cachebox:mycache";
- Getting the caches from the controller superclass
- Regular ColdBox applications
var caches = application.controller.getCachebox().getCaches()
- Preside applications
var caches = getController().getCachebox().getCaches()
- Regular ColdBox applications
- The function above will return you a Struct with all the providers available (caches var). If you want to use a specific provider you can use it as followed.
var myCache = caches['mycache']
Use the main cacheProvider functions
Once you have your Cache provider setting. You can use the next functions
- Data to handler with the cache
var _data = queryNew( "id,name" , "Integer,Varchar" , [ {id=1,name="One"}, {id=2,name="Two"}, {id=3,name="Three"} ] );
- Set data to Cache provider
myCache .set( objectKey = "testid" , object = _data );
- Get data from Cache provider
var resultFromCache = myCache .get( "testid");
- GetorSet data from Cache provider
myCache.getOrSet( "testid", function(){ return queryNew( "id,name" , "Integer,Varchar" , [ {id=1,name="One"}, {id=2,name="Two"}, {id=3,name="Three"} ] ); } )
- Clear object key from Cache provider
myCache.clear( "testid");
- Clear all Cache provider
myCache.clearAll();
Integration of advanced providers. Couchbase
Couchbase Server is an open source, distributed, JSON document database.
It exposes a store with managed cache for high speed data operations, indexers for efficient queries and a powerful query engine for executing SQL-like queries. Couchbase
CacheBox Couchbase Provider Module
To install just drop into your modules folder or use CommandBox to install
box install preside-ext-toomba-couchbase
The Couchbase Provider for Cachebox is a ColdBox 4.x module that allows you to connect CacheBox to a Couchbase cluster and leverage that cluster in your ColdBox applications. This extension is based on Couchbase CacheBox Provider Module for Coldbox
To complete this integration we supposed you have a couchbase server running. Here is an example to use this server locally with docker couchbase:
couchbase:
image: couchbase/server
volumes:
- ./couchbase:/opt/couchbase/var
ports:
- 8091-8094:8091-8094
- 11210-11211:11210-11211
Configure the Couchbase settings. Add the next setting in your Cachebox.cfc
component extends="preside.system.config.Cachebox" {
function configure() {
super.configure( argumentCollection=arguments );
cachebox.caches.couchbase = {
provider = "app.extensions.preside-ext-toomba-couchbase.modules.couchbase-provider.models.CouchbaseColdboxProvider"
, properties = {
objectDefaultLastAccessTimeout = 30
, useLastAccessTimeouts = true
, reapFrequency = 2
, freeMemoryPercentageThreshold = 0
, evictionPolicy = "LFU"
, evictCount = 200
, maxObjects = 1000
, objectStore = "ConcurrentStore"
, objectDefaultTimeout = 120
, ignoreCouchbaseTimeouts = true
, bucketName = server.system.environment["PRESIDE_COUCHBASE_BUCKETNAME"] ?: "default"
, servers = server.system.environment["PRESIDE_COUCHBASE_SERVERS"] ?: "localhost:8091"
, user = server.system.environment["PRESIDE_COUCHBASE_USER"] ?: ""
, password = server.system.environment["PRESIDE_COUCHBASE_PASSWORD"] ?: ""
}
}
}
}
Querying data stored in Couchbase (Advanced uses)
N1QL (pronounced “nickel”) is Couchbase’s query language. The goal of N1QL is to give developers and enterprises an expressive, powerful, and complete language for querying, transforming, and manipulating JSON data. Hence, N1QL supports a full set of SELECT, INSERT, UPDATE, DELETE, MERGE statements along with a rich set of expressions and operators. N1QL is inspired from SQL.
- Run Your First N1QL Query | Couchbase Docs
- N1QL Query Language Tutorial, Learn N1QL
- QUERYING WITH N1QL
There is not a “query” method available by default in the Couchbase Provider, but is possible to use that functionality using the Couchbase Client, that is accesible by the Provider, so just adding a function like this to the provider:
any function query(required any query) output="false" {
return getCouchbaseClient().n1qlQuery(statement = arguments.query);
}
By using that function we can run N1QL queries on our Couchbase server.
var query = "SELECT * FROM BUCKETNAME";
var data = couchbaseCache.query(query);
References