1- """Memory factory for creating memory instances based on configuration."""
1+ # Factory for creating memory implementations
22
3- from typing import Any , Dict , Optional
3+ from __future__ import annotations
4+
5+ import os
6+ from typing import Any , Dict , List , Optional
47
58from .file_store import FileMemory
9+ from .hybrid_store import HybridMemory
610from .inmem_store import InnerMemory
711from .memory import Memory
12+ from .rds_store import RDSMemory
13+ from .redis_store import RedisMemory
814
915
1016class MemoryFactory :
11- """Factory for creating memory instances based on configuration."""
17+ """Factory for creating memory implementations.
18+
19+ This class provides a convenient way to create different memory implementations
20+ based on configuration parameters. It also helps with type mapping and default
21+ configurations.
22+
23+ Available types:
24+ - "inner", "memory", "inmem": In-memory implementation for fast access and testing
25+ - "file": File-based implementation for persistence without external dependencies
26+ - "redis": Redis-based implementation for distributed caching
27+ - "rds": Relational database implementation for persistent storage
28+ - "hybrid": Hybrid implementation combining Redis for cache and RDS for persistence
29+ """
1230
13- # Registry of available memory types
1431 _memory_types = {
1532 "inner" : InnerMemory ,
1633 "memory" : InnerMemory , # alias for backward compatibility
1734 "inmem" : InnerMemory , # alias for backward compatibility
1835 "file" : FileMemory ,
36+ "redis" : RedisMemory ,
37+ "rds" : RDSMemory ,
38+ "hybrid" : HybridMemory ,
1939 }
2040
2141 @classmethod
2242 def create_memory (cls , memory_type : str = "inner" , ** kwargs ) -> Memory :
23- """Create a memory instance based on type and configuration .
43+ """Create a memory instance based on type.
2444
2545 Args:
26- memory_type: Type of memory to create ("inner", "file")
27- **kwargs: Additional configuration parameters for the memory instance
46+ memory_type: Type of memory to create
47+ **kwargs: Additional configuration parameters depending on type
2848
2949 Returns:
3050 Memory instance
31-
32- Raises:
33- ValueError: If memory_type is not supported
34-
35- Examples:
36- >>> # Create in-memory storage
37- >>> memory = MemoryFactory.create_memory("inner", hist_maxlen=100)
38-
39- >>> # Create file-based storage
40- >>> memory = MemoryFactory.create_memory("file", storage_dir="./data")
4151 """
4252 memory_type = memory_type .lower ()
4353
4454 if memory_type not in cls ._memory_types :
4555 available_types = ", " .join (cls ._memory_types .keys ())
4656 raise ValueError (f"Unsupported memory type: { memory_type } . " f"Available types: { available_types } " )
4757
48- memory_class = cls ._memory_types [memory_type ]
49- return memory_class (** kwargs )
58+ # For hybrid, pass through specific parameters
59+ if memory_type == "hybrid" :
60+ return HybridMemory (
61+ redis_url = kwargs .get ("redis_url" ),
62+ db_url = kwargs .get ("db_url" ),
63+ hist_maxlen = kwargs .get ("hist_maxlen" , 200 ),
64+ prefix = kwargs .get ("prefix" , "vf:" ),
65+ redis_client = kwargs .get ("redis_client" ),
66+ )
67+
68+ # Other types use direct constructor
69+ impl_class = cls ._memory_types [memory_type ]
70+ return impl_class (** kwargs )
5071
5172 @classmethod
5273 def create_from_config (cls , config : Dict [str , Any ]) -> Memory :
53- """Create a memory instance from configuration dictionary.
74+ """Create a memory instance from a configuration dictionary.
5475
5576 Args:
56- config: Configuration dictionary containing memory settings
77+ config: Configuration dictionary
5778
5879 Returns:
5980 Memory instance
60-
61- Examples:
62- >>> config = {
63- ... "type": "inner",
64- ... "hist_maxlen": 200,
65- ... "cleanup_interval_sec": 300
66- ... }
67- >>> memory = MemoryFactory.create_from_config(config)
68-
69- >>> config = {
70- ... "type": "file",
71- ... "storage_dir": "./memory_data",
72- ... "hist_maxlen": 500
73- ... }
74- >>> memory = MemoryFactory.create_from_config(config)
7581 """
76- config = config .copy () # Don't modify original config
77- memory_type = config .pop ( "type" , "inner" )
78- return cls .create_memory (memory_type , ** config )
82+ memory_type = config .get ( "type" , "inner" )
83+ kwargs = { k : v for k , v in config .items () if k != "type" }
84+ return cls .create_memory (memory_type , ** kwargs )
7985
8086 @classmethod
81- def register_memory_type (cls , name : str , memory_class : type ) -> None :
82- """Register a new memory type.
83-
84- Args:
85- name: Name of the memory type
86- memory_class: Memory class to register
87+ def get_available_types (cls ) -> List [str ]:
88+ """Get a list of available memory types.
8789
88- Examples:
89- >>> class CustomMemory:
90- ... pass
91- >>> MemoryFactory.register_memory_type("custom", CustomMemory)
90+ Returns:
91+ List[str]: A list of supported memory type identifiers.
9292 """
93- cls ._memory_types [ name . lower ()] = memory_class
93+ return list ( cls ._memory_types . keys ())
9494
9595 @classmethod
96- def get_available_types (cls ) -> list [ str ] :
97- """Get list of available memory types .
96+ def register_memory_type (cls , name : str , impl_class : Any ) -> None :
97+ """Register a new memory implementation type at runtime .
9898
99- Returns:
100- List of available memory type names
99+ Args:
100+ name: Identifier used when calling create_memory
101+ impl_class: The class to instantiate for this type
101102 """
102- return list (cls ._memory_types .keys ())
103+ if not isinstance (name , str ) or not name .strip ():
104+ raise ValueError ("name must be a non-empty string" )
105+ cls ._memory_types [name .lower ()] = impl_class
103106
104107 @classmethod
105108 def get_default_config (cls , memory_type : str = "inner" ) -> Dict [str , Any ]:
@@ -109,7 +112,7 @@ def get_default_config(cls, memory_type: str = "inner") -> Dict[str, Any]:
109112 memory_type: Type of memory
110113
111114 Returns:
112- Default configuration dictionary
115+ Default configuration parameters for the specified memory type
113116
114117 Examples:
115118 >>> config = MemoryFactory.get_default_config("inner")
@@ -118,16 +121,36 @@ def get_default_config(cls, memory_type: str = "inner") -> Dict[str, Any]:
118121 """
119122 memory_type = memory_type .lower ()
120123
124+ # Build redis url from environment variables to avoid hardcoding sensitive strings
125+ default_redis_url = (
126+ f"redis://{ os .getenv ('VF_REDIS_HOST' , 'localhost' )} :{ os .getenv ('VF_REDIS_PORT' , '6379' )} /"
127+ f"{ os .getenv ('VF_REDIS_DB' , '0' )} "
128+ )
129+ default_rds_url = os .getenv ("VF_RDS_URL" , "sqlite:///:memory:" )
130+
121131 if memory_type in ["inner" , "memory" , "inmem" ]:
122132 return {"type" : "inner" , "hist_maxlen" : 200 , "cleanup_interval_sec" : 300 }
123133 elif memory_type == "file" :
124134 return {"type" : "file" , "storage_dir" : "./memory_data" , "hist_maxlen" : 200 }
135+ elif memory_type == "redis" :
136+ return {"type" : "redis" , "url" : default_redis_url , "hist_maxlen" : 200 }
137+ elif memory_type == "rds" :
138+ return {"type" : "rds" , "db_url" : default_rds_url , "hist_maxlen" : 200 }
139+ elif memory_type == "hybrid" :
140+ return {
141+ "type" : "hybrid" ,
142+ "redis_url" : default_redis_url ,
143+ "db_url" : default_rds_url ,
144+ "hist_maxlen" : 200 ,
145+ }
125146 else :
126147 available_types = ", " .join (cls ._memory_types .keys ())
127148 raise ValueError (f"Unsupported memory type: { memory_type } . " f"Available types: { available_types } " )
128149
129150
130151# Convenience functions for easier usage
152+
153+
131154def create_memory (memory_type : str = "inner" , ** kwargs ) -> Memory :
132155 """Convenience function to create a memory instance.
133156
0 commit comments