Model Lifecycle¶
Rapyer provides TTL (Time To Live) management for your models, allowing automatic expiration and lifecycle control of your Redis-stored data.
TTL (Time To Live)¶
Set automatic expiration for your models:
class Session(AtomicRedisModel):
user_id: str
data: dict = {}
# Sessions expire after 30 minutes
Session.Meta.redis = redis_client
Session.Meta.ttl = 1800 # 30 minutes in seconds
When a TTL is set, the model will automatically be deleted from Redis after the specified time period.
TTL Refresh¶
By default, Rapyer refreshes a model's TTL whenever it is accessed or modified. This keeps models alive while they are in active use.
How It Works¶
When refresh_ttl is enabled (the default), the following operations reset the TTL timer:
- Reading a model with
afindoraget - Saving changes with
asave - Any atomic field operation (e.g.,
aappend,aupdate,aincrease)
A model with a 1-hour TTL will only expire if it remains untouched for a full hour.
Configuration¶
refresh_ttl accepts three forms:
| Value | Behavior |
|---|---|
True (default) |
Refresh TTL on every read/write operation |
False |
Never refresh TTL |
ActionGroup flag |
Refresh only on the specified categories of operations |
Global Configuration¶
from rapyer import init_rapyer
# Refresh on every operation (default)
await init_rapyer(redis="redis://localhost:6379/0", ttl=3600, refresh_ttl=True)
# Never refresh
await init_rapyer(redis="redis://localhost:6379/0", ttl=3600, refresh_ttl=False)
Per-Model Configuration¶
class Session(AtomicRedisModel):
user_id: str
data: dict = {}
Session.Meta.ttl = 1800
Session.Meta.refresh_ttl = False # Disable for this model only
Fine-Grained Strategies with ActionGroup¶
Pass an ActionGroup flag to refresh TTL only on specific categories of operations. Flags can be combined with |.
from rapyer.actions import ActionGroup
# Refresh only on writes — reads do not extend lifetime
Session.Meta.refresh_ttl = ActionGroup.UPDATE | ActionGroup.APPEND | ActionGroup.CREATE
# Refresh only when the model is fetched or read
Cache.Meta.refresh_ttl = ActionGroup.READ | ActionGroup.FETCH
# Refresh on every category except DELETE (equivalent to True)
Session.Meta.refresh_ttl = ActionGroup.all(for_ttl=True)
Available groups:
| Group | Triggers |
|---|---|
READ |
Reading a value (field-level reads, contains-checks) |
FETCH |
Loading a full model (aget, afind, afind_one) |
CREATE |
Creating a model (asave, ainsert) |
UPDATE |
Modifying existing data |
APPEND |
Adding items to a collection |
ERASE |
Removing items from a collection (apop, aclear, aremove) |
ARITHMETIC |
In-place numeric operations (aincrease) |
DELETE |
Removing the entire key — cannot be used with refresh_ttl |
DELETE is not refreshable
refresh_ttl cannot include ActionGroup.DELETE. The key is removed from Redis on delete, so refreshing its TTL is meaningless. Passing it raises InvalidRefreshTtlError.
See the ActionGroup API reference for the full list of methods that map to each group.
Initial TTL is Always Set¶
Even with refresh_ttl=False, the TTL is established the first time a model is created (asave, ainsert). Disabling refresh only prevents subsequent operations from resetting the timer — it does not prevent the initial expiration from being applied.
Use Cases¶
Active Session Management¶
Keep user sessions alive while they are actively using the application:
class UserSession(AtomicRedisModel):
user_id: str
last_page: str
cart_items: list = []
UserSession.Meta.ttl = 1800 # 30 minutes
UserSession.Meta.refresh_ttl = True
# Session TTL resets every time user navigates
session = await UserSession.afind(session_id)
session.last_page = "/checkout"
await session.asave() # TTL reset to 30 minutes
Fixed Expiration¶
For models that should expire at a fixed time regardless of access:
class PasswordResetToken(AtomicRedisModel):
user_id: str
token: str
PasswordResetToken.Meta.ttl = 3600 # 1 hour
PasswordResetToken.Meta.refresh_ttl = False # Token expires in exactly 1 hour
Setting TTL Dynamically¶
Use aset_ttl() to set or update the TTL of a specific model instance at runtime:
This is useful when you need different expiration times for individual instances, or when the TTL should be determined by business logic rather than a fixed configuration.
Note
aset_ttl() can only be called on top-level models, not on nested models.
Best Practices¶
- Enable for sessions: User sessions, shopping carts, and other user-activity-related models benefit from TTL refresh
- Disable for time-sensitive tokens: Password reset tokens, verification codes, and similar security-related models should have fixed expiration
- Consider your use case: If a model should "live" as long as it's being used, enable TTL refresh. If it should expire at a specific time, disable it
- Use
aset_ttl()for dynamic expiration: When different instances need different TTLs based on runtime conditions