setta 0.0.14.dev4__py3-none-any.whl → 0.0.14.dev6__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.
- setta/__init__.py +1 -1
- setta/tasks/task_runner.py +21 -9
- setta/tasks/tasks.py +53 -22
- setta/tasks/utils.py +55 -20
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/METADATA +1 -1
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/RECORD +10 -10
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/LICENSE +0 -0
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/WHEEL +0 -0
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/entry_points.txt +0 -0
- {setta-0.0.14.dev4.dist-info → setta-0.0.14.dev6.dist-info}/top_level.txt +0 -0
setta/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.0.14.
|
1
|
+
__version__ = "0.0.14.dev6"
|
setta/tasks/task_runner.py
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
import asyncio
|
2
2
|
import inspect
|
3
|
+
import logging
|
4
|
+
import traceback
|
3
5
|
from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor
|
4
6
|
from enum import Enum
|
5
7
|
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
6
10
|
|
7
11
|
class RunType(Enum):
|
8
12
|
SUBPROCESS = "SUBPROCESS"
|
@@ -16,14 +20,22 @@ class TaskRunner:
|
|
16
20
|
self.process_executor = ProcessPoolExecutor(max_workers=2)
|
17
21
|
|
18
22
|
async def run(self, fn, fn_args, run_as):
|
19
|
-
|
20
|
-
|
23
|
+
logger.debug(f"TaskRunner running function {fn.__name__} with run_as={run_as}")
|
24
|
+
try:
|
25
|
+
if inspect.iscoroutinefunction(fn):
|
26
|
+
return await fn(*fn_args)
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
if run_as == RunType.NONE:
|
29
|
+
return fn(*fn_args)
|
30
|
+
elif run_as == RunType.THREAD:
|
31
|
+
executor = self.thread_executor
|
32
|
+
elif run_as == RunType.SUBPROCESS:
|
33
|
+
executor = self.process_executor
|
28
34
|
|
29
|
-
|
35
|
+
return await asyncio.get_running_loop().run_in_executor(
|
36
|
+
executor, fn, *fn_args
|
37
|
+
)
|
38
|
+
except Exception as e:
|
39
|
+
logger.error(f"Error in TaskRunner.run: {str(e)}")
|
40
|
+
traceback.print_exc()
|
41
|
+
raise
|
setta/tasks/tasks.py
CHANGED
@@ -3,6 +3,7 @@ import copy
|
|
3
3
|
import json
|
4
4
|
import logging
|
5
5
|
import time
|
6
|
+
import traceback
|
6
7
|
from typing import Dict
|
7
8
|
|
8
9
|
from setta.database.utils import create_new_id
|
@@ -87,15 +88,25 @@ class Tasks:
|
|
87
88
|
or None in fnInfo["dependencies"]
|
88
89
|
or any(k in fnInfo["dependencies"] for k in message.content.keys())
|
89
90
|
):
|
90
|
-
|
91
|
-
|
92
|
-
{
|
93
|
-
"type": call_type,
|
94
|
-
"fn_name": fn_name,
|
95
|
-
"message": message,
|
96
|
-
"other_data": other_data,
|
97
|
-
}
|
91
|
+
logger.debug(
|
92
|
+
f"Sending message to subprocess {sp_key}, function {fn_name}, message type: {call_type}"
|
98
93
|
)
|
94
|
+
try:
|
95
|
+
# Send message to subprocess
|
96
|
+
sp_info["subprocess"].parent_conn.send(
|
97
|
+
{
|
98
|
+
"type": call_type,
|
99
|
+
"fn_name": fn_name,
|
100
|
+
"message": message,
|
101
|
+
"other_data": other_data,
|
102
|
+
}
|
103
|
+
)
|
104
|
+
except Exception as e:
|
105
|
+
logger.error(
|
106
|
+
f"Error sending message to subprocess {sp_key}: {str(e)}"
|
107
|
+
)
|
108
|
+
traceback.print_exc()
|
109
|
+
continue # Skip to next function if we can't send
|
99
110
|
|
100
111
|
# Create task for receiving response
|
101
112
|
task = asyncio.create_task(
|
@@ -127,23 +138,43 @@ class Tasks:
|
|
127
138
|
self, subprocess_key, fn_name, msg_id, recv_fn, websocket_manager, results
|
128
139
|
):
|
129
140
|
# Run the receive function in a thread
|
141
|
+
logger.debug(
|
142
|
+
f"Waiting for response from subprocess {subprocess_key}, function {fn_name}"
|
143
|
+
)
|
130
144
|
start_time = time.perf_counter()
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
subprocess_key, fn_name, elapsed_time
|
145
|
+
try:
|
146
|
+
result = await self.task_runner.run(recv_fn, [], RunType.THREAD)
|
147
|
+
logger.debug(
|
148
|
+
f"Received response from subprocess {subprocess_key}, function {fn_name}: status={result.get('status', 'unknown')}"
|
136
149
|
)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
await self.maybe_send_latest_run_time_info(
|
143
|
-
subprocess_key, fn_name, msg_id, websocket_manager
|
150
|
+
|
151
|
+
elapsed_time = time.perf_counter() - start_time
|
152
|
+
if result["status"] == "success":
|
153
|
+
self.update_average_subprocess_fn_time(
|
154
|
+
subprocess_key, fn_name, elapsed_time
|
144
155
|
)
|
145
|
-
|
146
|
-
|
156
|
+
if websocket_manager is not None:
|
157
|
+
if result["content"]:
|
158
|
+
await websocket_manager.send_message_to_requester(
|
159
|
+
msg_id, result["content"], result["messageType"]
|
160
|
+
)
|
161
|
+
await self.maybe_send_latest_run_time_info(
|
162
|
+
subprocess_key, fn_name, msg_id, websocket_manager
|
163
|
+
)
|
164
|
+
else:
|
165
|
+
results.append(result)
|
166
|
+
except EOFError:
|
167
|
+
logger.error(
|
168
|
+
f"EOF error when receiving response from subprocess {subprocess_key}, function {fn_name}"
|
169
|
+
)
|
170
|
+
# Add stack trace to see where exactly the error occurs
|
171
|
+
traceback.print_exc()
|
172
|
+
# Consider adding a placeholder result or raising to caller
|
173
|
+
except Exception as e:
|
174
|
+
logger.error(
|
175
|
+
f"Error receiving response from subprocess {subprocess_key}, function {fn_name}: {str(e)}"
|
176
|
+
)
|
177
|
+
traceback.print_exc()
|
147
178
|
|
148
179
|
async def add_custom_fns(self, code_graph, exporter_obj):
|
149
180
|
for c in code_graph:
|
setta/tasks/utils.py
CHANGED
@@ -61,8 +61,17 @@ class SettaInMemoryFnSubprocess:
|
|
61
61
|
sys.stderr = output_capture
|
62
62
|
|
63
63
|
while True:
|
64
|
-
|
65
|
-
|
64
|
+
try:
|
65
|
+
msg = self.child_conn.recv()
|
66
|
+
msg_type = msg["type"]
|
67
|
+
logger.debug(f"Subprocess received message type: {msg_type}")
|
68
|
+
except EOFError:
|
69
|
+
logger.error("EOF error when receiving message in subprocess")
|
70
|
+
break
|
71
|
+
except Exception as e:
|
72
|
+
logger.error(f"Error receiving message in subprocess: {str(e)}")
|
73
|
+
traceback.print_exc()
|
74
|
+
break
|
66
75
|
|
67
76
|
if msg_type == "shutdown":
|
68
77
|
# Signal all worker threads to stop
|
@@ -114,21 +123,43 @@ class SettaInMemoryFnSubprocess:
|
|
114
123
|
|
115
124
|
elif msg_type == "call" or msg_type == "call_with_new_exporter_obj":
|
116
125
|
fn_name = msg["fn_name"]
|
126
|
+
try:
|
127
|
+
logger.debug(
|
128
|
+
f"Subprocess about to process message for {fn_name}"
|
129
|
+
)
|
130
|
+
# Start a worker for this function if needed
|
131
|
+
self._start_worker_for_fn(
|
132
|
+
fn_name,
|
133
|
+
fn_workers,
|
134
|
+
fn_message_queues,
|
135
|
+
fns_dict,
|
136
|
+
cache,
|
137
|
+
lock,
|
138
|
+
send_lock,
|
139
|
+
self.child_conn,
|
140
|
+
)
|
117
141
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
send_lock
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
142
|
+
# Add the message to the function's queue
|
143
|
+
fn_message_queues[fn_name].put(msg)
|
144
|
+
except Exception as e:
|
145
|
+
logger.error(
|
146
|
+
f"Error processing message for {fn_name}: {str(e)}"
|
147
|
+
)
|
148
|
+
traceback.print_exc()
|
149
|
+
# Make sure to send an error response, so the parent doesn't hang
|
150
|
+
with send_lock:
|
151
|
+
try:
|
152
|
+
self.child_conn.send(
|
153
|
+
{
|
154
|
+
"status": "error",
|
155
|
+
"error": str(e),
|
156
|
+
"messageType": None,
|
157
|
+
}
|
158
|
+
)
|
159
|
+
except:
|
160
|
+
logger.error(
|
161
|
+
"Failed to send error response back to parent"
|
162
|
+
)
|
132
163
|
|
133
164
|
except Exception as e:
|
134
165
|
traceback.print_exc()
|
@@ -145,11 +176,14 @@ class SettaInMemoryFnSubprocess:
|
|
145
176
|
self, fn_name, fn_message_queues, fns_dict, cache, lock, send_lock, child_conn
|
146
177
|
):
|
147
178
|
"""Worker thread that processes messages for a specific function"""
|
179
|
+
logger.debug(f"Started worker thread for {fn_name}")
|
148
180
|
while True:
|
149
181
|
try:
|
150
182
|
# Get a message from the queue
|
151
183
|
msg = fn_message_queues[fn_name].get()
|
152
|
-
|
184
|
+
logger.debug(
|
185
|
+
f"Worker thread for {fn_name} got message of type: {msg.get('type') if msg else 'None'}"
|
186
|
+
)
|
153
187
|
if msg is None: # Sentinel value to stop the thread
|
154
188
|
break
|
155
189
|
|
@@ -241,10 +275,11 @@ class SettaInMemoryFnSubprocess:
|
|
241
275
|
|
242
276
|
# Send shutdown message to the subprocess
|
243
277
|
try:
|
278
|
+
logger.debug("Sending shutdown message to subprocess")
|
244
279
|
self.parent_conn.send({"type": "shutdown"})
|
245
|
-
|
246
|
-
|
247
|
-
|
280
|
+
logger.debug("Shutdown message sent")
|
281
|
+
except (BrokenPipeError, EOFError) as e:
|
282
|
+
logger.error(f"Error sending shutdown message: {str(e)}")
|
248
283
|
|
249
284
|
# Join the process with timeout
|
250
285
|
self.process.join(timeout=2)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
setta/__init__.py,sha256=
|
1
|
+
setta/__init__.py,sha256=Au0i6BplPktnDDP961GPD0r_9xhbmzMtWXB1881eIRw,28
|
2
2
|
setta/server.py,sha256=q4w9WG7SuLxwYtgXUCQyLt7t_HLmQV4y5abqvm7-uEA,4861
|
3
3
|
setta/start.py,sha256=5sMZ7WH3KV9Q0v186PsaYqsWOz7hebyrpXbBOp9wQww,3589
|
4
4
|
setta/cli/__init__.py,sha256=UxZG_VOMuF6lEBT3teUgTS9ulsK3wt3Gu3BbAQiAmt8,47
|
@@ -229,9 +229,9 @@ setta/static/frontend/assets/logo/logo.svg,sha256=k3XeAlA6hEaNfjnXG05hyb-8u1p_Fr
|
|
229
229
|
setta/static/seed/.DS_Store,sha256=ENxJvDQd7Te_U8gExcXtHE-mAeBUYOHELRfDWgN1NmA,6148
|
230
230
|
setta/static/seed/examples/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
|
231
231
|
setta/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
232
|
-
setta/tasks/task_runner.py,sha256=
|
233
|
-
setta/tasks/tasks.py,sha256=
|
234
|
-
setta/tasks/utils.py,sha256=
|
232
|
+
setta/tasks/task_runner.py,sha256=2bykjmSDPZ6lFqeaKTFYPN1eqHtrKDIZJpIi4PztL9Q,1232
|
233
|
+
setta/tasks/tasks.py,sha256=o8YVQvEW3uzhMTF38HFk_IgHVe4Wyye7ybb7QZm_-TQ,11695
|
234
|
+
setta/tasks/utils.py,sha256=GnFnNVhvXxzoIZtsvhDip12BMKVd73S3UCHdm7ZP01s,17786
|
235
235
|
setta/tasks/fns/__init__.py,sha256=JhGzzQGaT9BWtF3pOmguh6pzIF9kdG3jdDNLyYZ2w7g,461
|
236
236
|
setta/tasks/fns/codeAreaAutocomplete.py,sha256=gJ5JbjkWDyTothr-UF-YlOxrbVzj2iyOVK7XD3lfhSQ,6416
|
237
237
|
setta/tasks/fns/codeAreaFindTemplateVars.py,sha256=vD9rY8VNPavv6VKa1bnxRPPRDNvFQy6mPIZRl-_3GnY,3708
|
@@ -252,9 +252,9 @@ setta/utils/generate_new_filename.py,sha256=KBLX6paDmTvXR-027TpqQkfijIXc7mCfhen-
|
|
252
252
|
setta/utils/section_contents.py,sha256=V2HQPik6DfSXw4j7IalbP5AZ3OEGCbtL5ub3xL-Q_Qo,4141
|
253
253
|
setta/utils/utils.py,sha256=KjzcvgM3Ab3IcE8vaWYtgBpwzPLKg0LmblnHLoYZJHM,9164
|
254
254
|
setta/utils/websocket_manager.py,sha256=MBIMI8xxOFQF4lT3on4pupi1ttEWXdWPV4fI2YP_UJU,3925
|
255
|
-
setta-0.0.14.
|
256
|
-
setta-0.0.14.
|
257
|
-
setta-0.0.14.
|
258
|
-
setta-0.0.14.
|
259
|
-
setta-0.0.14.
|
260
|
-
setta-0.0.14.
|
255
|
+
setta-0.0.14.dev6.dist-info/LICENSE,sha256=us9fuCq9wmiZVzayjKxNZ2iJYF6dROe0Qp57ToCO7XU,11361
|
256
|
+
setta-0.0.14.dev6.dist-info/METADATA,sha256=UZ7Aa4y8MuovjaCfTVklgMKW9gokelnp1mWFNeLKba8,7517
|
257
|
+
setta-0.0.14.dev6.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
258
|
+
setta-0.0.14.dev6.dist-info/entry_points.txt,sha256=P0qCESy9fWF2q1EQ9JufGldCSnPHplDPn8J6Bgk5hB0,42
|
259
|
+
setta-0.0.14.dev6.dist-info/top_level.txt,sha256=8G4lmRzVOnJ11_DescPVHE6MQZH-o06A0nGsDDV2ngY,6
|
260
|
+
setta-0.0.14.dev6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|