scriptling.kv
Thread-safe key-value store for sharing state across HTTP requests.
Available Functions
| Function | Description |
|---|---|
set(key, value, ttl=0) |
Store a value with optional TTL |
get(key, default=None) |
Retrieve a value by key |
delete(key) |
Remove a key from the store |
incr(key, delta=1) |
Atomically increment a value |
keys(pattern="*") |
Get all keys matching pattern |
exists(key) |
Check if key exists |
ttl(key) |
Get remaining TTL for a key |
Overview
The scriptling.kv library provides an in-memory key-value store that persists across HTTP requests. It’s perfect for:
- Session management
- Rate limiting counters
- Caching API responses
- Storing user state
- Sharing data between request handlers
Key features:
- Thread-safe operations
- Optional TTL (time-to-live) for keys
- Deep copy on read (modifying returned values doesn’t affect stored data)
- Atomic increment operations
- Glob pattern matching for keys
Important: The KV store is an in-memory data structure with no size limits. Keys without a TTL persist indefinitely until explicitly deleted or clear() is called. In long-running processes, ensure you manage key lifetimes appropriately to avoid unbounded memory growth. Use TTLs where possible and periodically review stored keys with keys(). Expired entries are cleaned up automatically every 60 seconds.
Functions
scriptling.kv.set(key, value, ttl=0)
Store a value with optional TTL in seconds.
Parameters:
key(str): The key to store the value undervalue: The value to store (string, int, float, bool, list, dict)ttl(int, optional): Time-to-live in seconds. 0 means no expiration.
Returns: None
Example:
import scriptling.kv
# Store a simple value
scriptling.kv.set("api_key", "secret123")
# Store with TTL (1 hour)
scriptling.kv.set("session:abc", {"user": "bob", "login_time": 123456}, ttl=3600)
# Store a list
scriptling.kv.set("recent_items", ["item1", "item2", "item3"])
# Store a dict
scriptling.kv.set("config", {"debug": True, "port": 8080})scriptling.kv.get(key, default=None)
Retrieve a value by key.
Parameters:
key(str): The key to retrievedefault: Value to return if key doesn’t exist (default: None)
Returns: The stored value (deep copy), or the default if not found
Example:
import scriptling.kv
# Get a value
value = scriptling.kv.get("api_key")
# Get with default
count = scriptling.kv.get("counter", default=0)
# Expired keys return default
session = scriptling.kv.get("session:old", default={})scriptling.kv.delete(key)
Remove a key from the store.
Parameters:
key(str): The key to delete
Returns: None
Example:
import scriptling.kv
scriptling.kv.delete("session:abc")
scriptling.kv.delete("temp_data")scriptling.kv.exists(key)
Check if a key exists and is not expired.
Parameters:
key(str): The key to check
Returns: bool - True if key exists and is not expired
Example:
import scriptling.kv
if scriptling.kv.exists("config"):
config = scriptling.kv.get("config")
else:
config = load_default_config()scriptling.kv.incr(key, amount=1)
Atomically increment an integer value.
Parameters:
key(str): The key to incrementamount(int, optional): Amount to increment by (default: 1)
Returns: int - The new value after incrementing
Example:
import scriptling.kv
# Initialize counter
scriptling.kv.set("page_views", 0)
# Increment (returns 1)
views = scriptling.kv.incr("page_views")
# Increment by more (returns 6)
views = scriptling.kv.incr("page_views", 5)
# Non-existent keys are auto-initialized
scriptling.kv.incr("new_counter") # returns 1scriptling.kv.ttl(key)
Get remaining time-to-live for a key.
Parameters:
key(str): The key to check
Returns: int - Remaining TTL in seconds, -1 if no expiration, -2 if key doesn’t exist
Example:
import scriptling.kv
scriptling.kv.set("session", "data", ttl=3600)
remaining = scriptling.kv.ttl("session") # e.g., 3599
no_expiry = scriptling.kv.ttl("config") # -1 (no TTL)
missing = scriptling.kv.ttl("unknown") # -2 (doesn't exist)scriptling.kv.keys(pattern="*")
Get all keys matching a glob pattern.
Parameters:
pattern(str, optional): Glob pattern to match keys (default: “*”)
Returns: list - List of matching keys
Example:
import scriptling.kv
# Get all keys
all_keys = scriptling.kv.keys()
# Get keys matching pattern
user_keys = scriptling.kv.keys("user:*")
session_keys = scriptling.kv.keys("session:*")
cache_keys = scriptling.kv.keys("cache:*:data")scriptling.kv.clear()
Remove all keys from the store.
Warning: This operation cannot be undone.
Returns: None
Example:
import scriptling.kv
# Clear all data (use with caution!)
scriptling.kv.clear()Usage Examples
Rate Limiting
import scriptling.http
import scriptling.kv
def check_rate_limit(request):
ip = request.headers.get("x-forwarded-for", "unknown")
key = f"rate:{ip}"
count = scriptling.kv.incr(key)
# Set expiry on first request
if count == 1:
scriptling.kv.set(key, 1, ttl=60) # 1 minute window
if count > 100:
return scriptling.http.json(429, {"error": "Rate limit exceeded"})
return None # Allow requestSession Management
import scriptling.http
import scriptling.kv
import secrets
def create_session(user_id):
token = secrets.token_hex(32)
scriptling.kv.set(f"session:{token}", {
"user_id": user_id,
"created": time.time()
}, ttl=86400) # 24 hours
return token
def get_session(token):
return scriptling.kv.get(f"session:{token}")
def delete_session(token):
scriptling.kv.delete(f"session:{token}")Caching API Responses
import scriptling.http
import scriptling.kv
import requests
import json
def get_cached_api_data(endpoint, ttl=300):
cache_key = f"api:{endpoint}"
# Try cache first
cached = scriptling.kv.get(cache_key)
if cached:
return cached
# Fetch from API
response = requests.get(f"https://api.example.com/{endpoint}")
data = response.json()
# Cache for future requests
scriptling.kv.set(cache_key, data, ttl=ttl)
return dataSee Also
- scriptling.http - HTTP server route registration
- requests - HTTP client library