<commit_before># lua-resty-mlcache

[![Build Status][badge-travis-image]][badge-travis-url]

Fast and automated multi-level cache for OpenResty.

This library can be can be manipulated as a key/value store caching scalar Lua
types and tables, but is built on top of [lua_shared_dict] and
[lua-resty-lrucache]. This combination allows for extremely performant and
flexible caching.

Features:

- Caching and negative caching with TTLs.
- Built-in mutex via [lua-resty-lock] to prevent dog-pile effects to your
  database/backend on cache misses.
- Built-in inter-workers communication to propagate cache invalidations
  and allow workers to update their L1 (lua-resty-lrucache) caches upon changes
  (`set()`, `delete()`).
- Multiple isolated instances can be created to hold various types of data
  while relying on the *same* `lua_shared_dict` L2 cache.

Illustration of the various caching levels built into this library:

```
┌─────────────────────────────────────────────────┐
│ Nginx                                           │
│       ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│       │worker     │ │worker     │ │worker     │ │
│ L1    │           │ │           │ │           │ │
│       │ Lua cache │ │ Lua cache │ │ Lua cache │ │
│       └───────────┘ └───────────┘ └───────────┘ │
│             │             │             │       │
│             ▼             ▼             ▼       │
│       ┌───────────────────────────────────────┐ │
│       │                                       │ │
│ L2    │           lua_shared_dict             │ │
│       │                                       │ │
│       └───────────────────────────────────────┘ │
│                           │                     │
│                           ▼                     │
│                  ┌──────────────────┐           │
│                  │     callback     │           │
│                  └────────┬─────────┘           │
└───────────────────────────┼─────────────────────┘
                            │
  L3                        │   I/O fetch
                            ▼

                   Database, API, I/O...
```

The cache level hierarchy is:
- **L1**: Least-Recently-Used Lua-land cache using [lua-resty-lrucache].
   Provides the fastest lookup if populated, and avoids exhausting the workers'
   Lua VM memory.
- **L2**: `lua_shared_dict` memory zone shared by all workers. This level
   is only accessed if L1 was a miss, and prevents workers from requesting the
   L3 cache.
- **L3**: a custom function that will only be run by a single worker
   to avoid the dog-pile effect on your database/backend
   (via [lua-resty-lock]). Values fetched via L3 will be set to the L2 cache
   for other workers to access.

# Table of Contents

- [Synopsis](#synopsis)
- [Installation](#installation)
- [Methods](#methods)
    - [new](#new)
    - [get](#get)
    - [peek](#peek)
    - [set](#set)
    - [delete](#delete)
    - [update](#update)
- [License](#license)

# Synopsis

```
# nginx.conf

http {
    # you do not need to configure the following line when you
    # use LuaRocks or opm.
    lua_package_path "/path/to/lua-resty-mlcache/lib/?.lua;;";

    lua_shared_dict cache 1m;

    init_by_lua_block {
        local mlcache = require "resty.mlcache"

        local cache, err = mlcache.new("cache", {
            lru_size = 500,    -- size of the L1 (Lua-land LRU) cache
            ttl      = 3600,   -- 1h ttl for hits
            neg_ttl  = 30,     -- 30s ttl for misses
        })
        if err then

        end

        -- we put our instance in the global table for brivety in
        -- this example, but prefer an upvalue to one of your modules
        -- as recommended by ngx_lua
        _G.cache = cache
    }

    server {
        listen 8080;

        location / {
            content_by_lua_block {
                local function callback(username)
                    -- this only runs *once* until the key expires, so
                    -- do expansive operations like connecting to a remote
                    -- backend here. i.e: call a MySQL server in this callback
                    return db:get_user(username) -- { name = "<NAME>", email = "<EMAIL>" }
                end

                -- this call will respectively hit L1 and L2 before running the
                -- callback (L3). The returned value will then be stored in L2 and
                -- L1 for the next request.
                local user, err = cache:get("my_key", nil, callback, "<NAME>")
                if err then

                end

                ngx.say(user.username) -- "<NAME>"
            }
        }
    }
}
```

[Back to TOC](#table-of-contents)

# Installation

With [Luarocks](https://luarocks.org/):

```
$ luarocks install lua-resty-mlcache
```

Or via [opm](https://github.com/openresty/opm):

```
$ opm get thibaultcha/lua-resty-mlcache
```

Or manually:

Once you have a local copy of this module's `lib/` directory, add it to your
`LUA_PATH` (or `lua_package_path` directive for OpenResty):

```
/path/to/lib/?.lua;
```

[Back to TOC](#table-of-contents)

# Methods

new<commit_msg>docs(readme) add requirements section<commit_after># lua-resty-mlcache

[![Build Status][badge-travis-image]][badge-travis-url]

Fast and automated multi-level cache for OpenResty.

This library can be can be manipulated as a key/value store caching scalar Lua
types and tables, but is built on top of [lua_shared_dict] and
[lua-resty-lrucache]. This combination allows for extremely performant and
flexible caching.

Features:

- Caching and negative caching with TTLs.
- Built-in mutex via [lua-resty-lock] to prevent dog-pile effects to your
  database/backend on cache misses.
- Built-in inter-workers communication to propagate cache invalidations
  and allow workers to update their L1 (lua-resty-lrucache) caches upon changes
  (`set()`, `delete()`).
- Multiple isolated instances can be created to hold various types of data
  while relying on the *same* `lua_shared_dict` L2 cache.

Illustration of the various caching levels built into this library:

```
┌─────────────────────────────────────────────────┐
│ Nginx                                           │
│       ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│       │worker     │ │worker     │ │worker     │ │
│ L1    │           │ │           │ │           │ │
│       │ Lua cache │ │ Lua cache │ │ Lua cache │ │
│       └───────────┘ └───────────┘ └───────────┘ │
│             │             │             │       │
│             ▼             ▼             ▼       │
│       ┌───────────────────────────────────────┐ │
│       │                                       │ │
│ L2    │           lua_shared_dict             │ │
│       │                                       │ │
│       └───────────────────────────────────────┘ │
│                           │                     │
│                           ▼                     │
│                  ┌──────────────────┐           │
│                  │     callback     │           │
│                  └────────┬─────────┘           │
└───────────────────────────┼─────────────────────┘
                            │
  L3                        │   I/O fetch
                            ▼

                   Database, API, I/O...
```

The cache level hierarchy is:
- **L1**: Least-Recently-Used Lua-land cache using [lua-resty-lrucache].
   Provides the fastest lookup if populated, and avoids exhausting the workers'
   Lua VM memory.
- **L2**: `lua_shared_dict` memory zone shared by all workers. This level
   is only accessed if L1 was a miss, and prevents workers from requesting the
   L3 cache.
- **L3**: a custom function that will only be run by a single worker
   to avoid the dog-pile effect on your database/backend
   (via [lua-resty-lock]). Values fetched via L3 will be set to the L2 cache
   for other workers to access.

# Table of Contents

- [Synopsis](#synopsis)
- [Requirements](#requirements)
- [Installation](#installation)
- [Methods](#methods)
    - [new](#new)
    - [get](#get)
    - [peek](#peek)
    - [set](#set)
    - [delete](#delete)
    - [update](#update)
- [License](#license)

# Synopsis

```
# nginx.conf

http {
    # you do not need to configure the following line when you
    # use LuaRocks or opm.
    lua_package_path "/path/to/lua-resty-mlcache/lib/?.lua;;";

    lua_shared_dict cache 1m;

    init_by_lua_block {
        local mlcache = require "resty.mlcache"

        local cache, err = mlcache.new("cache", {
            lru_size = 500,    -- size of the L1 (Lua-land LRU) cache
            ttl      = 3600,   -- 1h ttl for hits
            neg_ttl  = 30,     -- 30s ttl for misses
        })
        if err then

        end

        -- we put our instance in the global table for brivety in
        -- this example, but prefer an upvalue to one of your modules
        -- as recommended by ngx_lua
        _G.cache = cache
    }

    server {
        listen 8080;

        location / {
            content_by_lua_block {
                local function callback(username)
                    -- this only runs *once* until the key expires, so
                    -- do expansive operations like connecting to a remote
                    -- backend here. i.e: call a MySQL server in this callback
                    return db:get_user(username) -- { name = "<NAME>", email = "<EMAIL>" }
                end

                -- this call will respectively hit L1 and L2 before running the
                -- callback (L3). The returned value will then be stored in L2 and
                -- L1 for the next request.
                local user, err = cache:get("my_key", nil, callback, "<NAME>")
                if err then

                end

                ngx.say(user.username) -- "<NAME>"
            }
        }
    }
}
```

[Back to TOC](#table-of-contents)

# Requirements

* OpenResty >= `1.11.2.2`
    * ngx_lua
    * lua-resty-lrucache
    * lua-resty-lock

This library **should** be entirely compatible with older versions of
OpenResty, but it has only been tested against OpenResty `1.11.2.2` and
greater.

[Back to TOC](#table-of-contents)

# Installation

With [Luarocks](https://luarocks.org/):

```
$ luarocks install lua-resty-mlcache
```

Or via [opm](https://github.com/openresty/opm):

```
$ opm get thibaultcha/lua-resty-mlcache
```

Or manually:

Once you have a local copy of this module's `lib/` directory, add it to your
`LUA_PATH` (or `lua_package_path` directive for OpenResty):

```
/path/to/lib/?.lua;
```

[Back to TOC](#table-of-contents)

# Methods

new
{'fraction_non_alphanumeric': 0.15304578130911842, 'fraction_numerical': 0.007567158531971245, 'mean_word_length': 1.7845667632341322, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '999458', 'n_tokens_mistral': 3431, 'n_tokens_neox': 3140, 'n_words': 1102}