Services

Redis

Redis as a cache and counter store: get, set with a lifetime, delete and count, over one connection kept open.

Version 1.0.0 · 4 functions · 1 crate

#cache#counters#redis#stores

Functions

What use redis.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use cache_get, cache_set from redis (Quillo 0.6).

cache_get(key: str) → str?or an error

The text at key, or null.

cache_set(key: str, value: str, ttl: int) → nullor an error

Keeps value at key for ttl seconds (0: for good).

cache_del(key: str) → boolor an error

Takes key away; whether it was there.

cache_incr(key: str) → intor an error

Adds one to the number at key (0 when there is none) and gives the new number: page views, rate limits.

Get it

$ quillo install redis               # redis.qwer into this folder$ quillo install redis --example     # and its example, redis.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/redis.qwer$ curl -O https://quillolang.org/plugins/files/redis.qwe

Then, in your program, all of it or only what you call:

main.qwe
use redis.qweruse cache_get, cache_set from redis      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
redis = "0.27"

Example

redis.qwe
// A page view counter and a cached answer, in Redis.////   REDIS_URL=redis://127.0.0.1/ quillo run redis.qwe      then open http://localhost:8080/viewsuse "redis.qwer"route GET /views = { views: cache_incr("views:home")? }// An answer kept for a minute, so a slow lookup runs once a minute at most.fn slow_report() = json.stringify({ total: 4521, at: now() })route GET /report {    let kept = cache_get("report")?    if kept != null { return json.parse(kept)? }    let fresh = slow_report()    cache_set("report", fresh, 60)?    json.parse(fresh)?}
$ quillo run redis.qwe$ curl 'localhost:8080/views'$ curl 'localhost:8080/report'

It talks to the Redis that REDIS_URL names, else Redis on this machine. The site's test runs it against a stand-in.

Source

redis.qwer
//! Redis as a cache and counter store: get, set with a lifetime, delete, count, and one connection kept open.//! version: 1.0.0//!//! [dependencies]//! redis = "0.27"use std::sync::Mutex;/// The connection, opened on the first call (`REDIS_URL`, else Redis on this machine) and opened again after an error.static CON: Mutex<Option<redis::Connection>> = Mutex::new(None);fn with<T>(f: impl Fn(&mut redis::Connection) -> redis::RedisResult<T>) -> Result<T, String> {    let mut slot = CON.lock().unwrap_or_else(|e| e.into_inner());    if slot.is_none() {        let url = std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1/".into());        let client = redis::Client::open(url).map_err(|e| e.to_string())?;        *slot = Some(client.get_connection_with_timeout(std::time::Duration::from_secs(2)).map_err(|e| e.to_string())?);    }    let r = f(slot.as_mut().unwrap());    if r.is_err() {        *slot = None;    }    r.map_err(|e| e.to_string())}/// The text at `key`, or null.pub fn cache_get(key: &str) -> Result<Option<String>, String> {    with(|c| redis::cmd("GET").arg(key).query(c))}/// Keeps `value` at `key` for `ttl` seconds (0: for good).pub fn cache_set(key: &str, value: &str, ttl: i64) -> Result<(), String> {    with(|c| {        let mut cmd = redis::cmd("SET");        cmd.arg(key).arg(value);        if ttl > 0 { cmd.arg("EX").arg(ttl); }        cmd.query(c)    })}/// Takes `key` away; whether it was there.pub fn cache_del(key: &str) -> Result<bool, String> {    with(|c| redis::cmd("DEL").arg(key).query::<i64>(c)).map(|n| n > 0)}/// Adds one to the number at `key` (0 when there is none) and gives the new number: page views, rate limits.pub fn cache_incr(key: &str) -> Result<i64, String> {    with(|c| redis::cmd("INCR").arg(key).query(c))}
Thread
77Useful? Like it, or add to its thread below.

Thread 0 posts

On Redis: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.