Metadata-Version: 2.5
Name: collective.redismemoize
Version: 1.0.0a1
Summary: Redis-backed storage for plone.memoize, shared across Plone instances, that keeps values Redis can't safely store in each process's RAM cache.
Project-URL: Homepage, https://github.com/collective/collective.redismemoize
Project-URL: Documentation, https://collective.github.io/collective.redismemoize/
Project-URL: PyPI, https://pypi.org/project/collective.redismemoize
Project-URL: Source, https://github.com/collective/collective.redismemoize
Project-URL: Tracker, https://github.com/collective/collective.redismemoize/issues
Author-email: Érico Andrei <ericof@plone.org>
License-Expression: GPL-2.0-only
License-File: LICENSE.GPL
License-File: LICENSE.md
Keywords: CMS,Plone,Python
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Web Environment
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 6.1
Classifier: Framework :: Plone :: 6.2
Classifier: Framework :: Plone :: Addon
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Python: >=3.10
Requires-Dist: plone-api
Requires-Dist: plone-memoize
Requires-Dist: plone-restapi
Requires-Dist: products-cmfplone
Requires-Dist: redis>=5
Requires-Dist: zope-ramcache
Provides-Extra: release
Requires-Dist: zest-pocompile; extra == 'release'
Requires-Dist: zest-releaser[recommended]; extra == 'release'
Requires-Dist: zestreleaser-towncrier; extra == 'release'
Provides-Extra: test
Requires-Dist: fakeredis; extra == 'test'
Requires-Dist: horse-with-no-namespace; extra == 'test'
Requires-Dist: plone-app-caching; extra == 'test'
Requires-Dist: plone-app-testing; extra == 'test'
Requires-Dist: plone-classicui; extra == 'test'
Requires-Dist: plone-restapi[test]; extra == 'test'
Requires-Dist: pytest; extra == 'test'
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest-docker; extra == 'test'
Requires-Dist: pytest-plone>=1.1.0; extra == 'test'
Requires-Dist: pyyaml; extra == 'test'
Description-Content-Type: text/markdown

<div align="center">
    <h1 align="center">collective.redismemoize</h1>
</div>
<div align="center">

[![PyPI](https://img.shields.io/pypi/v/collective.redismemoize)](https://pypi.org/project/collective.redismemoize/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/collective.redismemoize)](https://pypi.org/project/collective.redismemoize/)
[![PyPI - License](https://img.shields.io/pypi/l/collective.redismemoize)](https://pypi.org/project/collective.redismemoize/)
[![PyPI - Plone Versions](https://img.shields.io/pypi/frameworkversions/plone/collective.redismemoize)](https://pypi.org/project/collective.redismemoize/)
[![CI](https://github.com/collective/collective.redismemoize/actions/workflows/main.yml/badge.svg)](https://github.com/collective/collective.redismemoize/actions/workflows/main.yml)

</div>

Redis-backed storage for `plone.memoize`, shared across Plone instances, that keeps the values Redis can't safely store in each process's RAM cache.

Every Plone instance keeps its own `plone.memoize` RAM cache, so behind a load balancer each one computes the same cached values on its own, and a new instance starts cold.
`collective.redismemoize` stores those values in Redis or Valkey instead, where every instance reads them.
Values that are not plain data, such as content objects or anything holding a database connection, stay in the RAM cache, exactly where stock Plone keeps them.

📖 **Documentation:** https://collective.github.io/collective.redismemoize/

## Features

- ✅ Works for every `@ram.cache` function in Plone and in your add-ons, without changing them.
- 🔀 Routes each function on its own: plain data goes to Redis, anything else stays in RAM, and the reason is logged once.
- 🔒 Reads values back with a restricted unpickler that resolves only the classes plain data needs, so a write to Redis cannot run code in Plone.
- 🛟 Fails safe: when Redis is slow or down, a circuit breaker keeps every instance on its RAM cache until Redis answers again.
- 🎯 Include and exclude functions by pattern, and give your own functions their own TTL.
- 📊 A Manager-only `@redismemoize` REST API endpoint reports the status, routes and counters, and invalidates values after a deploy.
- 🧪 A test layer for add-ons, backed by `fakeredis`, to check that what your functions cache is shareable.
- 🔁 Tested against Redis 7 and Valkey 8.

Without configuration, the package changes nothing.

## Installation

Add `collective.redismemoize` to the dependencies of your Plone project, and install it.
With `plone.autoinclude`, the default in Plone 6, there is nothing else to load and no add-on to activate.

Then set one environment variable on every instance:

```shell
REDIS_MEMOIZE_URL=redis://redis:6379/0
```

Run Redis as a cache, on a private network: persistence off, a memory limit, and `allkeys-lru` eviction.
The [configuration guide](https://collective.github.io/collective.redismemoize/how-to-guides/configure.html) has a Docker Compose example, and the [configuration reference](https://collective.github.io/collective.redismemoize/reference/configuration.html) lists every variable.

## Compatibility

| Component | Versions |
| --- | --- |
| Plone | 6.1, 6.2 |
| Python | 3.10 to 3.14 |
| Redis | 4.0 and later; tested with 7.4 |
| Valkey | 7.2 and later; tested with 8 |

## Contribute

- [Issue tracker](https://github.com/collective/collective.redismemoize/issues)
- [Source code](https://github.com/collective/collective.redismemoize/)
- [Security policy](SECURITY.md)

You need [uv](https://docs.astral.sh/uv/), Make, Git, and Docker for the tests against real servers.

```shell
git clone git@github.com:collective/collective.redismemoize.git
cd collective.redismemoize
make install
make test
```

`make test` needs no container.
`make test-docker` runs the tests against Redis and Valkey containers.
`make help` lists every target.

## License

The project is licensed under GPLv2.

Redis is a registered trademark of Redis Ltd.
Any rights therein are reserved to Redis Ltd.
Any use by this project is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and this project.


---

# Changelog

<!--
   You should *NOT* be adding new change log entries to this file.
   You should create a file in the news directory instead.
   For helpful instructions, please see:
   https://github.com/plone/plone.releaser/blob/master/ADD-A-NEWS-ITEM.rst
-->

<!-- towncrier release notes start -->

## 1.0.0a1 (2026-10-19)


### Feature

- Initial implementation: `plone.memoize` RAM cache values are stored in Redis or Valkey and shared across Plone instances, while values that are not plain data stay in each process's RAM cache. Includes per-function routing, a circuit breaker, a restricted unpickler, environment-based configuration, a Manager-only `@redismemoize` REST API endpoint for status and invalidation, and a test layer for add-ons. @ericof
