Any ideas for a cache manager?

Hi all. I'm sure that many of you have already managed a structured cache system in your projects. What I think it's very important is the possibility to use or disable cache without modifying the code, managing indexes and deleting cache when inserting or updating something in the backend. I immagine to manage cache refreshing with events to fire on model saving in the backend, so if the cache is disabled you don't receive any error. What about using the cache inside the frontend? I think there should be the possibility to disable it by config file (cache enabled or disabled) and in debug mode, but putting an if everytime i call the cache is not a good way to perform it. How have you managed a structured caching system?

Hi @Cosimo you can overwrite the get method in your own cache adapter for example

class myCacheAdapter implement Phalcon\Cache\BackendInterface {
    public function get($id) {
        if ($cacheServiceIsAvailable === true) { // cache service is active?
            return parent::get($id);
        }

        return false;
    }

    // the rest of adapter
}

In this way you can enable the service whenever you want without having to modify all the code of your application

Good luck



5.0k

Very nice, thank you @emiliodeg. In terms of performance, returning false is neutral or a little bit slower than not using cache at all?

returning false you can continue using the adapter without changes

$element = $this->persistent->get('myElement'); // posible element cached

if (!$element) { // no cached
    $element = $this->elementManager->get('myElement'); // get fresh element

    $this->persistent->set('myElement', $element); // here you have to overwrite set method to cache is the service is active, similar on get
}

echo $element;

I hope it's help you

Good luck



5.0k
edited Feb '18

I've used your suggestion for the Adapter, so I've extended the File adpter (i need it, no more) using that flag to return false. Than I've created a cache manager in order to manage the cache logic inside a class and not inside the controllers or the methods.

class CacheManager extends Component
{
    /**
     * Get cache data. If data not exists, generate data and save to cache
     */
    public function get($key, $closure, $lifetime = 3000, $prefix = null)
    {
        //if array, serialize it and get unique key, altough use the string $key
        if (is_array($key)) {
            $key = $this->key($key);
        }
        //the prefix is useful to group several serialized keys
        if ($prefix) {
            $key = $prefix . "-" . $key;
        }
        if ($lifetime == 0) {
            return $closure();
        }
        $data = $this->cache->get($key, $lifetime);
        if (!$data) {
            $data = $closure();
            // if cache is disabled skip this step
            if ($this->getDi()->get('config')->cache->active) {
                $this->cache->save($key, $data, $lifetime);
            }
        }
        return $data;
    }

    public function save($key, $data, $lifetime)
    {
        if (is_array($key)) {
            $key = $this->key($key);
        }
        $this->cache->save($key, $data, $lifetime);
    }

    public function delete($key)
    {
        if (is_array($key)) {
            $key = $this->key($key);
        }
        $this->cache->delete($key);
    }

    public function key(array $params = [])
    {
        return md5(json_encode($params));
    }
}

inside config.ini I have a cache section, of course.

So to use cache for a peace of code, or a method, you have just to put it inside the closure. I think that way to manage cache is usefull for large resultsets and their manipulation. I've not considered the possibility to use ORM persistent cache, but you can achieve it in this way

    public static function find($parameters = null)
    {
        // Convert the parameters to an array
        if (!is_array($parameters)) {
            $parameters = [$parameters];
        }
        return \Phalcon\DI::getDefault()->get('cacheManager')->get(
            $parameters,
            function () use ($parameters) {
                return parent::find($parameters);
            }
        );
    }