CacheWorker

Defines a behavior to be implemented for managing data that should be held in the VM and periodically refreshed.

Installation

If available in Hex, the package can be installed by adding cache_worker to your list of dependencies in mix.exs:

def deps do
  [
    {:cache_worker, "~> 0.1.0"}
  ]
end

Guide

The data is organized as a key/val data store called a bucket where the keys and vals can be any data type.

Any errors generated by the callback functions will be caught and logged by the callback functions, thus allowing for an insulated, reliable experience for consumers, trying to access the data.

If you wanted to keep track of some widgets, you might create your module thusly:

defmodule WidgetStore do
  use CacheWorker, bucket: :widgets, file: "/tmp/widget-dump"

  def load(key) do
    {:ok, Somewhere.get_widget(key)}
  end
end

Add the WidgetStore module to your supervision tree. This will add the data refresher agent to handle updating the keys on the refresh interval.

children = [
  WidgetStore,
  ...,
]

Supervisor.start_link(children, opts)

When WidgetStore is started, it will load the dump file if one was configured. If a :refresh_interval was configured, a full refresh of all the data will be triggered at that interval, forever.

The &load/1 function on your WidgetStore module defines how the value for a given key is found and is called on whenever (1) a value is being requested and isn’t yet in the bucket, or (2) is being refreshed by the cache worker process.

To get a widget, all a consumer needs to do is call &WidgetStore.get(key) and it will be returned. (&fetch/1 does similarly, but provides more information.) The value from the cache will be used unless it’s the first time for the particular key. In this case, &WidgetStore.load/1 will be dispatched for the value, which will then be cached and returned.

Steps Taken on a &fetch(key) Request:

`&fetch("key")`
--> [Cache] => *from cache* `{:ok, "value from cache"}`
    -or-> *no cache* `&load("key")` => `{:error, "Something went wrong!"}`
        -or-> *Saved to the cache* => `{:ok, "Hot & fresh value!"}`

Options for use CacheWorker

The :bucket option must be defined directly in the use options.

The cascading logic for finding the final list of options is as follows, with each step having the opportunity to override the last:

In the use options, you may pass in any of the values described for the struct fields in CacheWorker.Config.

The &load/1 Callback

This is the only callback you must implement. It should fetch and return the data for the given key. This function should return one of the following:

The &init/1 Callback

You might like to override the default implementation for the &init/1 callback in order to take certain steps when your cache worker starts up, the most obvious of which would be seeding your bucket with certain data.

Simply override the &init/1 callback and return one of the following:

Error Insulation

Cache workers will catch and log any errors that arise from init() or load(). Callers will not need to be overly cautious (catching errors) when reaching for data if they prefer to gracefully continue on failures.

Options for &fetch/1 and &get/2

These functions allow access to the data in the cache worker’s bucket. The following options are available: