cortezaproject / corteza

Low-code platform
https://cortezaproject.org
Apache License 2.0
1.62k stars 372 forks source link

Resource caching for Store and DAL #491

Open darh opened 1 year ago

darh commented 1 year ago

To improve performance and ensure maximum platform stability, we need to support caching lookup, search, and aggregation operations on DAL and store levels.

The scope of this task is only DAL and Store caching implementation. Store and DAL are unaware of the security context and do not provide access control.

Caching backends (CB)

Corteza supports multiple caching backends and allows the selection and configuration of one or more caching backends for each DAL connection.

In the initial version, corteza supports REDIS, Memcache and an in-memory store.

Future versions might support drivers for Amazon ElastiCache, Google MemoryStore and others.

Caching and invalidation mechanisms

Lookup, search, and aggregation operations can be cached. Each resource type and compose module can select the cache strategy it will use.

Cache item key (CIK) format:

CB implementation can hash CIK value if needed.

Cache parameters and how configured BC can be controlled.

Parameters are propagated through calls via context.

CLI

Caching is disabled for all operations.

Code

Caching package provides utility functions to manipulate disabled & max-age parameters in the context. BC must inspect context values and execute accordingly.

HTTP interface

HTTP header Cache-Control is inspected for the no-cache parameter (sets disabled=true) and max-age parameter (seconds). See documentation for details on headers.

Headers are inspected early on request inside a chi router middleware.

Cache invalidation

by directly and indirectly linking resources

Each cached resource is directly or indirectly linked to that cache item. Each CB needs to implement its own dependency checking and invalidate cache items on resource change or removal.

Cache items for lookup operations are linked directly to the resource. CB can always generate CIK from a resource.

For the initial version, cache items for search and aggregate must use intermediate CIKs (example [resource-type]:[module-id]). All cache items related to this resource-type/module-id combo must be invalidated.

This is an oversimplified solution that will cause many cache-miss requests. It will be optimised in the future.

Clean all cache

Cache on a specific connection can be cleaned via API. A new POST endpoint is added, /system/connection/:id/clean-cache. It must be enabled only cache connections. Other connection types should respond with 501 Not Implemented status.

General caching rules

Caching is never enforced and can only be enabled on a CB. The cache can be ignored when data is requested.

When executing an operation, max-age can be passed along to control. Max-age value must be within range (5s ... 86400s)

Drivers

Store and DAL will require a cache driver that satisfies a straightforward interface to store and retrieve payload under a specific key.

Store

Configuration

General resource caching is configured in the .env file using the DB_CACHE_DSN key.

Changing store caching configuration requires server restart.

DSN format examples:

memory://
redis://<user>:<password>@<host>:<port>/<db_number>
redis://<user>:<password>@</path/to/redis.sock>?db=<db_number>
memcached://tcp:<host>:<port>,tcp:<host>:<port>,tcp:<host>:<port>

Provisioning

When DB_CACHE_DNS, Corteza provisions DAL connections and adds a new entry to the DB using the corteza::system:primary-cache type and primary-cache handle. Similar as primary store connection, the primary cache connection must also be read-only.

Initialisation

CortezaApp.InitStore is used to initialise the connection to the primary store connection. The function reads the CB configurations from DB_CACHE_DSN option and wraps the primary store connection.

Implementation

The caching layer for the primary store is a code similar to the RDBMS layer. Each generated function should appropriately interact with both connections - cache and underlying store.

Cache struct {
    store Storer
    cache interface {
        Read(key string) ([]byte, error)
        Write(key string, item []byte) error
    }
}

DAL

Configuration

Initialisation

DAL service implements per-module cache configuration in the storeOpPrep. The function reads the connection and model cache configuration and constructs (wraps) the connection accordingly. If the operation disallows caching, the function should skip CB wrap.

Implementation

Generic DAL driver provides custom create, search, delete, and update functions that interact with the cache driver to read and write cached items. Other operations are routed directly to the underlying storage connection

github-actions[bot] commented 1 year ago

Stale issue message

Bojan-Svirkov commented 1 year ago

Probably will be a part of a patch release or of 2023.9

github-actions[bot] commented 1 year ago

Stale issue message

github-actions[bot] commented 1 year ago

Stale issue message