REST API#
The package adds one endpoint, @redismemoize, on the Plone site root.
It requires the Manage portal permission, which only the Manager role has in a stock Plone 6.2 site.
Site Administrators get 401 Unauthorized.
Every instance answers for itself. The breaker, the routes and the counters belong to the process that handled the request.
The examples below are recorded by the test suite.
Get the status#
GET /@redismemoize returns the configuration, the state of the breaker, the server, and every cached function the process has seen.
http
GET /plone/@redismemoize HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
curl
curl -i -X GET http://nohost/plone/@redismemoize -H "Accept: application/json" --user admin:secret
httpie
http http://nohost/plone/@redismemoize Accept:application/json -a admin:secret
python-requests
requests.get('http://nohost/plone/@redismemoize', headers={'Accept': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"active": true,
"breaker": {
"open": false,
"seconds_until_retry": 0.0
},
"functions": {
"plone.app.theming.plugins.utils.getPluginSettings": {
"counters": {
"errors": 0,
"ram_hits": 2,
"ram_misses": 0,
"redis_hits": 0,
"redis_misses": 2,
"refused": 0,
"too_large": 0,
"undecodable": 0
},
"reason": null,
"route": "redis"
},
"plone.app.theming.plugins.utils.getPlugins": {
"counters": {
"errors": 0,
"ram_hits": 2,
"ram_misses": 0,
"redis_hits": 0,
"redis_misses": 2,
"refused": 0,
"too_large": 0,
"undecodable": 0
},
"reason": null,
"route": "redis"
},
"tests.integration.compute": {
"counters": {
"errors": 0,
"ram_hits": 0,
"ram_misses": 1,
"redis_hits": 1,
"redis_misses": 1,
"refused": 0,
"too_large": 0,
"undecodable": 0
},
"reason": null,
"route": "redis"
}
},
"server": {
"error": null,
"latency_ms": 0.25,
"product": "redis",
"version": null
},
"settings": {
"exclude": [],
"include": [],
"max_size": 1048576,
"prefix": "test.memoize",
"retry_after": 30.0,
"timeout": 0.25,
"ttl": 86400,
"url": "redis://fakeredis:6379/0"
}
}
The response has these keys:
activetruewhenREDIS_MEMOIZE_URLis set.settingsThe configuration in effect, with any password in the URL replaced by
***.breakeropen, andseconds_until_retry;nullwhen the package is inert.serverlatency_msof aPING,product(redisorvalkey),version, anderror;nullwhen the package is inert. The endpoint contacts the server even while the breaker is open.functionsFor each function, its
route, thereasonfor a RAM route, and itscounters.
The routes are:
redisValues go to Redis.
ram-excludedAn include or exclude pattern keeps the function in RAM.
ram-not-shareableA value was not shareable; the function stays in RAM until the process restarts.
The counters are redis_hits, redis_misses, ram_hits, ram_misses, refused, too_large, undecodable, and errors.
Without REDIS_MEMOIZE_URL, the response says so:
HTTP/1.1 200 OK
Content-Type: application/json
{
"active": false,
"breaker": null,
"functions": {},
"server": null,
"settings": {
"exclude": [],
"include": [],
"max_size": 1048576,
"prefix": "plone.memoize",
"retry_after": 30.0,
"timeout": 0.25,
"ttl": 86400,
"url": null
}
}
Invalidate one function#
POST /@redismemoize/invalidate with a body naming a function drops that function's values from Redis, and from the RAM cache of the instance that answers.
http
POST /plone/@redismemoize/invalidate HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{
"function": "tests.integration.compute"
}
curl
curl -i -X POST http://nohost/plone/@redismemoize/invalidate -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"function": "tests.integration.compute"}' --user admin:secret
httpie
echo '{
"function": "tests.integration.compute"
}' | http POST http://nohost/plone/@redismemoize/invalidate Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/@redismemoize/invalidate', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, json={'function': 'tests.integration.compute'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"function": "tests.integration.compute",
"removed": 1
}
removed is the number of Redis keys removed.
Invalidate everything#
POST /@redismemoize/invalidate with an empty object as the body drops every key under the prefix, and the whole RAM cache of the instance that answers.
http
POST /plone/@redismemoize/invalidate HTTP/1.1
Accept: application/json
Authorization: Basic YWRtaW46c2VjcmV0
Content-Type: application/json
{}
curl
curl -i -X POST http://nohost/plone/@redismemoize/invalidate -H "Accept: application/json" -H "Content-Type: application/json" --user admin:secret
httpie
http POST http://nohost/plone/@redismemoize/invalidate Accept:application/json Content-Type:application/json -a admin:secret
python-requests
requests.post('http://nohost/plone/@redismemoize/invalidate', headers={'Accept': 'application/json', 'Content-Type': 'application/json'}, auth=('admin', 'secret'))
HTTP/1.1 200 OK
Content-Type: application/json
{
"function": null,
"removed": 3
}
Errors#
400 Bad RequestThe body is not a JSON object, or
functionis not a non-empty string.401 UnauthorizedThe user lacks
Manage portal.404 Not FoundA
POSTto any path other than@redismemoize/invalidate.