UncountablePythonSDK 0.0.125__py3-none-any.whl → 0.0.127__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.
Potentially problematic release.
This version of UncountablePythonSDK might be problematic. Click here for more details.
- examples/integration-server/jobs/materials_auto/example_instrument.py +67 -38
- examples/integration-server/jobs/materials_auto/example_predictions.py +61 -0
- examples/integration-server/jobs/materials_auto/profile.yaml +9 -0
- examples/integration-server/pyproject.toml +3 -3
- pkgs/type_spec/builder.py +19 -9
- pkgs/type_spec/emit_typescript.py +2 -2
- pkgs/type_spec/type_info/emit_type_info.py +14 -1
- pkgs/type_spec/value_spec/__main__.py +2 -2
- uncountable/integration/cli.py +29 -1
- uncountable/integration/executors/executors.py +1 -2
- uncountable/integration/executors/generic_upload_executor.py +1 -1
- uncountable/integration/job.py +1 -0
- uncountable/integration/queue_runner/command_server/__init__.py +4 -0
- uncountable/integration/queue_runner/command_server/command_client.py +39 -0
- uncountable/integration/queue_runner/command_server/command_server.py +37 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server.proto +18 -0
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.py +21 -13
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2.pyi +28 -1
- uncountable/integration/queue_runner/command_server/protocol/command_server_pb2_grpc.py +90 -0
- uncountable/integration/queue_runner/command_server/types.py +24 -1
- uncountable/integration/queue_runner/datastore/datastore_sqlite.py +107 -8
- uncountable/integration/queue_runner/datastore/model.py +8 -1
- uncountable/integration/queue_runner/job_scheduler.py +42 -2
- uncountable/integration/queue_runner/worker.py +1 -1
- uncountable/integration/server.py +36 -6
- uncountable/types/__init__.py +8 -0
- uncountable/types/api/integrations/register_sockets_token.py +41 -0
- uncountable/types/api/recipes/edit_recipe_inputs.py +1 -1
- uncountable/types/api/recipes/get_recipe_output_metadata.py +2 -2
- uncountable/types/api/recipes/get_recipes_data.py +16 -0
- uncountable/types/api/recipes/lock_recipes.py +2 -1
- uncountable/types/api/recipes/set_recipe_total.py +59 -0
- uncountable/types/api/recipes/unlock_recipes.py +2 -1
- uncountable/types/api/uploader/complete_async_parse.py +46 -0
- uncountable/types/async_batch_processor.py +124 -0
- uncountable/types/async_batch_t.py +2 -0
- uncountable/types/client_base.py +76 -0
- uncountable/types/entity_t.py +1 -1
- uncountable/types/queued_job.py +1 -0
- uncountable/types/queued_job_t.py +9 -0
- uncountable/types/sockets.py +9 -0
- uncountable/types/sockets_t.py +99 -0
- uncountable/types/uploader.py +24 -0
- uncountable/types/uploader_t.py +222 -0
- {uncountablepythonsdk-0.0.125.dist-info → uncountablepythonsdk-0.0.127.dist-info}/METADATA +1 -1
- {uncountablepythonsdk-0.0.125.dist-info → uncountablepythonsdk-0.0.127.dist-info}/RECORD +48 -42
- {uncountablepythonsdk-0.0.125.dist-info → uncountablepythonsdk-0.0.127.dist-info}/WHEEL +0 -0
- {uncountablepythonsdk-0.0.125.dist-info → uncountablepythonsdk-0.0.127.dist-info}/top_level.txt +0 -0
|
@@ -18,7 +18,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
|
|
21
|
-
b'\nQuncountable/integration/queue_runner/command_server/protocol/command_server.proto\x1a\x1fgoogle/protobuf/timestamp.proto"E\n\x11\x45nqueueJobRequest\x12\x14\n\x0cjob_ref_name\x18\x01 \x01(\t\x12\x1a\n\x12serialized_payload\x18\x02 \x01(\t"H\n\x10\x45nqueueJobResult\x12\x1b\n\x13successfully_queued\x18\x01 \x01(\x08\x12\x17\n\x0fqueued_job_uuid\x18\x02 \x01(\t"\x14\n\x12\x43heckHealthRequest"$\n\x11\x43heckHealthResult\x12\x0f\n\x07success\x18\x01 \x01(\x08"6\n\x15ListQueuedJobsRequest\x12\x0e\n\x06offset\x18\x01 \x01(\r\x12\r\n\x05limit\x18\x02 \x01(\r"\
|
|
21
|
+
b'\nQuncountable/integration/queue_runner/command_server/protocol/command_server.proto\x1a\x1fgoogle/protobuf/timestamp.proto"E\n\x11\x45nqueueJobRequest\x12\x14\n\x0cjob_ref_name\x18\x01 \x01(\t\x12\x1a\n\x12serialized_payload\x18\x02 \x01(\t"H\n\x10\x45nqueueJobResult\x12\x1b\n\x13successfully_queued\x18\x01 \x01(\x08\x12\x17\n\x0fqueued_job_uuid\x18\x02 \x01(\t"\x1f\n\x0fRetryJobRequest\x12\x0c\n\x04uuid\x18\x01 \x01(\t"F\n\x0eRetryJobResult\x12\x1b\n\x13successfully_queued\x18\x01 \x01(\x08\x12\x17\n\x0fqueued_job_uuid\x18\x02 \x01(\t"\x1a\n\x18VaccuumQueuedJobsRequest"\x19\n\x17VaccuumQueuedJobsResult"\x14\n\x12\x43heckHealthRequest"$\n\x11\x43heckHealthResult\x12\x0f\n\x07success\x18\x01 \x01(\x08"6\n\x15ListQueuedJobsRequest\x12\x0e\n\x06offset\x18\x01 \x01(\r\x12\r\n\x05limit\x18\x02 \x01(\r"\xf4\x01\n\x14ListQueuedJobsResult\x12\x43\n\x0bqueued_jobs\x18\x01 \x03(\x0b\x32..ListQueuedJobsResult.ListQueuedJobsResultItem\x1a\x96\x01\n\x18ListQueuedJobsResultItem\x12\x0c\n\x04uuid\x18\x01 \x01(\t\x12\x14\n\x0cjob_ref_name\x18\x02 \x01(\t\x12\x14\n\x0cnum_attempts\x18\x03 \x01(\x03\x12\x30\n\x0csubmitted_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0e\n\x06status\x18\x05 \x01(\t2\xc0\x02\n\rCommandServer\x12\x35\n\nEnqueueJob\x12\x12.EnqueueJobRequest\x1a\x11.EnqueueJobResult"\x00\x12/\n\x08RetryJob\x12\x10.RetryJobRequest\x1a\x0f.RetryJobResult"\x00\x12\x38\n\x0b\x43heckHealth\x12\x13.CheckHealthRequest\x1a\x12.CheckHealthResult"\x00\x12\x41\n\x0eListQueuedJobs\x12\x16.ListQueuedJobsRequest\x1a\x15.ListQueuedJobsResult"\x00\x12J\n\x11VaccuumQueuedJobs\x12\x19.VaccuumQueuedJobsRequest\x1a\x18.VaccuumQueuedJobsResult"\x00\x62\x06proto3'
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
_globals = globals()
|
|
@@ -34,16 +34,24 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|
|
34
34
|
_globals["_ENQUEUEJOBREQUEST"]._serialized_end = 187
|
|
35
35
|
_globals["_ENQUEUEJOBRESULT"]._serialized_start = 189
|
|
36
36
|
_globals["_ENQUEUEJOBRESULT"]._serialized_end = 261
|
|
37
|
-
_globals["
|
|
38
|
-
_globals["
|
|
39
|
-
_globals["
|
|
40
|
-
_globals["
|
|
41
|
-
_globals["
|
|
42
|
-
_globals["
|
|
43
|
-
_globals["
|
|
44
|
-
_globals["
|
|
45
|
-
_globals["
|
|
46
|
-
_globals["
|
|
47
|
-
_globals["
|
|
48
|
-
_globals["
|
|
37
|
+
_globals["_RETRYJOBREQUEST"]._serialized_start = 263
|
|
38
|
+
_globals["_RETRYJOBREQUEST"]._serialized_end = 294
|
|
39
|
+
_globals["_RETRYJOBRESULT"]._serialized_start = 296
|
|
40
|
+
_globals["_RETRYJOBRESULT"]._serialized_end = 366
|
|
41
|
+
_globals["_VACCUUMQUEUEDJOBSREQUEST"]._serialized_start = 368
|
|
42
|
+
_globals["_VACCUUMQUEUEDJOBSREQUEST"]._serialized_end = 394
|
|
43
|
+
_globals["_VACCUUMQUEUEDJOBSRESULT"]._serialized_start = 396
|
|
44
|
+
_globals["_VACCUUMQUEUEDJOBSRESULT"]._serialized_end = 421
|
|
45
|
+
_globals["_CHECKHEALTHREQUEST"]._serialized_start = 423
|
|
46
|
+
_globals["_CHECKHEALTHREQUEST"]._serialized_end = 443
|
|
47
|
+
_globals["_CHECKHEALTHRESULT"]._serialized_start = 445
|
|
48
|
+
_globals["_CHECKHEALTHRESULT"]._serialized_end = 481
|
|
49
|
+
_globals["_LISTQUEUEDJOBSREQUEST"]._serialized_start = 483
|
|
50
|
+
_globals["_LISTQUEUEDJOBSREQUEST"]._serialized_end = 537
|
|
51
|
+
_globals["_LISTQUEUEDJOBSRESULT"]._serialized_start = 540
|
|
52
|
+
_globals["_LISTQUEUEDJOBSRESULT"]._serialized_end = 784
|
|
53
|
+
_globals["_LISTQUEUEDJOBSRESULT_LISTQUEUEDJOBSRESULTITEM"]._serialized_start = 634
|
|
54
|
+
_globals["_LISTQUEUEDJOBSRESULT_LISTQUEUEDJOBSRESULTITEM"]._serialized_end = 784
|
|
55
|
+
_globals["_COMMANDSERVER"]._serialized_start = 787
|
|
56
|
+
_globals["_COMMANDSERVER"]._serialized_end = 1107
|
|
49
57
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -35,6 +35,30 @@ class EnqueueJobResult(_message.Message):
|
|
|
35
35
|
self, successfully_queued: bool = ..., queued_job_uuid: _Optional[str] = ...
|
|
36
36
|
) -> None: ...
|
|
37
37
|
|
|
38
|
+
class RetryJobRequest(_message.Message):
|
|
39
|
+
__slots__ = ("uuid",)
|
|
40
|
+
UUID_FIELD_NUMBER: _ClassVar[int]
|
|
41
|
+
uuid: str
|
|
42
|
+
def __init__(self, uuid: _Optional[str] = ...) -> None: ...
|
|
43
|
+
|
|
44
|
+
class RetryJobResult(_message.Message):
|
|
45
|
+
__slots__ = ("successfully_queued", "queued_job_uuid")
|
|
46
|
+
SUCCESSFULLY_QUEUED_FIELD_NUMBER: _ClassVar[int]
|
|
47
|
+
QUEUED_JOB_UUID_FIELD_NUMBER: _ClassVar[int]
|
|
48
|
+
successfully_queued: bool
|
|
49
|
+
queued_job_uuid: str
|
|
50
|
+
def __init__(
|
|
51
|
+
self, successfully_queued: bool = ..., queued_job_uuid: _Optional[str] = ...
|
|
52
|
+
) -> None: ...
|
|
53
|
+
|
|
54
|
+
class VaccuumQueuedJobsRequest(_message.Message):
|
|
55
|
+
__slots__ = ()
|
|
56
|
+
def __init__(self) -> None: ...
|
|
57
|
+
|
|
58
|
+
class VaccuumQueuedJobsResult(_message.Message):
|
|
59
|
+
__slots__ = ()
|
|
60
|
+
def __init__(self) -> None: ...
|
|
61
|
+
|
|
38
62
|
class CheckHealthRequest(_message.Message):
|
|
39
63
|
__slots__ = ()
|
|
40
64
|
def __init__(self) -> None: ...
|
|
@@ -58,21 +82,24 @@ class ListQueuedJobsRequest(_message.Message):
|
|
|
58
82
|
class ListQueuedJobsResult(_message.Message):
|
|
59
83
|
__slots__ = ("queued_jobs",)
|
|
60
84
|
class ListQueuedJobsResultItem(_message.Message):
|
|
61
|
-
__slots__ = ("uuid", "job_ref_name", "num_attempts", "submitted_at")
|
|
85
|
+
__slots__ = ("uuid", "job_ref_name", "num_attempts", "submitted_at", "status")
|
|
62
86
|
UUID_FIELD_NUMBER: _ClassVar[int]
|
|
63
87
|
JOB_REF_NAME_FIELD_NUMBER: _ClassVar[int]
|
|
64
88
|
NUM_ATTEMPTS_FIELD_NUMBER: _ClassVar[int]
|
|
65
89
|
SUBMITTED_AT_FIELD_NUMBER: _ClassVar[int]
|
|
90
|
+
STATUS_FIELD_NUMBER: _ClassVar[int]
|
|
66
91
|
uuid: str
|
|
67
92
|
job_ref_name: str
|
|
68
93
|
num_attempts: int
|
|
69
94
|
submitted_at: _timestamp_pb2.Timestamp
|
|
95
|
+
status: str
|
|
70
96
|
def __init__(
|
|
71
97
|
self,
|
|
72
98
|
uuid: _Optional[str] = ...,
|
|
73
99
|
job_ref_name: _Optional[str] = ...,
|
|
74
100
|
num_attempts: _Optional[int] = ...,
|
|
75
101
|
submitted_at: _Optional[_Union[_timestamp_pb2.Timestamp, _Mapping]] = ...,
|
|
102
|
+
status: _Optional[str] = ...,
|
|
76
103
|
) -> None: ...
|
|
77
104
|
|
|
78
105
|
QUEUED_JOBS_FIELD_NUMBER: _ClassVar[int]
|
|
@@ -24,6 +24,11 @@ class CommandServerStub(object):
|
|
|
24
24
|
request_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.EnqueueJobRequest.SerializeToString,
|
|
25
25
|
response_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.EnqueueJobResult.FromString,
|
|
26
26
|
)
|
|
27
|
+
self.RetryJob = channel.unary_unary(
|
|
28
|
+
"/CommandServer/RetryJob",
|
|
29
|
+
request_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobRequest.SerializeToString,
|
|
30
|
+
response_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobResult.FromString,
|
|
31
|
+
)
|
|
27
32
|
self.CheckHealth = channel.unary_unary(
|
|
28
33
|
"/CommandServer/CheckHealth",
|
|
29
34
|
request_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.CheckHealthRequest.SerializeToString,
|
|
@@ -34,6 +39,11 @@ class CommandServerStub(object):
|
|
|
34
39
|
request_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.ListQueuedJobsRequest.SerializeToString,
|
|
35
40
|
response_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.ListQueuedJobsResult.FromString,
|
|
36
41
|
)
|
|
42
|
+
self.VaccuumQueuedJobs = channel.unary_unary(
|
|
43
|
+
"/CommandServer/VaccuumQueuedJobs",
|
|
44
|
+
request_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsRequest.SerializeToString,
|
|
45
|
+
response_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsResult.FromString,
|
|
46
|
+
)
|
|
37
47
|
|
|
38
48
|
|
|
39
49
|
class CommandServerServicer(object):
|
|
@@ -45,6 +55,12 @@ class CommandServerServicer(object):
|
|
|
45
55
|
context.set_details("Method not implemented!")
|
|
46
56
|
raise NotImplementedError("Method not implemented!")
|
|
47
57
|
|
|
58
|
+
def RetryJob(self, request, context):
|
|
59
|
+
"""Missing associated documentation comment in .proto file."""
|
|
60
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
61
|
+
context.set_details("Method not implemented!")
|
|
62
|
+
raise NotImplementedError("Method not implemented!")
|
|
63
|
+
|
|
48
64
|
def CheckHealth(self, request, context):
|
|
49
65
|
"""Missing associated documentation comment in .proto file."""
|
|
50
66
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
@@ -57,6 +73,12 @@ class CommandServerServicer(object):
|
|
|
57
73
|
context.set_details("Method not implemented!")
|
|
58
74
|
raise NotImplementedError("Method not implemented!")
|
|
59
75
|
|
|
76
|
+
def VaccuumQueuedJobs(self, request, context):
|
|
77
|
+
"""Missing associated documentation comment in .proto file."""
|
|
78
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
79
|
+
context.set_details("Method not implemented!")
|
|
80
|
+
raise NotImplementedError("Method not implemented!")
|
|
81
|
+
|
|
60
82
|
|
|
61
83
|
def add_CommandServerServicer_to_server(servicer, server):
|
|
62
84
|
rpc_method_handlers = {
|
|
@@ -65,6 +87,11 @@ def add_CommandServerServicer_to_server(servicer, server):
|
|
|
65
87
|
request_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.EnqueueJobRequest.FromString,
|
|
66
88
|
response_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.EnqueueJobResult.SerializeToString,
|
|
67
89
|
),
|
|
90
|
+
"RetryJob": grpc.unary_unary_rpc_method_handler(
|
|
91
|
+
servicer.RetryJob,
|
|
92
|
+
request_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobRequest.FromString,
|
|
93
|
+
response_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobResult.SerializeToString,
|
|
94
|
+
),
|
|
68
95
|
"CheckHealth": grpc.unary_unary_rpc_method_handler(
|
|
69
96
|
servicer.CheckHealth,
|
|
70
97
|
request_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.CheckHealthRequest.FromString,
|
|
@@ -75,6 +102,11 @@ def add_CommandServerServicer_to_server(servicer, server):
|
|
|
75
102
|
request_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.ListQueuedJobsRequest.FromString,
|
|
76
103
|
response_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.ListQueuedJobsResult.SerializeToString,
|
|
77
104
|
),
|
|
105
|
+
"VaccuumQueuedJobs": grpc.unary_unary_rpc_method_handler(
|
|
106
|
+
servicer.VaccuumQueuedJobs,
|
|
107
|
+
request_deserializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsRequest.FromString,
|
|
108
|
+
response_serializer=uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsResult.SerializeToString,
|
|
109
|
+
),
|
|
78
110
|
}
|
|
79
111
|
generic_handler = grpc.method_handlers_generic_handler(
|
|
80
112
|
"CommandServer", rpc_method_handlers
|
|
@@ -115,6 +147,35 @@ class CommandServer(object):
|
|
|
115
147
|
metadata,
|
|
116
148
|
)
|
|
117
149
|
|
|
150
|
+
@staticmethod
|
|
151
|
+
def RetryJob(
|
|
152
|
+
request,
|
|
153
|
+
target,
|
|
154
|
+
options=(),
|
|
155
|
+
channel_credentials=None,
|
|
156
|
+
call_credentials=None,
|
|
157
|
+
insecure=False,
|
|
158
|
+
compression=None,
|
|
159
|
+
wait_for_ready=None,
|
|
160
|
+
timeout=None,
|
|
161
|
+
metadata=None,
|
|
162
|
+
):
|
|
163
|
+
return grpc.experimental.unary_unary(
|
|
164
|
+
request,
|
|
165
|
+
target,
|
|
166
|
+
"/CommandServer/RetryJob",
|
|
167
|
+
uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobRequest.SerializeToString,
|
|
168
|
+
uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.RetryJobResult.FromString,
|
|
169
|
+
options,
|
|
170
|
+
channel_credentials,
|
|
171
|
+
insecure,
|
|
172
|
+
call_credentials,
|
|
173
|
+
compression,
|
|
174
|
+
wait_for_ready,
|
|
175
|
+
timeout,
|
|
176
|
+
metadata,
|
|
177
|
+
)
|
|
178
|
+
|
|
118
179
|
@staticmethod
|
|
119
180
|
def CheckHealth(
|
|
120
181
|
request,
|
|
@@ -172,3 +233,32 @@ class CommandServer(object):
|
|
|
172
233
|
timeout,
|
|
173
234
|
metadata,
|
|
174
235
|
)
|
|
236
|
+
|
|
237
|
+
@staticmethod
|
|
238
|
+
def VaccuumQueuedJobs(
|
|
239
|
+
request,
|
|
240
|
+
target,
|
|
241
|
+
options=(),
|
|
242
|
+
channel_credentials=None,
|
|
243
|
+
call_credentials=None,
|
|
244
|
+
insecure=False,
|
|
245
|
+
compression=None,
|
|
246
|
+
wait_for_ready=None,
|
|
247
|
+
timeout=None,
|
|
248
|
+
metadata=None,
|
|
249
|
+
):
|
|
250
|
+
return grpc.experimental.unary_unary(
|
|
251
|
+
request,
|
|
252
|
+
target,
|
|
253
|
+
"/CommandServer/VaccuumQueuedJobs",
|
|
254
|
+
uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsRequest.SerializeToString,
|
|
255
|
+
uncountable_dot_integration_dot_queue__runner_dot_command__server_dot_protocol_dot_command__server__pb2.VaccuumQueuedJobsResult.FromString,
|
|
256
|
+
options,
|
|
257
|
+
channel_credentials,
|
|
258
|
+
insecure,
|
|
259
|
+
call_credentials,
|
|
260
|
+
compression,
|
|
261
|
+
wait_for_ready,
|
|
262
|
+
timeout,
|
|
263
|
+
metadata,
|
|
264
|
+
)
|
|
@@ -8,6 +8,8 @@ from uncountable.types import queued_job_t
|
|
|
8
8
|
|
|
9
9
|
class CommandType(StrEnum):
|
|
10
10
|
ENQUEUE_JOB = "enqueue_job"
|
|
11
|
+
RETRY_JOB = "retry_job"
|
|
12
|
+
VACCUUM_QUEUED_JOBS = "vaccuum_queued_jobs"
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
RT = typing.TypeVar("RT")
|
|
@@ -24,6 +26,16 @@ class CommandEnqueueJobResponse:
|
|
|
24
26
|
queued_job_uuid: str
|
|
25
27
|
|
|
26
28
|
|
|
29
|
+
@dataclass(kw_only=True)
|
|
30
|
+
class CommandRetryJobResponse:
|
|
31
|
+
queued_job_uuid: str | None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(kw_only=True)
|
|
35
|
+
class CommandVaccuumQueuedJobsResponse:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
27
39
|
@dataclass(kw_only=True)
|
|
28
40
|
class CommandEnqueueJob(CommandBase[CommandEnqueueJobResponse]):
|
|
29
41
|
type: CommandType = CommandType.ENQUEUE_JOB
|
|
@@ -32,7 +44,18 @@ class CommandEnqueueJob(CommandBase[CommandEnqueueJobResponse]):
|
|
|
32
44
|
response_queue: asyncio.Queue[CommandEnqueueJobResponse]
|
|
33
45
|
|
|
34
46
|
|
|
35
|
-
|
|
47
|
+
@dataclass(kw_only=True)
|
|
48
|
+
class CommandRetryJob(CommandBase[CommandRetryJobResponse]):
|
|
49
|
+
type: CommandType = CommandType.RETRY_JOB
|
|
50
|
+
queued_job_uuid: str
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(kw_only=True)
|
|
54
|
+
class CommandVaccuumQueuedJobs(CommandBase[CommandVaccuumQueuedJobsResponse]):
|
|
55
|
+
type: CommandType = CommandType.VACCUUM_QUEUED_JOBS
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
_Command = CommandEnqueueJob | CommandRetryJob | CommandVaccuumQueuedJobs
|
|
36
59
|
|
|
37
60
|
|
|
38
61
|
CommandQueue = asyncio.Queue[_Command]
|
|
@@ -2,7 +2,7 @@ import datetime
|
|
|
2
2
|
import uuid
|
|
3
3
|
from datetime import UTC
|
|
4
4
|
|
|
5
|
-
from sqlalchemy import delete, insert, select, update
|
|
5
|
+
from sqlalchemy import delete, insert, or_, select, text, update
|
|
6
6
|
from sqlalchemy.engine import Engine
|
|
7
7
|
|
|
8
8
|
from pkgs.argument_parser import CachedParser
|
|
@@ -14,6 +14,8 @@ from uncountable.types import queued_job_t
|
|
|
14
14
|
|
|
15
15
|
queued_job_payload_parser = CachedParser(queued_job_t.QueuedJobPayload)
|
|
16
16
|
|
|
17
|
+
MAX_QUEUE_WINDOW_DAYS = 30
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class DatastoreSqlite(Datastore):
|
|
19
21
|
def __init__(self, session_maker: DBSessionMaker) -> None:
|
|
@@ -23,6 +25,17 @@ class DatastoreSqlite(Datastore):
|
|
|
23
25
|
@classmethod
|
|
24
26
|
def setup(cls, engine: Engine) -> None:
|
|
25
27
|
Base.metadata.create_all(engine)
|
|
28
|
+
with engine.connect() as connection:
|
|
29
|
+
if not bool(
|
|
30
|
+
connection.execute(
|
|
31
|
+
text(
|
|
32
|
+
"select exists (select 1 from pragma_table_info('queued_jobs') where name='status');"
|
|
33
|
+
)
|
|
34
|
+
).scalar()
|
|
35
|
+
):
|
|
36
|
+
connection.execute(
|
|
37
|
+
text("alter table queued_jobs add column status VARCHAR")
|
|
38
|
+
)
|
|
26
39
|
|
|
27
40
|
def add_job_to_queue(
|
|
28
41
|
self, job_payload: queued_job_t.QueuedJobPayload, job_ref_name: str
|
|
@@ -36,6 +49,7 @@ class DatastoreSqlite(Datastore):
|
|
|
36
49
|
QueuedJob.id.key: queued_job_uuid,
|
|
37
50
|
QueuedJob.job_ref_name.key: job_ref_name,
|
|
38
51
|
QueuedJob.payload.key: serialized_payload,
|
|
52
|
+
QueuedJob.status.key: queued_job_t.JobStatus.QUEUED,
|
|
39
53
|
QueuedJob.num_attempts: num_attempts,
|
|
40
54
|
QueuedJob.submitted_at: submitted_at,
|
|
41
55
|
})
|
|
@@ -44,10 +58,48 @@ class DatastoreSqlite(Datastore):
|
|
|
44
58
|
queued_job_uuid=queued_job_uuid,
|
|
45
59
|
job_ref_name=job_ref_name,
|
|
46
60
|
payload=job_payload,
|
|
61
|
+
status=queued_job_t.JobStatus.QUEUED,
|
|
47
62
|
submitted_at=submitted_at,
|
|
48
63
|
num_attempts=num_attempts,
|
|
49
64
|
)
|
|
50
65
|
|
|
66
|
+
def retry_job(
|
|
67
|
+
self,
|
|
68
|
+
queued_job_uuid: str,
|
|
69
|
+
) -> queued_job_t.QueuedJob | None:
|
|
70
|
+
with self.session_maker() as session:
|
|
71
|
+
select_stmt = select(
|
|
72
|
+
QueuedJob.id,
|
|
73
|
+
QueuedJob.payload,
|
|
74
|
+
QueuedJob.num_attempts,
|
|
75
|
+
QueuedJob.job_ref_name,
|
|
76
|
+
QueuedJob.status,
|
|
77
|
+
QueuedJob.submitted_at,
|
|
78
|
+
).filter(QueuedJob.id == queued_job_uuid)
|
|
79
|
+
existing_job = session.execute(select_stmt).one_or_none()
|
|
80
|
+
|
|
81
|
+
if (
|
|
82
|
+
existing_job is None
|
|
83
|
+
or existing_job.status != queued_job_t.JobStatus.FAILED
|
|
84
|
+
):
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
update_stmt = (
|
|
88
|
+
update(QueuedJob)
|
|
89
|
+
.values({QueuedJob.status.key: queued_job_t.JobStatus.QUEUED})
|
|
90
|
+
.filter(QueuedJob.id == queued_job_uuid)
|
|
91
|
+
)
|
|
92
|
+
session.execute(update_stmt)
|
|
93
|
+
|
|
94
|
+
return queued_job_t.QueuedJob(
|
|
95
|
+
queued_job_uuid=existing_job.id,
|
|
96
|
+
job_ref_name=existing_job.job_ref_name,
|
|
97
|
+
num_attempts=existing_job.num_attempts,
|
|
98
|
+
status=queued_job_t.JobStatus.QUEUED,
|
|
99
|
+
submitted_at=existing_job.submitted_at,
|
|
100
|
+
payload=queued_job_payload_parser.parse_storage(existing_job.payload),
|
|
101
|
+
)
|
|
102
|
+
|
|
51
103
|
def increment_num_attempts(self, queued_job_uuid: str) -> int:
|
|
52
104
|
with self.session_maker() as session:
|
|
53
105
|
update_stmt = (
|
|
@@ -68,6 +120,17 @@ class DatastoreSqlite(Datastore):
|
|
|
68
120
|
delete_stmt = delete(QueuedJob).filter(QueuedJob.id == queued_job_uuid)
|
|
69
121
|
session.execute(delete_stmt)
|
|
70
122
|
|
|
123
|
+
def update_job_status(
|
|
124
|
+
self, queued_job_uuid: str, status: queued_job_t.JobStatus
|
|
125
|
+
) -> None:
|
|
126
|
+
with self.session_maker() as session:
|
|
127
|
+
update_stmt = (
|
|
128
|
+
update(QueuedJob)
|
|
129
|
+
.values({QueuedJob.status.key: status})
|
|
130
|
+
.filter(QueuedJob.id == queued_job_uuid)
|
|
131
|
+
)
|
|
132
|
+
session.execute(update_stmt)
|
|
133
|
+
|
|
71
134
|
def list_queued_job_metadata(
|
|
72
135
|
self, offset: int = 0, limit: int | None = 100
|
|
73
136
|
) -> list[queued_job_t.QueuedJobMetadata]:
|
|
@@ -77,6 +140,7 @@ class DatastoreSqlite(Datastore):
|
|
|
77
140
|
QueuedJob.id,
|
|
78
141
|
QueuedJob.job_ref_name,
|
|
79
142
|
QueuedJob.num_attempts,
|
|
143
|
+
QueuedJob.status,
|
|
80
144
|
QueuedJob.submitted_at,
|
|
81
145
|
)
|
|
82
146
|
.order_by(QueuedJob.submitted_at)
|
|
@@ -89,6 +153,7 @@ class DatastoreSqlite(Datastore):
|
|
|
89
153
|
queued_job_uuid=row.id,
|
|
90
154
|
job_ref_name=row.job_ref_name,
|
|
91
155
|
num_attempts=row.num_attempts,
|
|
156
|
+
status=row.status or queued_job_t.JobStatus.QUEUED,
|
|
92
157
|
submitted_at=row.submitted_at,
|
|
93
158
|
)
|
|
94
159
|
for row in session.execute(select_statement)
|
|
@@ -106,9 +171,16 @@ class DatastoreSqlite(Datastore):
|
|
|
106
171
|
QueuedJob.payload,
|
|
107
172
|
QueuedJob.num_attempts,
|
|
108
173
|
QueuedJob.job_ref_name,
|
|
174
|
+
QueuedJob.status,
|
|
109
175
|
QueuedJob.submitted_at,
|
|
110
176
|
)
|
|
111
177
|
.filter(QueuedJob.job_ref_name == job_ref_name)
|
|
178
|
+
.filter(
|
|
179
|
+
or_(
|
|
180
|
+
QueuedJob.status == queued_job_t.JobStatus.QUEUED,
|
|
181
|
+
QueuedJob.status.is_(None),
|
|
182
|
+
)
|
|
183
|
+
)
|
|
112
184
|
.limit(1)
|
|
113
185
|
.order_by(QueuedJob.submitted_at)
|
|
114
186
|
)
|
|
@@ -119,6 +191,7 @@ class DatastoreSqlite(Datastore):
|
|
|
119
191
|
queued_job_uuid=row.id,
|
|
120
192
|
job_ref_name=row.job_ref_name,
|
|
121
193
|
num_attempts=row.num_attempts,
|
|
194
|
+
status=row.status or queued_job_t.JobStatus.QUEUED,
|
|
122
195
|
submitted_at=row.submitted_at,
|
|
123
196
|
payload=parsed_payload,
|
|
124
197
|
)
|
|
@@ -127,13 +200,23 @@ class DatastoreSqlite(Datastore):
|
|
|
127
200
|
|
|
128
201
|
def load_job_queue(self) -> list[queued_job_t.QueuedJob]:
|
|
129
202
|
with self.session_maker() as session:
|
|
130
|
-
select_stmt =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
203
|
+
select_stmt = (
|
|
204
|
+
select(
|
|
205
|
+
QueuedJob.id,
|
|
206
|
+
QueuedJob.payload,
|
|
207
|
+
QueuedJob.num_attempts,
|
|
208
|
+
QueuedJob.job_ref_name,
|
|
209
|
+
QueuedJob.status,
|
|
210
|
+
QueuedJob.submitted_at,
|
|
211
|
+
)
|
|
212
|
+
.filter(
|
|
213
|
+
or_(
|
|
214
|
+
QueuedJob.status == queued_job_t.JobStatus.QUEUED,
|
|
215
|
+
QueuedJob.status.is_(None),
|
|
216
|
+
)
|
|
217
|
+
)
|
|
218
|
+
.order_by(QueuedJob.submitted_at)
|
|
219
|
+
)
|
|
137
220
|
|
|
138
221
|
queued_jobs: list[queued_job_t.QueuedJob] = []
|
|
139
222
|
for row in session.execute(select_stmt):
|
|
@@ -143,9 +226,25 @@ class DatastoreSqlite(Datastore):
|
|
|
143
226
|
queued_job_uuid=row.id,
|
|
144
227
|
job_ref_name=row.job_ref_name,
|
|
145
228
|
num_attempts=row.num_attempts,
|
|
229
|
+
status=row.status or queued_job_t.JobStatus.QUEUED,
|
|
146
230
|
submitted_at=row.submitted_at,
|
|
147
231
|
payload=parsed_payload,
|
|
148
232
|
)
|
|
149
233
|
)
|
|
150
234
|
|
|
151
235
|
return queued_jobs
|
|
236
|
+
|
|
237
|
+
def vaccuum_queued_jobs(self) -> None:
|
|
238
|
+
with self.session_maker() as session:
|
|
239
|
+
delete_stmt = (
|
|
240
|
+
delete(QueuedJob)
|
|
241
|
+
.filter(QueuedJob.status == queued_job_t.JobStatus.QUEUED)
|
|
242
|
+
.filter(
|
|
243
|
+
QueuedJob.submitted_at
|
|
244
|
+
<= (
|
|
245
|
+
datetime.datetime.now(UTC)
|
|
246
|
+
- datetime.timedelta(days=MAX_QUEUE_WINDOW_DAYS)
|
|
247
|
+
)
|
|
248
|
+
)
|
|
249
|
+
)
|
|
250
|
+
session.execute(delete_stmt)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from sqlalchemy import JSON, BigInteger, Column, DateTime, Text
|
|
1
|
+
from sqlalchemy import JSON, BigInteger, Column, DateTime, Enum, Text
|
|
2
2
|
from sqlalchemy.orm import declarative_base
|
|
3
3
|
from sqlalchemy.sql import func
|
|
4
4
|
|
|
5
|
+
from uncountable.types import queued_job_t
|
|
6
|
+
|
|
5
7
|
Base = declarative_base()
|
|
6
8
|
|
|
7
9
|
|
|
@@ -15,3 +17,8 @@ class QueuedJob(Base):
|
|
|
15
17
|
)
|
|
16
18
|
payload = Column(JSON, nullable=False)
|
|
17
19
|
num_attempts = Column(BigInteger, nullable=False, default=0, server_default="0")
|
|
20
|
+
status = Column(
|
|
21
|
+
Enum(queued_job_t.JobStatus, length=None),
|
|
22
|
+
default=queued_job_t.JobStatus.QUEUED,
|
|
23
|
+
nullable=True,
|
|
24
|
+
)
|
|
@@ -10,8 +10,13 @@ from uncountable.integration.queue_runner.command_server import (
|
|
|
10
10
|
CommandEnqueueJob,
|
|
11
11
|
CommandEnqueueJobResponse,
|
|
12
12
|
CommandQueue,
|
|
13
|
+
CommandRetryJob,
|
|
14
|
+
CommandRetryJobResponse,
|
|
13
15
|
CommandTask,
|
|
14
16
|
)
|
|
17
|
+
from uncountable.integration.queue_runner.command_server.types import (
|
|
18
|
+
CommandVaccuumQueuedJobs,
|
|
19
|
+
)
|
|
15
20
|
from uncountable.integration.queue_runner.datastore import DatastoreSqlite
|
|
16
21
|
from uncountable.integration.queue_runner.datastore.interface import Datastore
|
|
17
22
|
from uncountable.integration.queue_runner.worker import Worker
|
|
@@ -99,7 +104,9 @@ async def start_scheduler(
|
|
|
99
104
|
worker = job_worker_lookup[queued_job.job_ref_name]
|
|
100
105
|
except KeyError as e:
|
|
101
106
|
logger.log_exception(e)
|
|
102
|
-
datastore.
|
|
107
|
+
datastore.update_job_status(
|
|
108
|
+
queued_job.queued_job_uuid, queued_job_t.JobStatus.FAILED
|
|
109
|
+
)
|
|
103
110
|
return
|
|
104
111
|
await worker.listen_queue.put(queued_job)
|
|
105
112
|
|
|
@@ -135,6 +142,25 @@ async def start_scheduler(
|
|
|
135
142
|
CommandEnqueueJobResponse(queued_job_uuid=queued_job_uuid)
|
|
136
143
|
)
|
|
137
144
|
|
|
145
|
+
async def _handle_retry_job_command(command: CommandRetryJob) -> None:
|
|
146
|
+
queued_job = datastore.retry_job(command.queued_job_uuid)
|
|
147
|
+
if queued_job is None:
|
|
148
|
+
await command.response_queue.put(
|
|
149
|
+
CommandRetryJobResponse(queued_job_uuid=None)
|
|
150
|
+
)
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
await enqueue_queued_job(queued_job)
|
|
154
|
+
await command.response_queue.put(
|
|
155
|
+
CommandRetryJobResponse(queued_job_uuid=queued_job.queued_job_uuid)
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def _handle_vaccuum_queued_jobs_command(
|
|
159
|
+
command: CommandVaccuumQueuedJobs,
|
|
160
|
+
) -> None:
|
|
161
|
+
logger.log_info("Vaccuuming queued jobs...")
|
|
162
|
+
datastore.vaccuum_queued_jobs()
|
|
163
|
+
|
|
138
164
|
for queued_job in queued_jobs:
|
|
139
165
|
await enqueue_queued_job(queued_job)
|
|
140
166
|
|
|
@@ -151,10 +177,24 @@ async def start_scheduler(
|
|
|
151
177
|
match command:
|
|
152
178
|
case CommandEnqueueJob():
|
|
153
179
|
await _handle_enqueue_job_command(command=command)
|
|
180
|
+
case CommandRetryJob():
|
|
181
|
+
await _handle_retry_job_command(command=command)
|
|
182
|
+
case CommandVaccuumQueuedJobs():
|
|
183
|
+
_handle_vaccuum_queued_jobs_command(command=command)
|
|
154
184
|
case _:
|
|
155
185
|
typing.assert_never(command)
|
|
156
186
|
command_task = asyncio.create_task(command_queue.get())
|
|
157
187
|
elif task == result_task:
|
|
158
188
|
queued_job_result = result_task.result()
|
|
159
|
-
|
|
189
|
+
match queued_job_result.job_result.success:
|
|
190
|
+
case True:
|
|
191
|
+
datastore.update_job_status(
|
|
192
|
+
queued_job_result.queued_job_uuid,
|
|
193
|
+
queued_job_t.JobStatus.SUCCESS,
|
|
194
|
+
)
|
|
195
|
+
case False:
|
|
196
|
+
datastore.update_job_status(
|
|
197
|
+
queued_job_result.queued_job_uuid,
|
|
198
|
+
queued_job_t.JobStatus.FAILED,
|
|
199
|
+
)
|
|
160
200
|
result_task = asyncio.create_task(result_queue.get())
|
|
@@ -103,13 +103,13 @@ def run_queued_job(
|
|
|
103
103
|
profile_metadata=job_details.profile_metadata,
|
|
104
104
|
logger=job_logger,
|
|
105
105
|
payload=payload,
|
|
106
|
+
job_uuid=queued_job.queued_job_uuid,
|
|
106
107
|
)
|
|
107
108
|
|
|
108
109
|
return execute_job(
|
|
109
110
|
args=args,
|
|
110
111
|
profile_metadata=job_details.profile_metadata,
|
|
111
112
|
job_definition=job_details.job_definition,
|
|
112
|
-
job_uuid=queued_job.queued_job_uuid,
|
|
113
113
|
)
|
|
114
114
|
except BaseException as e:
|
|
115
115
|
job_logger.log_exception(e)
|