Auto-Synced Collections
redis-memory automatically wraps lists and dictionaries to keep them synchronized with Redis. Any modifications to these collections are immediately persisted.
Auto-Synced Lists
Basic Operations
from redis_memory import Memory
mem = Memory()
mem.tasks = [1, 2, 3]
# All list operations sync automatically
mem.tasks.append(4) # [1, 2, 3, 4]
mem.tasks.extend([5, 6]) # [1, 2, 3, 4, 5, 6]
mem.tasks.insert(0, 0) # [0, 1, 2, 3, 4, 5, 6]
# Check in another process
mem2 = Memory()
print(mem2.tasks) # [0, 1, 2, 3, 4, 5, 6]
Supported Operations
The following list operations automatically sync:
append(item): Add item to endextend(iterable): Add multiple itemsinsert(index, item): Insert at positionremove(item): Remove first occurrencepop([index]): Remove and return itemclear(): Remove all itemssort(): Sort in placereverse(): Reverse in place
Item Assignment
mem.items = [1, 2, 3]
mem.items[0] = 10 # [10, 2, 3] - syncs automatically
mem.items[1:3] = [20, 30] # [10, 20, 30] - syncs automatically
Auto-Synced Dictionaries
Basic Operations
mem = Memory()
mem.config = {"theme": "dark", "lang": "en"}
# All dict operations sync automatically
mem.config["notifications"] = True
mem.config.update({"font": "Arial", "size": 12})
# Check in another process
mem2 = Memory()
print(mem2.config)
# {'theme': 'dark', 'lang': 'en', 'notifications': True, 'font': 'Arial', 'size': 12}
Supported Operations
The following dict operations automatically sync:
__setitem__(key, value): Set a key__delitem__(key): Delete a keypop(key): Remove and return valuepopitem(): Remove and return (key, value) pairclear(): Remove all itemsupdate(other): Update with another dictsetdefault(key, default): Set if not exists
Nested Access
mem.data = {"user": {"name": "Alice", "age": 30}}
# Direct modification syncs the entire structure
mem.data["user"]["age"] = 31
print(mem.data) # {'user': {'name': 'Alice', 'age': 31}}
Nested Collections
redis-memory handles deeply nested structures:
mem = Memory()
mem.complex = {
"users": [
{"name": "Alice", "scores": [95, 87, 92]},
{"name": "Bob", "scores": [88, 91, 85]}
],
"settings": {
"theme": "dark",
"notifications": {
"email": True,
"push": False
}
}
}
# Modifications at any level sync automatically
mem.complex["users"][0]["scores"].append(96)
mem.complex["settings"]["notifications"]["push"] = True
# Check in another process
mem2 = Memory()
print(mem2.complex["users"][0]["scores"]) # [95, 87, 92, 96]
print(mem2.complex["settings"]["notifications"]["push"]) # True
Converting to Plain Python Types
Sometimes you need regular Python lists/dicts (for pickling, JSON serialization, etc.):
Converting Lists
mem = Memory()
mem.items = [1, 2, 3]
# Convert to plain list
plain_list = mem.items.aslist()
print(type(plain_list)) # <class 'list'>
# Now you can use with any library
import pickle
pickle.dump(plain_list, open('data.pkl', 'wb'))
Converting Dictionaries
mem = Memory()
mem.config = {"key": "value", "nested": {"a": 1}}
# Convert to plain dict
plain_dict = mem.config.asdict()
print(type(plain_dict)) # <class 'dict'>
# Works with nested structures too
print(type(plain_dict["nested"])) # <class 'dict'>
Recursive Conversion
Both aslist() and asdict() recursively convert nested structures:
mem.data = {
"items": [1, 2, {"nested": [3, 4]}],
"config": {"x": [5, 6]}
}
plain = mem.data.asdict()
# All nested SyncedList and SyncedDict objects are converted
# to plain list and dict objects
Performance Considerations
Sync Frequency
Every modification triggers a sync to Redis. For bulk operations, consider:
# Less efficient (multiple syncs)
for i in range(1000):
mem.items.append(i) # 1000 Redis writes
# More efficient (one sync)
new_items = list(range(1000))
mem.items = mem.items.aslist() + new_items # 1 Redis write
Large Collections
For very large collections, consider:
- Pagination: Split large lists into smaller chunks
- Compression: Use Redis compression if available
- Alternative structures: Use Redis native data structures for specific use cases
Type Checking
You can check if an object is synced:
from redis_memory import SyncedList, SyncedDict
mem = Memory()
mem.items = [1, 2, 3]
mem.config = {"key": "value"}
isinstance(mem.items, SyncedList) # True
isinstance(mem.config, SyncedDict) # True
# Plain types after conversion
plain_list = mem.items.aslist()
isinstance(plain_list, SyncedList) # False
isinstance(plain_list, list) # True
Limitations
Copy vs Reference
When you extract a nested collection, modifications to the extracted reference may not sync:
Best Practice
Always modify collections through the memory object's attribute chain to ensure syncing works correctly.