nebu 0.1.88__py3-none-any.whl → 0.1.93__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nebu/cache.py +15 -11
- nebu/containers/container.py +19 -13
- nebu/data.py +112 -92
- nebu/logging.py +33 -0
- nebu/namespaces/namespace.py +15 -8
- nebu/processors/consumer.py +244 -192
- nebu/processors/consumer_process_worker.py +179 -96
- nebu/processors/decorate.py +245 -219
- nebu/processors/processor.py +47 -32
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/METADATA +2 -1
- nebu-0.1.93.dist-info/RECORD +28 -0
- nebu/containers/decorator.py +0 -93
- nebu/containers/server.py +0 -70
- nebu/processors/remote.py +0 -47
- nebu-0.1.88.dist-info/RECORD +0 -30
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/WHEEL +0 -0
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/licenses/LICENSE +0 -0
- {nebu-0.1.88.dist-info → nebu-0.1.93.dist-info}/top_level.txt +0 -0
nebu/cache.py
CHANGED
@@ -7,6 +7,8 @@ import redis
|
|
7
7
|
import socks # Add socks import
|
8
8
|
from pydantic import BaseModel, Field
|
9
9
|
|
10
|
+
from nebu.logging import logger # Import the logger
|
11
|
+
|
10
12
|
|
11
13
|
class OwnedValue(BaseModel):
|
12
14
|
created_at: int = Field(default_factory=lambda: int(time.time()))
|
@@ -30,11 +32,11 @@ class Cache:
|
|
30
32
|
Also checks for REDIS_URL and prefers that if set.
|
31
33
|
"""
|
32
34
|
redis_url = os.environ.get("REDIS_URL")
|
33
|
-
|
35
|
+
logger.debug(f"REDIS_URL: {redis_url}")
|
34
36
|
namespace = os.environ.get("NEBU_NAMESPACE")
|
35
37
|
if not namespace:
|
36
38
|
raise ValueError("NEBU_NAMESPACE environment variable is not set")
|
37
|
-
|
39
|
+
logger.debug(f"NAMESPACE: {namespace}")
|
38
40
|
self.redis_client = None
|
39
41
|
connection_info = ""
|
40
42
|
|
@@ -43,9 +45,11 @@ class Cache:
|
|
43
45
|
# Use the proxy settings provided by tailscaled
|
44
46
|
socks.set_default_proxy(socks.SOCKS5, "localhost", 1055)
|
45
47
|
socket.socket = socks.socksocket
|
46
|
-
|
48
|
+
logger.info(
|
49
|
+
"Configured SOCKS5 proxy for socket connections via localhost:1055"
|
50
|
+
)
|
47
51
|
except Exception as proxy_err:
|
48
|
-
|
52
|
+
logger.warning(f"Failed to configure SOCKS proxy: {proxy_err}")
|
49
53
|
# Depending on requirements, you might want to raise an error here
|
50
54
|
# or proceed without the proxy if it's optional.
|
51
55
|
# For now, we'll print the error and continue, but the Redis connection
|
@@ -70,12 +74,12 @@ class Cache:
|
|
70
74
|
|
71
75
|
# Ping the server to ensure connection is established
|
72
76
|
self.redis_client.ping()
|
73
|
-
|
77
|
+
logger.info(f"Successfully connected to Redis using {connection_info}")
|
74
78
|
|
75
79
|
self.prefix = f"cache:{namespace}"
|
76
|
-
|
80
|
+
logger.info(f"Using cache prefix: {self.prefix}")
|
77
81
|
except Exception as e:
|
78
|
-
|
82
|
+
logger.error(f"Error connecting to Redis: {e}")
|
79
83
|
# Ensure client is None if connection fails at any point
|
80
84
|
self.redis_client = None
|
81
85
|
|
@@ -85,7 +89,7 @@ class Cache:
|
|
85
89
|
Returns None if the key does not exist or connection failed.
|
86
90
|
"""
|
87
91
|
if not self.redis_client:
|
88
|
-
|
92
|
+
logger.warning("Redis client not connected.")
|
89
93
|
return None
|
90
94
|
try:
|
91
95
|
key = f"{self.prefix}:{key}"
|
@@ -93,7 +97,7 @@ class Cache:
|
|
93
97
|
result = self.redis_client.get(key)
|
94
98
|
return cast(str | None, result)
|
95
99
|
except Exception as e:
|
96
|
-
|
100
|
+
logger.error(f"Error getting key '{key}' from Redis: {e}")
|
97
101
|
return None
|
98
102
|
|
99
103
|
def set(self, key: str, value: str, expiry_seconds: int | None = None) -> bool:
|
@@ -103,7 +107,7 @@ class Cache:
|
|
103
107
|
Returns True if successful, False otherwise (e.g., connection failed).
|
104
108
|
"""
|
105
109
|
if not self.redis_client:
|
106
|
-
|
110
|
+
logger.warning("Redis client not connected.")
|
107
111
|
return False
|
108
112
|
try:
|
109
113
|
key = f"{self.prefix}:{key}"
|
@@ -116,5 +120,5 @@ class Cache:
|
|
116
120
|
result = self.redis_client.set(key, value)
|
117
121
|
return cast(bool, result)
|
118
122
|
except Exception as e:
|
119
|
-
|
123
|
+
logger.error(f"Error setting key '{key}' in Redis: {e}")
|
120
124
|
return False
|
nebu/containers/container.py
CHANGED
@@ -18,6 +18,7 @@ from nebu.containers.models import (
|
|
18
18
|
V1SSHKey,
|
19
19
|
V1VolumePath,
|
20
20
|
)
|
21
|
+
from nebu.logging import logger # Import the logger
|
21
22
|
from nebu.meta import V1ResourceReference
|
22
23
|
|
23
24
|
|
@@ -42,18 +43,19 @@ class Container:
|
|
42
43
|
proxy_port: Optional[int] = None,
|
43
44
|
authz: Optional[V1AuthzConfig] = None,
|
44
45
|
config: Optional[GlobalConfig] = None,
|
46
|
+
api_key: Optional[str] = None,
|
45
47
|
):
|
46
48
|
# Fallback to a default config if none is provided
|
47
49
|
config = config or GlobalConfig.read()
|
48
50
|
current_server = config.get_current_server_config()
|
49
51
|
if not current_server:
|
50
52
|
raise ValueError("No current server config found")
|
51
|
-
self.api_key = current_server.api_key
|
53
|
+
self.api_key = api_key or current_server.api_key
|
52
54
|
self.nebu_host = current_server.server
|
53
55
|
self.config = config
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
+
logger.debug(f"nebu_host: {self.nebu_host}")
|
58
|
+
logger.debug(f"api_key: {self.api_key}")
|
57
59
|
|
58
60
|
# Construct the containers base URL
|
59
61
|
self.containers_url = f"{self.nebu_host}/v1/containers"
|
@@ -71,7 +73,7 @@ class Container:
|
|
71
73
|
)
|
72
74
|
|
73
75
|
containers = V1Containers.model_validate(response.json())
|
74
|
-
|
76
|
+
logger.debug(f"containers: {containers}")
|
75
77
|
existing = next(
|
76
78
|
(
|
77
79
|
c
|
@@ -81,7 +83,7 @@ class Container:
|
|
81
83
|
None,
|
82
84
|
)
|
83
85
|
|
84
|
-
|
86
|
+
logger.debug(f"existing: {existing}")
|
85
87
|
|
86
88
|
if not existing:
|
87
89
|
# If there's no existing container, create one:
|
@@ -114,7 +116,7 @@ class Container:
|
|
114
116
|
)
|
115
117
|
create_response.raise_for_status()
|
116
118
|
self.container = V1Container.model_validate(create_response.json())
|
117
|
-
|
119
|
+
logger.info(f"Created container {self.container.metadata.name}")
|
118
120
|
else:
|
119
121
|
# If container is found, check if anything has changed
|
120
122
|
# Gather the updated fields from the function arguments
|
@@ -154,11 +156,13 @@ class Container:
|
|
154
156
|
|
155
157
|
if not fields_changed:
|
156
158
|
# Nothing changed—do nothing
|
157
|
-
|
159
|
+
logger.info(
|
160
|
+
f"No changes detected for container {existing.metadata.name}."
|
161
|
+
)
|
158
162
|
self.container = existing
|
159
163
|
return
|
160
164
|
|
161
|
-
|
165
|
+
logger.info(
|
162
166
|
f"Detected changes for container {existing.metadata.name}, deleting and recreating."
|
163
167
|
)
|
164
168
|
|
@@ -175,7 +179,7 @@ class Container:
|
|
175
179
|
headers={"Authorization": f"Bearer {self.api_key}"},
|
176
180
|
)
|
177
181
|
delete_response.raise_for_status()
|
178
|
-
|
182
|
+
logger.info(f"Deleted container {existing.metadata.name}")
|
179
183
|
|
180
184
|
# Now recreate the container using the updated parameters
|
181
185
|
create_request = V1ContainerRequest(
|
@@ -204,7 +208,7 @@ class Container:
|
|
204
208
|
)
|
205
209
|
create_response.raise_for_status()
|
206
210
|
self.container = V1Container.model_validate(create_response.json())
|
207
|
-
|
211
|
+
logger.info(f"Recreated container {self.container.metadata.name}")
|
208
212
|
|
209
213
|
# Save constructor params to `self` for reference, like you do in ReplayBuffer.
|
210
214
|
self.kind = "Container"
|
@@ -242,7 +246,7 @@ class Container:
|
|
242
246
|
headers={"Authorization": f"Bearer {self.api_key}"},
|
243
247
|
)
|
244
248
|
response.raise_for_status()
|
245
|
-
|
249
|
+
logger.info(f"Deleted container {self.name} in namespace {self.namespace}")
|
246
250
|
|
247
251
|
@classmethod
|
248
252
|
def get(
|
@@ -250,6 +254,7 @@ class Container:
|
|
250
254
|
name: Optional[str] = None,
|
251
255
|
namespace: Optional[str] = None,
|
252
256
|
config: Optional[GlobalConfig] = None,
|
257
|
+
api_key: Optional[str] = None,
|
253
258
|
) -> List[V1Container]:
|
254
259
|
"""
|
255
260
|
Get a list of containers that match the optional name and/or namespace filters.
|
@@ -258,7 +263,7 @@ class Container:
|
|
258
263
|
current_server = config.get_current_server_config()
|
259
264
|
if not current_server:
|
260
265
|
raise ValueError("No current server config found")
|
261
|
-
api_key = current_server.api_key
|
266
|
+
api_key = api_key or current_server.api_key
|
262
267
|
nebu_host = current_server.server
|
263
268
|
|
264
269
|
containers_url = f"{nebu_host}/v1/containers"
|
@@ -292,6 +297,7 @@ class Container:
|
|
292
297
|
name: str,
|
293
298
|
namespace: Optional[str] = None,
|
294
299
|
config: Optional[GlobalConfig] = None,
|
300
|
+
api_key: Optional[str] = None,
|
295
301
|
):
|
296
302
|
"""
|
297
303
|
Get a container from the remote server.
|
@@ -307,7 +313,7 @@ class Container:
|
|
307
313
|
current_server = out.config.get_current_server_config()
|
308
314
|
if not current_server:
|
309
315
|
raise ValueError("No current server config found")
|
310
|
-
out.api_key = current_server.api_key
|
316
|
+
out.api_key = api_key or current_server.api_key
|
311
317
|
out.nebu_host = current_server.server
|
312
318
|
out.containers_url = f"{out.nebu_host}/v1/containers"
|
313
319
|
|