Skip to content

Add examples #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions examples/chat_history.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from typing import List, Set

from upstash_redis import Redis

# An example chat history model for storing
# messages of different users with the chatbot

# A user can have multiple chats
# A chat can have multiple messages

# user:123:chats -> set of chat ids

# chat:123 -> list of messages

# chat:next_id -> 1 (incrementing id for chats)


class ChatModel:
def __init__(self, redis: Redis):
self.redis = redis

def get_user_chats(self, user_id: str) -> Set[str]:
# A set of chat ids for a user, stores which chats belong to the user
return self.redis.smembers(f"user:{user_id}:chats")

def get_chat_messages(self, chat_id: str) -> List[str]:
return self.redis.lrange(f"chat:{chat_id}", 0, -1)

def add_message(self, chat_id: str, message: str):
# Push the message to the end of the list
self.redis.rpush(f"chat:{chat_id}", message)

def create_chat(self, user_id: str) -> str:
# A unique incrementing id for the chat
# Since increment is atomic and returns the new value
chat_id = str(self.redis.incr("chat:next_id"))

# Add the chat to the user's chat list
self.redis.sadd(f"user:{user_id}:chats", chat_id)

return chat_id

def delete_chat(self, chat_id: str, user_id: str):
# Remove the chat from the user's chat list
self.redis.srem(f"user:{user_id}:chats", str(chat_id))

# Delete the chat
self.redis.delete(f"chat:{chat_id}")

def delete_user(self, user_id: str):
# Delete all chats of the user
for chat_id in self.get_user_chats(user_id):
self.delete_chat(chat_id, user_id)

# Delete the user's chat list
self.redis.delete(f"user:{user_id}:chats")


redis = Redis.from_env()
chat = ChatModel(redis)

chat.redis.flushall()

# You can acquire the userid from an authentication service
# or from the session cookie
userid = "myid"

chatid_1 = chat.create_chat(userid)

chat.add_message(chatid_1, "user:Hello")

chat.add_message(chatid_1, "bot:Hello")

chat.add_message(chatid_1, "user:How are you?")

chatid_2 = chat.create_chat(userid)

chat.add_message(chatid_2, "user:This is chat2")

chat_ids = chat.get_user_chats(userid)

# Print all the data
print("chatid_1:", chatid_1)
print("chatid_2:", chatid_2)
print("chat_ids:", chat_ids)

print("chat 1 messages:", chat.get_chat_messages(chatid_1))
print("chat 2 messages:", chat.get_chat_messages(chatid_2))

# Delete the first chat
chat.delete_user(userid)

print("chatids after deletion:", chat.get_user_chats(userid))

# Output
# chatid_1: 1
# chatid_2: 2
# chat_ids: {'2', '1'}
# chat 1 messages: ['user:Hello', 'bot:Hello', 'user:How are you?']
# chat 2 messages: ['user:This is chat2']
# chatids after deletion: set()
91 changes: 91 additions & 0 deletions examples/scan_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from threading import Thread
from typing import List, Optional, Tuple

from upstash_redis import Redis

# A simple task queue for scanning websites

# Multiple workers can run the same code and
# pop tasks from the queue

# Scan the website and store the results in list

# scan:waiting -> list of tasks with

# scan:running -> a set of running tasks,
# since a task must be popped from the waiting list by its id,
# we use a set

# scan:completed:123 -> a list of completed tasks for the client
class TaskQueue:
def __init__(self, redis: Redis):
self.redis = redis

def add_scan_task(self, clientid: str, website: str):
# Add the task to the waiting list
self.redis.rpush("scan:waiting", f"{clientid}:{website}")

def consume_completed_tasks(self, clientid: str) -> List[str]:
# Consume all completed tasks for the client
# and return them

# Redis doesn't have a popall command but you can atomically
# pop all elements from a list by specifying a large count

# Ignore type since if count is specified, this method returns a list
return self.redis.rpop(f"scan:completed:{clientid}", 99999) # type: ignore

def start_scan(self) -> Optional[Tuple[str, str]]:
# Pop task from the waiting list and add it to the running list
task: str | None = self.redis.rpop("scan:waiting") # type: ignore

if task is None:
# No task to run
return None

self.redis.sadd("scan:running", task)

[client, website] = task.split(":", 1)

return (client, website)

def complete_scan(self, clientid: str, website: str, result: str):
# Add the result to the client's completed list
self.redis.rpush(f"scan:completed:{clientid}", result)

# Remove the task from the running list
self.redis.srem("scan:running", f"{clientid}:{website}")


redis = Redis.from_env()
queue = TaskQueue(redis)

queue.add_scan_task("client1", "https://example.com")

queue.add_scan_task("client1", "https://google.com")

# This code will be run by multiple workers
def work():
task = queue.start_scan()

if task is None:
return

[client, website] = task

# scan the website and store the result in a list
queue.complete_scan(client, website, f"results for {website}")


t1 = Thread(target=work)
t2 = Thread(target=work)

t1.start()
t2.start()

t1.join()
t2.join()

completed = queue.consume_completed_tasks("client1")

print("completed: ", completed)
39 changes: 39 additions & 0 deletions examples/simple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from upstash_redis import Redis

# Reads from the environment variables
# UPSTASH_REDIS_REST_URL
# UPSTASH_REDIS_REST_TOKEN
redis = Redis.from_env()

# Set or get a key
redis.set("key", "value")

# 10 is converted to "10", it's still a string
redis.set("key", 10)

# The dictionary is converted to json, it's still a string
redis.set(
"key",
{
"name": "John",
"age": 30,
},
)

# Expires in 10 seconds
redis.set("expire_key", value="expire_value", ex=10)

# Gets the time to live in seconds
redis.ttl("expire_key")

# Change ttl
redis.expire("expire_key", 20)

# Remove ttl
redis.persist("expire_key")

# Set a key only if it does not exist
redis.set("key", "value", nx=True)

# Set a key only if it exists
redis.set("key", "value", xx=True)
46 changes: 46 additions & 0 deletions examples/simple_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import asyncio

from upstash_redis.asyncio import Redis


async def main():
# Reads from the environment variables
# UPSTASH_REDIS_REST_URL
# UPSTASH_REDIS_REST_TOKEN
redis = Redis.from_env()

# Set or get a key
await redis.set("key", "value")

# 10 is converted to "10", it's still a string
await redis.set("key", 10)

# The dictionary is converted to json, it's still a string
await redis.set(
"key",
{
"name": "John",
"age": 30,
},
)

# Expires in 10 seconds
await redis.set("expire_key", value="expire_value", ex=10)

# Gets the time to live in seconds
await redis.ttl("expire_key")

# Change ttl
await redis.expire("expire_key", 20)

# Remove ttl
await redis.persist("expire_key")

# Set a key only if it does not exist
await redis.set("key", "value", nx=True)

# Set a key only if it exists
await redis.set("key", "value", xx=True)


asyncio.run(main())
Loading