indexify 0.3.4__py3-none-any.whl → 0.3.6__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.
- indexify/cli/cli.py +6 -4
- indexify/executor/downloader.py +2 -3
- indexify/executor/executor.py +8 -7
- indexify/executor/function_executor/function_executor.py +3 -4
- indexify/executor/function_executor/health_checker.py +4 -4
- indexify/executor/function_executor/invocation_state_client.py +3 -4
- indexify/{function_executor/proto/configuration.py → executor/function_executor/server/client_configuration.py} +7 -11
- indexify/executor/function_executor/server/subprocess_function_executor_server.py +1 -2
- indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py +0 -5
- indexify/executor/function_executor/single_task_runner.py +2 -4
- indexify/executor/function_executor/task_input.py +1 -1
- indexify/executor/function_executor/task_output.py +1 -1
- indexify/executor/task_fetcher.py +5 -5
- indexify/executor/task_reporter.py +3 -4
- {indexify-0.3.4.dist-info → indexify-0.3.6.dist-info}/METADATA +3 -4
- indexify-0.3.6.dist-info/RECORD +25 -0
- indexify-0.3.6.dist-info/entry_points.txt +3 -0
- indexify/function_executor/README.md +0 -18
- indexify/function_executor/handlers/run_function/function_inputs_loader.py +0 -53
- indexify/function_executor/handlers/run_function/handler.py +0 -126
- indexify/function_executor/handlers/run_function/request_validator.py +0 -26
- indexify/function_executor/handlers/run_function/response_helper.py +0 -96
- indexify/function_executor/initialize_request_validator.py +0 -21
- indexify/function_executor/invocation_state/invocation_state_proxy_server.py +0 -170
- indexify/function_executor/invocation_state/proxied_invocation_state.py +0 -22
- indexify/function_executor/invocation_state/response_validator.py +0 -29
- indexify/function_executor/main.py +0 -50
- indexify/function_executor/proto/function_executor.proto +0 -130
- indexify/function_executor/proto/function_executor_pb2.py +0 -69
- indexify/function_executor/proto/function_executor_pb2.pyi +0 -225
- indexify/function_executor/proto/function_executor_pb2_grpc.py +0 -260
- indexify/function_executor/proto/message_validator.py +0 -38
- indexify/function_executor/server.py +0 -29
- indexify/function_executor/service.py +0 -133
- indexify/utils/README.md +0 -3
- indexify/utils/http_client.py +0 -88
- indexify/utils/logging.py +0 -66
- indexify-0.3.4.dist-info/RECORD +0 -45
- indexify-0.3.4.dist-info/entry_points.txt +0 -4
- {indexify-0.3.4.dist-info → indexify-0.3.6.dist-info}/WHEEL +0 -0
@@ -1,225 +0,0 @@
|
|
1
|
-
from typing import ClassVar as _ClassVar
|
2
|
-
from typing import Iterable as _Iterable
|
3
|
-
from typing import Mapping as _Mapping
|
4
|
-
from typing import Optional as _Optional
|
5
|
-
from typing import Union as _Union
|
6
|
-
|
7
|
-
from google.protobuf import descriptor as _descriptor
|
8
|
-
from google.protobuf import message as _message
|
9
|
-
from google.protobuf.internal import containers as _containers
|
10
|
-
|
11
|
-
DESCRIPTOR: _descriptor.FileDescriptor
|
12
|
-
|
13
|
-
class SerializedObject(_message.Message):
|
14
|
-
__slots__ = ("bytes", "string", "content_type")
|
15
|
-
BYTES_FIELD_NUMBER: _ClassVar[int]
|
16
|
-
STRING_FIELD_NUMBER: _ClassVar[int]
|
17
|
-
CONTENT_TYPE_FIELD_NUMBER: _ClassVar[int]
|
18
|
-
bytes: bytes
|
19
|
-
string: str
|
20
|
-
content_type: str
|
21
|
-
def __init__(
|
22
|
-
self,
|
23
|
-
bytes: _Optional[bytes] = ...,
|
24
|
-
string: _Optional[str] = ...,
|
25
|
-
content_type: _Optional[str] = ...,
|
26
|
-
) -> None: ...
|
27
|
-
|
28
|
-
class InitializeRequest(_message.Message):
|
29
|
-
__slots__ = ("namespace", "graph_name", "graph_version", "function_name", "graph")
|
30
|
-
NAMESPACE_FIELD_NUMBER: _ClassVar[int]
|
31
|
-
GRAPH_NAME_FIELD_NUMBER: _ClassVar[int]
|
32
|
-
GRAPH_VERSION_FIELD_NUMBER: _ClassVar[int]
|
33
|
-
FUNCTION_NAME_FIELD_NUMBER: _ClassVar[int]
|
34
|
-
GRAPH_FIELD_NUMBER: _ClassVar[int]
|
35
|
-
namespace: str
|
36
|
-
graph_name: str
|
37
|
-
graph_version: str
|
38
|
-
function_name: str
|
39
|
-
graph: SerializedObject
|
40
|
-
def __init__(
|
41
|
-
self,
|
42
|
-
namespace: _Optional[str] = ...,
|
43
|
-
graph_name: _Optional[str] = ...,
|
44
|
-
graph_version: _Optional[str] = ...,
|
45
|
-
function_name: _Optional[str] = ...,
|
46
|
-
graph: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
47
|
-
) -> None: ...
|
48
|
-
|
49
|
-
class InitializeResponse(_message.Message):
|
50
|
-
__slots__ = ("success", "customer_error")
|
51
|
-
SUCCESS_FIELD_NUMBER: _ClassVar[int]
|
52
|
-
CUSTOMER_ERROR_FIELD_NUMBER: _ClassVar[int]
|
53
|
-
success: bool
|
54
|
-
customer_error: str
|
55
|
-
def __init__(
|
56
|
-
self, success: bool = ..., customer_error: _Optional[str] = ...
|
57
|
-
) -> None: ...
|
58
|
-
|
59
|
-
class SetInvocationStateRequest(_message.Message):
|
60
|
-
__slots__ = ("key", "value")
|
61
|
-
KEY_FIELD_NUMBER: _ClassVar[int]
|
62
|
-
VALUE_FIELD_NUMBER: _ClassVar[int]
|
63
|
-
key: str
|
64
|
-
value: SerializedObject
|
65
|
-
def __init__(
|
66
|
-
self,
|
67
|
-
key: _Optional[str] = ...,
|
68
|
-
value: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
69
|
-
) -> None: ...
|
70
|
-
|
71
|
-
class SetInvocationStateResponse(_message.Message):
|
72
|
-
__slots__ = ()
|
73
|
-
def __init__(self) -> None: ...
|
74
|
-
|
75
|
-
class GetInvocationStateRequest(_message.Message):
|
76
|
-
__slots__ = ("key",)
|
77
|
-
KEY_FIELD_NUMBER: _ClassVar[int]
|
78
|
-
key: str
|
79
|
-
def __init__(self, key: _Optional[str] = ...) -> None: ...
|
80
|
-
|
81
|
-
class GetInvocationStateResponse(_message.Message):
|
82
|
-
__slots__ = ("key", "value")
|
83
|
-
KEY_FIELD_NUMBER: _ClassVar[int]
|
84
|
-
VALUE_FIELD_NUMBER: _ClassVar[int]
|
85
|
-
key: str
|
86
|
-
value: SerializedObject
|
87
|
-
def __init__(
|
88
|
-
self,
|
89
|
-
key: _Optional[str] = ...,
|
90
|
-
value: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
91
|
-
) -> None: ...
|
92
|
-
|
93
|
-
class InvocationStateRequest(_message.Message):
|
94
|
-
__slots__ = ("request_id", "task_id", "set", "get")
|
95
|
-
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
|
96
|
-
TASK_ID_FIELD_NUMBER: _ClassVar[int]
|
97
|
-
SET_FIELD_NUMBER: _ClassVar[int]
|
98
|
-
GET_FIELD_NUMBER: _ClassVar[int]
|
99
|
-
request_id: str
|
100
|
-
task_id: str
|
101
|
-
set: SetInvocationStateRequest
|
102
|
-
get: GetInvocationStateRequest
|
103
|
-
def __init__(
|
104
|
-
self,
|
105
|
-
request_id: _Optional[str] = ...,
|
106
|
-
task_id: _Optional[str] = ...,
|
107
|
-
set: _Optional[_Union[SetInvocationStateRequest, _Mapping]] = ...,
|
108
|
-
get: _Optional[_Union[GetInvocationStateRequest, _Mapping]] = ...,
|
109
|
-
) -> None: ...
|
110
|
-
|
111
|
-
class InvocationStateResponse(_message.Message):
|
112
|
-
__slots__ = ("request_id", "success", "set", "get")
|
113
|
-
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
|
114
|
-
SUCCESS_FIELD_NUMBER: _ClassVar[int]
|
115
|
-
SET_FIELD_NUMBER: _ClassVar[int]
|
116
|
-
GET_FIELD_NUMBER: _ClassVar[int]
|
117
|
-
request_id: str
|
118
|
-
success: bool
|
119
|
-
set: SetInvocationStateResponse
|
120
|
-
get: GetInvocationStateResponse
|
121
|
-
def __init__(
|
122
|
-
self,
|
123
|
-
request_id: _Optional[str] = ...,
|
124
|
-
success: bool = ...,
|
125
|
-
set: _Optional[_Union[SetInvocationStateResponse, _Mapping]] = ...,
|
126
|
-
get: _Optional[_Union[GetInvocationStateResponse, _Mapping]] = ...,
|
127
|
-
) -> None: ...
|
128
|
-
|
129
|
-
class FunctionOutput(_message.Message):
|
130
|
-
__slots__ = ("outputs",)
|
131
|
-
OUTPUTS_FIELD_NUMBER: _ClassVar[int]
|
132
|
-
outputs: _containers.RepeatedCompositeFieldContainer[SerializedObject]
|
133
|
-
def __init__(
|
134
|
-
self, outputs: _Optional[_Iterable[_Union[SerializedObject, _Mapping]]] = ...
|
135
|
-
) -> None: ...
|
136
|
-
|
137
|
-
class RouterOutput(_message.Message):
|
138
|
-
__slots__ = ("edges",)
|
139
|
-
EDGES_FIELD_NUMBER: _ClassVar[int]
|
140
|
-
edges: _containers.RepeatedScalarFieldContainer[str]
|
141
|
-
def __init__(self, edges: _Optional[_Iterable[str]] = ...) -> None: ...
|
142
|
-
|
143
|
-
class RunTaskRequest(_message.Message):
|
144
|
-
__slots__ = (
|
145
|
-
"namespace",
|
146
|
-
"graph_name",
|
147
|
-
"graph_version",
|
148
|
-
"function_name",
|
149
|
-
"graph_invocation_id",
|
150
|
-
"task_id",
|
151
|
-
"function_input",
|
152
|
-
"function_init_value",
|
153
|
-
)
|
154
|
-
NAMESPACE_FIELD_NUMBER: _ClassVar[int]
|
155
|
-
GRAPH_NAME_FIELD_NUMBER: _ClassVar[int]
|
156
|
-
GRAPH_VERSION_FIELD_NUMBER: _ClassVar[int]
|
157
|
-
FUNCTION_NAME_FIELD_NUMBER: _ClassVar[int]
|
158
|
-
GRAPH_INVOCATION_ID_FIELD_NUMBER: _ClassVar[int]
|
159
|
-
TASK_ID_FIELD_NUMBER: _ClassVar[int]
|
160
|
-
FUNCTION_INPUT_FIELD_NUMBER: _ClassVar[int]
|
161
|
-
FUNCTION_INIT_VALUE_FIELD_NUMBER: _ClassVar[int]
|
162
|
-
namespace: str
|
163
|
-
graph_name: str
|
164
|
-
graph_version: str
|
165
|
-
function_name: str
|
166
|
-
graph_invocation_id: str
|
167
|
-
task_id: str
|
168
|
-
function_input: SerializedObject
|
169
|
-
function_init_value: SerializedObject
|
170
|
-
def __init__(
|
171
|
-
self,
|
172
|
-
namespace: _Optional[str] = ...,
|
173
|
-
graph_name: _Optional[str] = ...,
|
174
|
-
graph_version: _Optional[str] = ...,
|
175
|
-
function_name: _Optional[str] = ...,
|
176
|
-
graph_invocation_id: _Optional[str] = ...,
|
177
|
-
task_id: _Optional[str] = ...,
|
178
|
-
function_input: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
179
|
-
function_init_value: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
180
|
-
) -> None: ...
|
181
|
-
|
182
|
-
class RunTaskResponse(_message.Message):
|
183
|
-
__slots__ = (
|
184
|
-
"task_id",
|
185
|
-
"function_output",
|
186
|
-
"router_output",
|
187
|
-
"stdout",
|
188
|
-
"stderr",
|
189
|
-
"is_reducer",
|
190
|
-
"success",
|
191
|
-
)
|
192
|
-
TASK_ID_FIELD_NUMBER: _ClassVar[int]
|
193
|
-
FUNCTION_OUTPUT_FIELD_NUMBER: _ClassVar[int]
|
194
|
-
ROUTER_OUTPUT_FIELD_NUMBER: _ClassVar[int]
|
195
|
-
STDOUT_FIELD_NUMBER: _ClassVar[int]
|
196
|
-
STDERR_FIELD_NUMBER: _ClassVar[int]
|
197
|
-
IS_REDUCER_FIELD_NUMBER: _ClassVar[int]
|
198
|
-
SUCCESS_FIELD_NUMBER: _ClassVar[int]
|
199
|
-
task_id: str
|
200
|
-
function_output: FunctionOutput
|
201
|
-
router_output: RouterOutput
|
202
|
-
stdout: str
|
203
|
-
stderr: str
|
204
|
-
is_reducer: bool
|
205
|
-
success: bool
|
206
|
-
def __init__(
|
207
|
-
self,
|
208
|
-
task_id: _Optional[str] = ...,
|
209
|
-
function_output: _Optional[_Union[FunctionOutput, _Mapping]] = ...,
|
210
|
-
router_output: _Optional[_Union[RouterOutput, _Mapping]] = ...,
|
211
|
-
stdout: _Optional[str] = ...,
|
212
|
-
stderr: _Optional[str] = ...,
|
213
|
-
is_reducer: bool = ...,
|
214
|
-
success: bool = ...,
|
215
|
-
) -> None: ...
|
216
|
-
|
217
|
-
class HealthCheckRequest(_message.Message):
|
218
|
-
__slots__ = ()
|
219
|
-
def __init__(self) -> None: ...
|
220
|
-
|
221
|
-
class HealthCheckResponse(_message.Message):
|
222
|
-
__slots__ = ("healthy",)
|
223
|
-
HEALTHY_FIELD_NUMBER: _ClassVar[int]
|
224
|
-
healthy: bool
|
225
|
-
def __init__(self, healthy: bool = ...) -> None: ...
|
@@ -1,260 +0,0 @@
|
|
1
|
-
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
2
|
-
"""Client and server classes corresponding to protobuf-defined services."""
|
3
|
-
import warnings
|
4
|
-
|
5
|
-
import grpc
|
6
|
-
|
7
|
-
from indexify.function_executor.proto import (
|
8
|
-
function_executor_pb2 as indexify_dot_function__executor_dot_proto_dot_function__executor__pb2,
|
9
|
-
)
|
10
|
-
|
11
|
-
GRPC_GENERATED_VERSION = "1.68.1"
|
12
|
-
GRPC_VERSION = grpc.__version__
|
13
|
-
_version_not_supported = False
|
14
|
-
|
15
|
-
try:
|
16
|
-
from grpc._utilities import first_version_is_lower
|
17
|
-
|
18
|
-
_version_not_supported = first_version_is_lower(
|
19
|
-
GRPC_VERSION, GRPC_GENERATED_VERSION
|
20
|
-
)
|
21
|
-
except ImportError:
|
22
|
-
_version_not_supported = True
|
23
|
-
|
24
|
-
if _version_not_supported:
|
25
|
-
raise RuntimeError(
|
26
|
-
f"The grpc package installed is at version {GRPC_VERSION},"
|
27
|
-
+ f" but the generated code in indexify/function_executor/proto/function_executor_pb2_grpc.py depends on"
|
28
|
-
+ f" grpcio>={GRPC_GENERATED_VERSION}."
|
29
|
-
+ f" Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}"
|
30
|
-
+ f" or downgrade your generated code using grpcio-tools<={GRPC_VERSION}."
|
31
|
-
)
|
32
|
-
|
33
|
-
|
34
|
-
class FunctionExecutorStub(object):
|
35
|
-
"""Missing associated documentation comment in .proto file."""
|
36
|
-
|
37
|
-
def __init__(self, channel):
|
38
|
-
"""Constructor.
|
39
|
-
|
40
|
-
Args:
|
41
|
-
channel: A grpc.Channel.
|
42
|
-
"""
|
43
|
-
self.initialize = channel.unary_unary(
|
44
|
-
"/function_executor_service.FunctionExecutor/initialize",
|
45
|
-
request_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeRequest.SerializeToString,
|
46
|
-
response_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeResponse.FromString,
|
47
|
-
_registered_method=True,
|
48
|
-
)
|
49
|
-
self.initialize_invocation_state_server = channel.stream_stream(
|
50
|
-
"/function_executor_service.FunctionExecutor/initialize_invocation_state_server",
|
51
|
-
request_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateResponse.SerializeToString,
|
52
|
-
response_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateRequest.FromString,
|
53
|
-
_registered_method=True,
|
54
|
-
)
|
55
|
-
self.run_task = channel.unary_unary(
|
56
|
-
"/function_executor_service.FunctionExecutor/run_task",
|
57
|
-
request_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskRequest.SerializeToString,
|
58
|
-
response_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskResponse.FromString,
|
59
|
-
_registered_method=True,
|
60
|
-
)
|
61
|
-
self.check_health = channel.unary_unary(
|
62
|
-
"/function_executor_service.FunctionExecutor/check_health",
|
63
|
-
request_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckRequest.SerializeToString,
|
64
|
-
response_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckResponse.FromString,
|
65
|
-
_registered_method=True,
|
66
|
-
)
|
67
|
-
|
68
|
-
|
69
|
-
class FunctionExecutorServicer(object):
|
70
|
-
"""Missing associated documentation comment in .proto file."""
|
71
|
-
|
72
|
-
def initialize(self, request, context):
|
73
|
-
"""Initializes the Function Executor to run tasks
|
74
|
-
for a particular function. This method is called only
|
75
|
-
once per Function Executor as it can only run a single function.
|
76
|
-
It should be called before calling RunTask for the function.
|
77
|
-
"""
|
78
|
-
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
79
|
-
context.set_details("Method not implemented!")
|
80
|
-
raise NotImplementedError("Method not implemented!")
|
81
|
-
|
82
|
-
def initialize_invocation_state_server(self, request_iterator, context):
|
83
|
-
"""Initializes a server that sends requests to the client to perform actions on
|
84
|
-
a task's graph invocation state. This method is called only once per Function Executor
|
85
|
-
It should be called before calling RunTask for the function.
|
86
|
-
"""
|
87
|
-
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
88
|
-
context.set_details("Method not implemented!")
|
89
|
-
raise NotImplementedError("Method not implemented!")
|
90
|
-
|
91
|
-
def run_task(self, request, context):
|
92
|
-
"""Executes the task defined in the request.
|
93
|
-
Multiple tasks can be running in parallel.
|
94
|
-
"""
|
95
|
-
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
96
|
-
context.set_details("Method not implemented!")
|
97
|
-
raise NotImplementedError("Method not implemented!")
|
98
|
-
|
99
|
-
def check_health(self, request, context):
|
100
|
-
"""Health check method to check if the Function Executor is healthy."""
|
101
|
-
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
102
|
-
context.set_details("Method not implemented!")
|
103
|
-
raise NotImplementedError("Method not implemented!")
|
104
|
-
|
105
|
-
|
106
|
-
def add_FunctionExecutorServicer_to_server(servicer, server):
|
107
|
-
rpc_method_handlers = {
|
108
|
-
"initialize": grpc.unary_unary_rpc_method_handler(
|
109
|
-
servicer.initialize,
|
110
|
-
request_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeRequest.FromString,
|
111
|
-
response_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeResponse.SerializeToString,
|
112
|
-
),
|
113
|
-
"initialize_invocation_state_server": grpc.stream_stream_rpc_method_handler(
|
114
|
-
servicer.initialize_invocation_state_server,
|
115
|
-
request_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateResponse.FromString,
|
116
|
-
response_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateRequest.SerializeToString,
|
117
|
-
),
|
118
|
-
"run_task": grpc.unary_unary_rpc_method_handler(
|
119
|
-
servicer.run_task,
|
120
|
-
request_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskRequest.FromString,
|
121
|
-
response_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskResponse.SerializeToString,
|
122
|
-
),
|
123
|
-
"check_health": grpc.unary_unary_rpc_method_handler(
|
124
|
-
servicer.check_health,
|
125
|
-
request_deserializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckRequest.FromString,
|
126
|
-
response_serializer=indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckResponse.SerializeToString,
|
127
|
-
),
|
128
|
-
}
|
129
|
-
generic_handler = grpc.method_handlers_generic_handler(
|
130
|
-
"function_executor_service.FunctionExecutor", rpc_method_handlers
|
131
|
-
)
|
132
|
-
server.add_generic_rpc_handlers((generic_handler,))
|
133
|
-
server.add_registered_method_handlers(
|
134
|
-
"function_executor_service.FunctionExecutor", rpc_method_handlers
|
135
|
-
)
|
136
|
-
|
137
|
-
|
138
|
-
# This class is part of an EXPERIMENTAL API.
|
139
|
-
class FunctionExecutor(object):
|
140
|
-
"""Missing associated documentation comment in .proto file."""
|
141
|
-
|
142
|
-
@staticmethod
|
143
|
-
def initialize(
|
144
|
-
request,
|
145
|
-
target,
|
146
|
-
options=(),
|
147
|
-
channel_credentials=None,
|
148
|
-
call_credentials=None,
|
149
|
-
insecure=False,
|
150
|
-
compression=None,
|
151
|
-
wait_for_ready=None,
|
152
|
-
timeout=None,
|
153
|
-
metadata=None,
|
154
|
-
):
|
155
|
-
return grpc.experimental.unary_unary(
|
156
|
-
request,
|
157
|
-
target,
|
158
|
-
"/function_executor_service.FunctionExecutor/initialize",
|
159
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeRequest.SerializeToString,
|
160
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InitializeResponse.FromString,
|
161
|
-
options,
|
162
|
-
channel_credentials,
|
163
|
-
insecure,
|
164
|
-
call_credentials,
|
165
|
-
compression,
|
166
|
-
wait_for_ready,
|
167
|
-
timeout,
|
168
|
-
metadata,
|
169
|
-
_registered_method=True,
|
170
|
-
)
|
171
|
-
|
172
|
-
@staticmethod
|
173
|
-
def initialize_invocation_state_server(
|
174
|
-
request_iterator,
|
175
|
-
target,
|
176
|
-
options=(),
|
177
|
-
channel_credentials=None,
|
178
|
-
call_credentials=None,
|
179
|
-
insecure=False,
|
180
|
-
compression=None,
|
181
|
-
wait_for_ready=None,
|
182
|
-
timeout=None,
|
183
|
-
metadata=None,
|
184
|
-
):
|
185
|
-
return grpc.experimental.stream_stream(
|
186
|
-
request_iterator,
|
187
|
-
target,
|
188
|
-
"/function_executor_service.FunctionExecutor/initialize_invocation_state_server",
|
189
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateResponse.SerializeToString,
|
190
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.InvocationStateRequest.FromString,
|
191
|
-
options,
|
192
|
-
channel_credentials,
|
193
|
-
insecure,
|
194
|
-
call_credentials,
|
195
|
-
compression,
|
196
|
-
wait_for_ready,
|
197
|
-
timeout,
|
198
|
-
metadata,
|
199
|
-
_registered_method=True,
|
200
|
-
)
|
201
|
-
|
202
|
-
@staticmethod
|
203
|
-
def run_task(
|
204
|
-
request,
|
205
|
-
target,
|
206
|
-
options=(),
|
207
|
-
channel_credentials=None,
|
208
|
-
call_credentials=None,
|
209
|
-
insecure=False,
|
210
|
-
compression=None,
|
211
|
-
wait_for_ready=None,
|
212
|
-
timeout=None,
|
213
|
-
metadata=None,
|
214
|
-
):
|
215
|
-
return grpc.experimental.unary_unary(
|
216
|
-
request,
|
217
|
-
target,
|
218
|
-
"/function_executor_service.FunctionExecutor/run_task",
|
219
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskRequest.SerializeToString,
|
220
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.RunTaskResponse.FromString,
|
221
|
-
options,
|
222
|
-
channel_credentials,
|
223
|
-
insecure,
|
224
|
-
call_credentials,
|
225
|
-
compression,
|
226
|
-
wait_for_ready,
|
227
|
-
timeout,
|
228
|
-
metadata,
|
229
|
-
_registered_method=True,
|
230
|
-
)
|
231
|
-
|
232
|
-
@staticmethod
|
233
|
-
def check_health(
|
234
|
-
request,
|
235
|
-
target,
|
236
|
-
options=(),
|
237
|
-
channel_credentials=None,
|
238
|
-
call_credentials=None,
|
239
|
-
insecure=False,
|
240
|
-
compression=None,
|
241
|
-
wait_for_ready=None,
|
242
|
-
timeout=None,
|
243
|
-
metadata=None,
|
244
|
-
):
|
245
|
-
return grpc.experimental.unary_unary(
|
246
|
-
request,
|
247
|
-
target,
|
248
|
-
"/function_executor_service.FunctionExecutor/check_health",
|
249
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckRequest.SerializeToString,
|
250
|
-
indexify_dot_function__executor_dot_proto_dot_function__executor__pb2.HealthCheckResponse.FromString,
|
251
|
-
options,
|
252
|
-
channel_credentials,
|
253
|
-
insecure,
|
254
|
-
call_credentials,
|
255
|
-
compression,
|
256
|
-
wait_for_ready,
|
257
|
-
timeout,
|
258
|
-
metadata,
|
259
|
-
_registered_method=True,
|
260
|
-
)
|
@@ -1,38 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
|
3
|
-
from .function_executor_pb2 import SerializedObject
|
4
|
-
|
5
|
-
|
6
|
-
class MessageValidator:
|
7
|
-
def __init__(self, message: Any):
|
8
|
-
self._message = message
|
9
|
-
|
10
|
-
def required_field(self, field_name: str) -> "MessageValidator":
|
11
|
-
if not self._message.HasField(field_name):
|
12
|
-
raise ValueError(
|
13
|
-
f"Field '{field_name}' is required in {type(self._message).__name__}"
|
14
|
-
)
|
15
|
-
return self
|
16
|
-
|
17
|
-
def required_serialized_object(self, field_name: str) -> "MessageValidator":
|
18
|
-
"""Validates the SerializedObject.
|
19
|
-
|
20
|
-
Raises: ValueError: If the SerializedObject is invalid or not present."""
|
21
|
-
self.required_field(field_name)
|
22
|
-
return self.optional_serialized_object(field_name)
|
23
|
-
|
24
|
-
def optional_serialized_object(self, field_name: str) -> "MessageValidator":
|
25
|
-
"""Validates the SerializedObject.
|
26
|
-
|
27
|
-
Raises: ValueError: If the SerializedObject is invalid."""
|
28
|
-
if not self._message.HasField(field_name):
|
29
|
-
return self
|
30
|
-
|
31
|
-
serializedObject: SerializedObject = getattr(self._message, field_name)
|
32
|
-
if not serializedObject.HasField("string") and not serializedObject.HasField(
|
33
|
-
"bytes"
|
34
|
-
):
|
35
|
-
raise ValueError("oneof 'data' is required in SerializedObject")
|
36
|
-
if not serializedObject.HasField("content_type"):
|
37
|
-
raise ValueError("Field 'content_type' is required in SerializedObject")
|
38
|
-
return self
|
@@ -1,29 +0,0 @@
|
|
1
|
-
from concurrent.futures import ThreadPoolExecutor
|
2
|
-
|
3
|
-
import grpc
|
4
|
-
|
5
|
-
from .proto.configuration import GRPC_SERVER_OPTIONS
|
6
|
-
from .proto.function_executor_pb2_grpc import add_FunctionExecutorServicer_to_server
|
7
|
-
from .service import Service
|
8
|
-
|
9
|
-
# Temporary limit until we have a better way to control this.
|
10
|
-
# This limits the number of concurrent tasks that Function Executor can run.
|
11
|
-
MAX_RPC_CONCURRENCY = 100
|
12
|
-
|
13
|
-
|
14
|
-
class Server:
|
15
|
-
def __init__(self, server_address: str, service: Service):
|
16
|
-
self._server_address: str = server_address
|
17
|
-
self._service: Service = service
|
18
|
-
|
19
|
-
def run(self):
|
20
|
-
"""Runs Function Executor Service at the configured address."""
|
21
|
-
server = grpc.server(
|
22
|
-
thread_pool=ThreadPoolExecutor(max_workers=MAX_RPC_CONCURRENCY),
|
23
|
-
maximum_concurrent_rpcs=MAX_RPC_CONCURRENCY,
|
24
|
-
options=GRPC_SERVER_OPTIONS,
|
25
|
-
)
|
26
|
-
add_FunctionExecutorServicer_to_server(self._service, server)
|
27
|
-
server.add_insecure_port(self._server_address)
|
28
|
-
server.start()
|
29
|
-
server.wait_for_termination()
|
@@ -1,133 +0,0 @@
|
|
1
|
-
from typing import Iterator, Optional, Union
|
2
|
-
|
3
|
-
import grpc
|
4
|
-
import structlog
|
5
|
-
from tensorlake.functions_sdk.functions import TensorlakeCompute
|
6
|
-
from tensorlake.functions_sdk.object_serializer import get_serializer
|
7
|
-
|
8
|
-
from .handlers.run_function.handler import Handler as RunTaskHandler
|
9
|
-
from .handlers.run_function.request_validator import (
|
10
|
-
RequestValidator as RunTaskRequestValidator,
|
11
|
-
)
|
12
|
-
from .initialize_request_validator import InitializeRequestValidator
|
13
|
-
from .invocation_state.invocation_state_proxy_server import InvocationStateProxyServer
|
14
|
-
from .invocation_state.proxied_invocation_state import ProxiedInvocationState
|
15
|
-
from .proto.function_executor_pb2 import (
|
16
|
-
HealthCheckRequest,
|
17
|
-
HealthCheckResponse,
|
18
|
-
InitializeRequest,
|
19
|
-
InitializeResponse,
|
20
|
-
InvocationStateResponse,
|
21
|
-
RunTaskRequest,
|
22
|
-
RunTaskResponse,
|
23
|
-
)
|
24
|
-
from .proto.function_executor_pb2_grpc import FunctionExecutorServicer
|
25
|
-
|
26
|
-
|
27
|
-
class Service(FunctionExecutorServicer):
|
28
|
-
def __init__(self):
|
29
|
-
self._logger = structlog.get_logger(module=__name__)
|
30
|
-
self._namespace: Optional[str] = None
|
31
|
-
self._graph_name: Optional[str] = None
|
32
|
-
self._graph_version: Optional[str] = None
|
33
|
-
self._function_name: Optional[str] = None
|
34
|
-
self._function: Optional[Union[TensorlakeCompute, TensorlakeCompute]] = None
|
35
|
-
self._invocation_state_proxy_server: Optional[InvocationStateProxyServer] = None
|
36
|
-
|
37
|
-
def initialize(
|
38
|
-
self, request: InitializeRequest, context: grpc.ServicerContext
|
39
|
-
) -> InitializeResponse:
|
40
|
-
request_validator: InitializeRequestValidator = InitializeRequestValidator(
|
41
|
-
request
|
42
|
-
)
|
43
|
-
request_validator.check()
|
44
|
-
|
45
|
-
self._namespace = request.namespace
|
46
|
-
self._graph_name = request.graph_name
|
47
|
-
self._graph_version = request.graph_version
|
48
|
-
self._function_name = request.function_name
|
49
|
-
# The function is only loaded once per Function Executor. It's important to use a single
|
50
|
-
# loaded function so all the tasks when executed are sharing the same memory. This allows
|
51
|
-
# implementing smart caching in customer code. E.g. load a model into GPU only once and
|
52
|
-
# share the model's file descriptor between all tasks or download function configuration
|
53
|
-
# only once.
|
54
|
-
self._logger = self._logger.bind(
|
55
|
-
namespace=request.namespace,
|
56
|
-
graph_name=request.graph_name,
|
57
|
-
graph_version=request.graph_version,
|
58
|
-
function_name=request.function_name,
|
59
|
-
)
|
60
|
-
graph_serializer = get_serializer(request.graph.content_type)
|
61
|
-
try:
|
62
|
-
# Process user controlled input in a try-except block to not treat errors here as our
|
63
|
-
# internal platform errors.
|
64
|
-
graph = graph_serializer.deserialize(request.graph.bytes)
|
65
|
-
self._function = graph_serializer.deserialize(graph[request.function_name])
|
66
|
-
except Exception as e:
|
67
|
-
return InitializeResponse(success=False, customer_error=str(e))
|
68
|
-
|
69
|
-
self._logger.info("initialized function executor service")
|
70
|
-
return InitializeResponse(success=True)
|
71
|
-
|
72
|
-
def initialize_invocation_state_server(
|
73
|
-
self,
|
74
|
-
client_responses: Iterator[InvocationStateResponse],
|
75
|
-
context: grpc.ServicerContext,
|
76
|
-
):
|
77
|
-
self._invocation_state_proxy_server = InvocationStateProxyServer(
|
78
|
-
client_responses, self._logger
|
79
|
-
)
|
80
|
-
self._logger.info("initialized invocation proxy server")
|
81
|
-
yield from self._invocation_state_proxy_server.run()
|
82
|
-
|
83
|
-
def run_task(
|
84
|
-
self, request: RunTaskRequest, context: grpc.ServicerContext
|
85
|
-
) -> RunTaskResponse:
|
86
|
-
# Customer function code never raises an exception because we catch all of them and add
|
87
|
-
# their details to the response. We can only get an exception here if our own code failed.
|
88
|
-
# If our code raises an exception the grpc framework converts it into GRPC_STATUS_UNKNOWN
|
89
|
-
# error with the exception message. Differentiating errors is not needed for now.
|
90
|
-
RunTaskRequestValidator(request=request).check()
|
91
|
-
self._check_task_routed_correctly(request)
|
92
|
-
|
93
|
-
return RunTaskHandler(
|
94
|
-
request=request,
|
95
|
-
graph_name=self._graph_name,
|
96
|
-
graph_version=self._graph_version,
|
97
|
-
function_name=self._function_name,
|
98
|
-
function=self._function,
|
99
|
-
invocation_state=ProxiedInvocationState(
|
100
|
-
request.task_id, self._invocation_state_proxy_server
|
101
|
-
),
|
102
|
-
logger=self._logger,
|
103
|
-
).run()
|
104
|
-
|
105
|
-
def _check_task_routed_correctly(self, request: RunTaskRequest):
|
106
|
-
# Fail with internal error as this happened due to wrong task routing to this Server.
|
107
|
-
# If we run the wrongly routed task then it can steal data from this Server if it belongs
|
108
|
-
# to a different customer.
|
109
|
-
if request.namespace != self._namespace:
|
110
|
-
raise ValueError(
|
111
|
-
f"This Function Executor is not initialized for this namespace {request.namespace}"
|
112
|
-
)
|
113
|
-
if request.graph_name != self._graph_name:
|
114
|
-
raise ValueError(
|
115
|
-
f"This Function Executor is not initialized for this graph_name {request.graph_name}"
|
116
|
-
)
|
117
|
-
if request.graph_version != self._graph_version:
|
118
|
-
raise ValueError(
|
119
|
-
f"This Function Executor is not initialized for this graph_version {request.graph_version}"
|
120
|
-
)
|
121
|
-
if request.function_name != self._function_name:
|
122
|
-
raise ValueError(
|
123
|
-
f"This Function Executor is not initialized for this function_name {request.function_name}"
|
124
|
-
)
|
125
|
-
|
126
|
-
def check_health(
|
127
|
-
self, request: HealthCheckRequest, context: grpc.ServicerContext
|
128
|
-
) -> HealthCheckResponse:
|
129
|
-
# This health check validates that the Server:
|
130
|
-
# - Has its process alive (not exited).
|
131
|
-
# - Didn't exhaust its thread pool.
|
132
|
-
# - Is able to communicate over its server socket.
|
133
|
-
return HealthCheckResponse(healthy=True)
|
indexify/utils/README.md
DELETED