/st_redis_connection

Connect to Redis and other compatible databases (KeyDB, DragonflyDB, LedisDB, SSDB, ARDB) from your Streamlit app.

Primary LanguagePythonMIT LicenseMIT

Streamlit RedisConnection

Connect to Redis and other compatible databases (KeyDB, DragonflyDB, LedisDB, SSDB, ARDB) from your Streamlit app.

Installation

pip install git+https://github.com/mobarski/st_redis_connection

Quick demonstration

import streamlit as st
from st_redis_connection import RedisConnection

redis = st.experimental_connection("my_redis", type=RedisConnection)
db = redis.client()
cnt = db.incr('my-counter')
st.metric('Views', cnt)

Main methods

client()

connection.client() -> redis.Redis | redis.Sentinel | redis.RedisCluster

Get Redis client object that will be used to issue commands to the server.

More info about it's methods here.

lock()

connection.lock(name, timeout=None, sleep=0.1, blocking=True, blocking_timeout=None, thread_local=True) -> redis.lock.Lock

A shared, distributed Lock using Redis.

More info here.

Configuration

The connection configuration can be:

  • passed via connection kwargs
  • passed through environmental variables
  • stored in Streamlit's secrets.toml file (~/.streamlit/secrets.toml on Linux)

You can find more information about managing connections in this section of Streamlit documentation and some examples below.

Most important parameters:

  • host - server host (default: 'localhost')
  • port - server port (default: 6379)
  • username - user name (default: default)
  • password - user password
  • db - numeric id of the database (default: 0)
  • from_url - configuration passed via URL. More info here
  • mode - Redis client type used in the connection:
    • redis (default) - redis.Redis
    • sentinel - redis.Sentinel
    • cluster - redis.RedisCluster

You can read more about connecting to Redis here.

Usage examples

simple_app.py
import streamlit as st
from st_redis_connection import RedisConnection

redis = st.experimental_connection("my_redis", type=RedisConnection)
db = redis.client()

cnt = db.incr('my-counter')
st.metric('Views', cnt)
lua_scripting_app.py
import streamlit as st
from st_redis_connection import RedisConnection
from random import randint

redis = st.experimental_connection("redis_dev", type=RedisConnection)
db = redis.client()

# Lua Scripting example - atomic CTR calculation
# REF: https://redis.readthedocs.io/en/latest/lua_scripting.html
recalc_ctr = db.register_script("""
local clicks = redis.call('INCRBY', KEYS[1], ARGV[1])
local views  = redis.call('INCRBY', KEYS[2], ARGV[2])
local ctr = 1000 * clicks / views
redis.call('SET', KEYS[3], ctr)
return ctr
""")

new_clicks = randint(0,5)
new_views  = 5
ctr = recalc_ctr(keys=['x:clicks','x:views','x:ctr'], args=[new_clicks, new_views])

st.metric('CTR', ctr/1000)
pipeline_app.py
import streamlit as st
from st_redis_connection import RedisConnection
from random import randint

redis = st.experimental_connection("redis_dev", type=RedisConnection)
db = redis.client()

new_clicks = randint(0,5)
new_views  = 5

pipe = db.pipeline()
pipe.incrby('x:clicks', new_clicks)
pipe.incrby('x:views',  new_views)
clicks,views = pipe.execute()

ctr = clicks / views
st.metric('CTR', ctr)
demo_app.py

You can find live demo of this app here

# NOTE: for simplicity, this is far from being a good example of *how* to use Redis.

import streamlit as st
from st_redis_connection import RedisConnection

N_CLICKS = 100 # number of clicks to enable the reset button

redis = st.experimental_connection("redis", type=RedisConnection)
db = redis.client()

clicks1 = int(db.get('clicks1') or 0)
clicks2 = int(db.get('clicks2') or 0)
views   = int(db.get('views')   or 1)

st.markdown('# Redis connection demo')
c1,c2,c3 = st.columns(3)

b1 = c1.button('Click me.')
b2 = c2.button('No! Click me!')
b3 = c3.button('Reset stats',
               disabled = clicks1 + clicks2 < N_CLICKS,
               help = f'Reset all stats to zero. Enbled after {N_CLICKS} clicks.')

if b1: db.incr('clicks1')
if b2: db.incr('clicks2')
if b3:
    db.set('clicks1', 0)
    db.set('clicks2', 0)
    db.set('views',   1)

if b1 or b2 or b3:
    st.experimental_rerun()
else:
    db.incr('views')

c1.metric('button 1 clicks', clicks1)
c2.metric('button 2 clicks', clicks2)
c3.metric('total views', views)

Configuration examples

connection kwargs
REDIS_URL = "rediss://default:this-is-my-password@my-redis-host:25061"
redis = st.experimental_connection('', type=RedisConnection, from_url=REDIS_URL)
redis = st.experimental_connection('', type=RedisConnection, host='my-host', port=1234, password='my-password', db=2)
secrets.toml
[connections.my_redis]
from_url = "rediss://default:this-is-my-password@my-redis-host:25061/1"

[connections.redis2_db3]
host = "my-redis-host2"
port = 6379
password = "password-for-this-instance"
db = 3

[connections.redis3_sen]
mode = "sentinel"
sentinels = [["localhost", 26379]]
password = "another-password"

[connections.redis_cluster]
mode = "cluster"
environmental variables
my_redis_from_url = "rediss://default:this-is-my-password@my-redis-host:25061/1"

redis2_db3_host = "my-redis-host2"
redis2_db3_port = 25061
redis2_db3_password = "password-for-this-instance"
redis2_db3_db = 3

# NOTE: currently Redis sentinels cannot be configured via env. variables
# NOTE: currently Redis clusters  cannot be configured via env. variables