README.md

Gibreel
=======
*distributed cache implemented in Erlang*

Installation
------------

Using rebar:

```
{deps, [
	{gibreel, ".*", {hg, "https://bitbucket.org/jjmrocha/gibreel", "default"}}
]}.
```

Start Gibreel
-------------

Gibreel depends on columbo and cclock, you need to start both before gibreel.

```
#!erlang
ok = application:start(columbo),
ok = application:start(cclock),
ok = application:start(gibreel).
```

gibreel Module
--------------

The module gibreel allows you to create and destroy caches.
The main functions are:

* create_cache/1  **To create a basic cache (using defaults)**
* create_cache/2  **To create a cache with options**
* delete_cache/1  **Delete cache**
* list_caches/0  **List all caches**

### create_cache Function

```
#!erlang
gibreel:create_cache(CacheName :: atom()) -> 
	ok | {error, Reason :: any()}.

gibreel:create_cache(CacheName :: atom(), Options :: [Option, ...]) -> 
	ok | {error, Reason :: any()}.
```

The available options are:

* __max_age__ - It's a ``` pos_integer() ``` and represents the expiration time of the items stored in the cache, time in seconds, defaults to 0 (items on the cache don't expire)
* __get_value_function__ - It's a function ``` fun((Key :: term()) -> term() | not_found | error) ``` used by the cache to retrieve the value for the key, defaults to ``` none ```
* __max_size__ - It's a ``` pos_integer() ``` and represents the max number of items stored in the cache, when the max size is reached the oldest key-value is deleted to make space for the new one, defaults to ``` none ```
* __cluster_nodes__ - Must be one of the values ``` local | all | [node(), ...] ```, where (defaults to ``` local ```):
	* ``` local ``` - The cache is local
	* ``` all ``` - The cache must synchronize with all cache instances running in the cluster
    * ``` [node(), ...] ``` The cache must synchronize with all cache instances running on the node list
* __purge_interval__ - It's a ``` pos_integer() ``` and represents the running interval (time in seconds) for the purge process, which removes expired items from the cache, defaults to ``` none ``` (purge process don't run)
* __sync_mode__ - Must be one of the values ``` lazy | full ```, where (defaults to ``` lazy ```):
    * ``` lazy ``` - Cache only synchronize the new key-values or when a item is removed
    * ``` full ``` - Cache must synchronize with all cache instances at start

### delete_cache Function

```
#!erlang
gibreel:delete_cache(CacheName :: atom()) -> ok.
```

Deletes the cache.

### list_caches Function

```
#!erlang
gibreel:list_caches() -> [atom(), ...].
```

Lists the names of all caches.

### Examples

#### Using gibreel as a session storage

The webapp server [Kill Bill](https://bitbucket.org/jjmrocha/kill-bill) uses Gibreel to store the session data.

```
#!erlang
Options = [
    {max_age, 1200},
	{purge_interval, 60},
	{cluster_nodes, all},
	{sync_mode, full}
],
gibreel:create_cache(my_webapp_session, Options).
```

#### Using gibreel as a DB cache

The site [Gmailbox.org](https://www.gmailbox.org) uses Gibreel as a DB cache for CouchDB.

```
#!erlang
LoadFunction = fun(Key) ->
	case chair:get_doc(gmailboxDB, Key) of
		{ok, Doc} -> Doc;
		{db_error, Error} ->
			case jsondoc:get_value(<<"error">>, Error) of
				<<"not_found">> -> not_found;
				_ -> error
			end;
		{error, _} -> error		
	end
end,
Options = [
	{get_value_function, LoadFunction},
	{max_age, 600},
	{max_size, 10000},
	{cluster_nodes, all}
],
gibreel:create_cache(account_cache, Options).
```

g_cache Module
--------------

The module cache allows you to store, remove and retrieve items from cache.
The main functions are:

* store/3  **Stores a key-value pair on the cache**
* get/2  **Retrieves the value for the key**
* remove/2  **Removes a key-value from the cache**
* touch/2  **Changes the item expiration date**
* size/1  **Return the number o key-value pairs in the cache**
* foldl/3  **Calls a function for all elements of the cache and returns an accumulator**

### store Function

```
#!erlang
g_cache:store(CacheName :: atom(), Key :: term(), Value :: term()) -> 
    no_cache | ok.
```

Stores a key-value pair on the cache.

### get Function

```
#!erlang
g_cache:get(CacheName :: atom(), Key :: term()) -> 
    {ok, Value :: term()} | not_found | no_cache | error.
```

Retrieves the value for the key.

### remove Function

```
#!erlang
g_cache:remove(CacheName :: atom(), Key :: term()) -> 
    no_cache | ok.
```

Removes a key-value from the cache.

### touch Function

```
#!erlang
g_cache:touch(CacheName :: atom(), Key :: term()) -> ok.
```

Changes the item expiration date.

### size Function

```
#!erlang
g_cache:size(CacheName :: atom()) -> no_cache | integer().
```

Return the number o key-value pairs in the cache.

### foldl Function

```
#!erlang
g_cache:foldl(CacheName :: atom(), Fun, Acc :: term()) -> no_cache | term().
```

Calls function Fun on successive elements on the cache, starting with Acc. Fun/2 must return a new accumulator which is passed to the next call. The function returns the final value of the accumulator. Acc is returned if the list is empty.

For example:

```
#!erlang
g_cache:foldl(example, fun({_Key, Value}, Acc) ->
    [Value|Acc]
end, []).
```