Boosting Performance with External Cache Integration in Evolutivo Framework

EvolutivoFW is a powerful open-source business and development system that offers a wide range of features to manage and streamline business processes. Among its arsenal of capabilities is the external cache integration, a feature that can significantly enhance the performance and scalability of the system. In this blog post, we will delve into the workings of EvolutivoFW's external cache integration and explore how it can be leveraged to optimize system performance.

Cache Integration: Improving Performance and Scalability

The external cache integration in EvolutivoFW revolves around utilizing an external caching system to store frequently accessed data. By doing so, the need to retrieve this data from the database on every request is reduced, leading to improved overall system performance. The integration acts as a middle layer between the application and the database, effectively reducing the number of database queries and enhancing response times. This feature proves particularly useful in scenarios with high user concurrency and heavy database usage.

Configuring the External Cache

To start harnessing the benefits of the external cache integration, the application must be configured to connect and communicate with the chosen caching system. EvolutivoFW supports various caching systems like Memcached and Redis. The configuration process typically involves specifying the cache server's host, port, and any required authentication credentials. You can access the cache configuration settings in the "Utilities" section of the EvolutivoFW interface.

I would recommend using docker to start the external service and keeping it closed inside the server or available only over an internal private network. Please do not expose the cache service on the internet.

Once the configuration is complete, EvolutivoFW can store different types of data in the cache. This includes database query results, module-specific data, user sessions, and other frequently accessed information. When data is requested, EvolutivoFW first checks if it exists in the cache. If found, the data is retrieved directly from the cache, eliminating the need to query the database.

To maintain data consistency, EvolutivoFW implements cache invalidation mechanisms. Whenever a relevant record is modified or deleted, the corresponding cache entries are invalidated or cleared. This ensures that the application always retrieves the most up-to-date information, preventing any discrepancies between cached and database-stored data. Our integration includes methods that are specific to the idiosyncrasy of the application permitting us to invalidate values depending on modifications done in modules and individual records.

To prevent the accumulation of stale data in the cache, EvolutivoFW incorporates cache expiration functionality. You can set a time-to-live (TTL) value for cache entries, determining how long they will remain valid in the cache. After the TTL expires, the entries are automatically removed from the cache. This ensures that data is periodically refreshed from the database, allowing for accurate and current information retrieval.

Using the External Cache Integration

Once the connection to the cache server is established and activated, you can utilize the global cache object named $cbAppCache within your code. This object follows the PSR-16 caching interface and is based on the Laminas Cache library, providing extensive functionality. Some of the available methods include get, set, setMultiple, delete, deleteMultiple, has. These methods allow you to perform various caching operations, such as retrieving, setting, deleting, and checking the existence of cache entries.

Additionally to the PSR-16 standard methods, you can use these two methods: hasWithModuleCheck, and hasWithQueryCheck which permit us to search for keys depending on the modification date of a specific record or the whole set of records in a module.

You can find the complete information in the Cache Layer Library Documentation

Examples

To help you understand the usage of the cache integration, you can find code examples and references to different parts of EvolutivoFW that utilize the caching functionality in the Cache Layer Library Documentation. These examples showcase its versatility and applicability across various scenarios.

Specifically, we can analyze the usage of the library in the EvolutivoFW Rule calculation.

The code starts with this block:

if ($cbAppCache->isUsable()) {
    $cacheKey = md5(implode('', $adb->flatten_array($params)));
    $query = '(select vtiger_crmentity.modifiedtime
        from vtiger_crmentity
        inner join vtiger_cbmap on (vtiger_cbmap.targetname=vtiger_crmentity.setype and vtiger_cbmap.cbmapid=?)
        where vtiger_crmentity.deleted=0 order by modifiedtime desc limit 1)
        UNION
        (select vtiger_crmentity.modifiedtime
        from vtiger_crmentity
        where vtiger_crmentity.deleted=0 and vtiger_crmentity.crmid=?) order by modifiedtime desc limit 1';
    if ($cbAppCache->getCacheClient()->hasWithQueryCheck($cacheKey, $query, [$conditionid, $conditionid])) {
        $cacheValue = $cbAppCache->getCacheClient()->get($cacheKey);
        cbEventHandler::do_action('corebos.audit.rule', array($current_user->id, $params, false, 'Cache', $cacheValue, date('Y-m-d H:i:s')));
        return $cacheValue;
    }
}

where we see that we first check if the cache layer integration is usable or not, then we calculate the key and check for the key validity based on a complex query that returns the last modified time of the records in the target module that the rule uses, if any record in that module has changed since the last time we calculated the saved value then we must calculate it again, and the last modified time of the business map that holds the expression, if this record has changed we must calculate the result again.

We do this using the specific hasWithQueryCheck method. If the key is found we return its value without calculating the expression again.

Finally, at the end of the script we save the value if we have calculated it.

if ($cbAppCache->isUsable()) {
    $cbAppCache->getCacheClient()->setMultiple([$cacheKey => $ruleinfo, $cacheKey.$cbAppCache->getCacheClient()->getModifiedTimePostfix() => date('YmdHis')]);
}

Note that the value is invalidated and eliminated from the cache service when the hasWithQueryCheck fails.

Future Possibilities

I encourage the migration of the existing memory-based cache to the new library, ensuring consistency and efficiency throughout the application, but we should also keep an open mind to other usability options that may be useful.

The external cache integration in EvolutivoFW offers a scalable and efficient solution to optimize application performance

HTH

Previous Post Next Post