1212"""
1313
1414from wit_world .imports import config_store as wit_config_store
15- from wit_world .imports .types import Error_BufferLen , Error_InvalidArgument , OpenError
1615
17- from fastly_compute .exceptions import FastlyError , remap_wit_errors
18-
19-
20- class ConfigStoreError (FastlyError ):
21- """Base exception for all config store errors."""
22-
23-
24- class ConfigStoreNotFoundError (ConfigStoreError ):
25- """The requested config store does not exist."""
26-
27-
28- class ConfigStoreInvalidNameError (ConfigStoreError ):
29- """The config store name is invalid."""
30-
31-
32- class ConfigStoreBufferTooSmallError (ConfigStoreError ):
33- """The buffer provided was too small for the config value.
34-
35- The required buffer size is available in the `required_size` attribute.
36- """
37-
38- def __init__ (self , error : Error_BufferLen ):
39- """Initialize with the WIT error containing the required size.
40-
41- :param error: The WIT Error_BufferLen dataclass with the required size
42- """
43- self .required_size = error .value
44- super ().__init__ (
45- f"Buffer too small for config store value. Required size: { self .required_size } bytes"
46- )
47-
48-
49- class ConfigStoreInvalidKeyError (ConfigStoreError ):
50- """The key provided is invalid."""
16+ # The maximum value for a u64, used to signal that we don't want to cap
17+ # the length of values returned by the host.
18+ _MAX_U64 = 0xFFFFFFFFFFFFFFFF
5119
5220
5321class ConfigStore :
@@ -67,21 +35,14 @@ def __init__(self, store: wit_config_store.Store):
6735 self ._store = store
6836
6937 @classmethod
70- @remap_wit_errors (
71- {
72- OpenError .NOT_FOUND : ConfigStoreNotFoundError ,
73- OpenError .INVALID_SYNTAX : ConfigStoreInvalidNameError ,
74- OpenError .NAME_TOO_LONG : ConfigStoreInvalidNameError ,
75- OpenError .RESERVED : ConfigStoreInvalidNameError ,
76- }
77- )
7838 def open (cls , name : str ) -> "ConfigStore" :
7939 """Open a config store by name.
8040
8141 :param name: The name of the config store
8242 :return: ConfigStore instance
83- :raises ConfigStoreNotFoundError: If the config store doesn't exist
84- :raises ConfigStoreInvalidNameError: If the name is invalid or too long
43+ :raises ~fastly_compute.exceptions.types.open_error.NotFound: If the config store doesn't exist
44+ :raises ~fastly_compute.exceptions.types.open_error.InvalidSyntax: If the name is invalid
45+ :raises ~fastly_compute.exceptions.types.open_error.NameTooLong: If the name is too long
8546
8647 Example::
8748
@@ -90,91 +51,39 @@ def open(cls, name: str) -> "ConfigStore":
9051 store = wit_config_store .Store .open (name )
9152 return cls (store )
9253
93- def get (
94- self , key : str , default : str | None = None , initial_buf_len : int = 1024
95- ) -> str | None :
96- """Get a configuration value with automatic buffer resizing.
97-
98- This method automatically handles buffer sizing for config store values.
99- If the initial buffer is too small, it will automatically retry once with
100- the exact size required by the host.
54+ def get (self , key : str , default : str | None = None ) -> str | None :
55+ """Get a configuration value.
10156
10257 :param key: The configuration key
10358 :param default: Default value if key not found
104- :param initial_buf_len: Initial buffer size hint in bytes (default: 1024).
105- This can be tuned for performance if you know your values are typically
106- larger or smaller than 1KB.
10759 :return: Configuration value or default if not found
108- :raises ConfigStoreInvalidKeyError: If the key is invalid
109- :raises ConfigStoreBufferTooSmallError: If the value is too large even after
110- automatic resizing (should not happen unless there's a host-level bug)
60+ :raises ~fastly_compute.exceptions.types.error.InvalidArgument: If the key is invalid
11161
11262 Example::
11363
11464 config = ConfigStore.open("app-config")
115- # Basic usage with default buffer size
11665 api_url = config.get("api_url", "https://api.example.com")
117-
118- # Optimize for large values by using a larger initial buffer
119- large_value = config.get("large_config", initial_buf_len=16384)
12066 """
121- # Try with the initial buffer size
122- try :
123- result = self ._get_raw (key , initial_buf_len )
124- except ConfigStoreBufferTooSmallError as e :
125- # Buffer was too small. The exception contains the exact required size.
126- # Retry ONCE with the exact size needed. If this second attempt fails,
127- # let the exception propagate (no infinite recursion).
128- result = self ._get_raw (key , e .required_size )
129-
67+ result = self ._store .get (key , _MAX_U64 )
13068 if result is None :
13169 result = default
13270
13371 return result
13472
135- @remap_wit_errors (
136- {
137- Error_BufferLen : ConfigStoreBufferTooSmallError ,
138- Error_InvalidArgument : ConfigStoreInvalidKeyError ,
139- }
140- )
141- def _get_raw (self , key : str , max_len : int ) -> str | None :
142- """Internal method to get a value with a specific buffer size.
143-
144- :param key: The configuration key
145- :param max_len: Maximum buffer length
146- :return: Configuration value or None if not found
147- :raises ConfigStoreBufferTooSmallError: If the buffer is too small
148- :raises ConfigStoreInvalidKeyError: If the key is invalid
149- """
150- return self ._store .get (key , max_len )
151-
15273 def contains (self , key : str ) -> bool :
15374 """Check if a key exists in the config store.
15475
155- Uses a zero-length buffer to efficiently check for key existence without
156- retrieving the value.
157-
15876 :param key: The configuration key
15977 :return: True if the key exists, False otherwise
160- :raises ConfigStoreInvalidKeyError : If the key is invalid
78+ :raises ~fastly_compute.exceptions.types.error.InvalidArgument : If the key is invalid
16179
16280 Example::
16381
16482 config = ConfigStore.open("app-config")
16583 if config.contains("feature_flag"):
16684 print("Feature flag exists")
16785 """
168- try :
169- # Use a 0-length buffer to check existence without retrieving the value
170- result = self ._get_raw (key , 0 )
171- return result is not None
172- except ConfigStoreBufferTooSmallError :
173- # Buffer too small means the key exists with a non-empty value
174- return True
175- except ConfigStoreInvalidKeyError :
176- # Re-raise invalid key errors
177- raise
86+ return self .get (key ) is not None
17887
17988 def close (self ) -> None :
18089 """Explicitly close the config store, releasing its resources.
@@ -196,5 +105,10 @@ def __enter__(self) -> "ConfigStore":
196105 return self
197106
198107 def __exit__ (self , exc_type , exc_val , exc_tb ):
199- """Context manager exit."""
200- self ._store .__exit__ (exc_type , exc_val , exc_tb )
108+ """Context manager exit.
109+
110+ Use of the context manager will free up the underlying host resource on
111+ exit. Referencing the resource after context manager exit will result in
112+ a trap.
113+ """
114+ self .close ()
0 commit comments