Skip to content

Latest commit

 

History

History
254 lines (155 loc) · 6.02 KB

README.md

File metadata and controls

254 lines (155 loc) · 6.02 KB

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