indexify 0.2.47__py3-none-any.whl → 0.3.0__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.py → cli/cli.py} +75 -82
- indexify/executor/README.md +35 -0
- indexify/executor/api_objects.py +9 -3
- indexify/executor/downloader.py +5 -5
- indexify/executor/executor.py +35 -22
- indexify/executor/function_executor/function_executor.py +14 -3
- indexify/executor/function_executor/function_executor_state.py +13 -10
- indexify/executor/function_executor/invocation_state_client.py +2 -1
- indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py +22 -10
- indexify/executor/function_executor/single_task_runner.py +43 -26
- indexify/executor/function_executor/task_input.py +1 -3
- indexify/executor/task_fetcher.py +5 -7
- indexify/executor/task_reporter.py +3 -5
- indexify/executor/task_runner.py +30 -23
- indexify/function_executor/README.md +18 -0
- indexify/function_executor/handlers/run_function/function_inputs_loader.py +13 -14
- indexify/function_executor/handlers/run_function/handler.py +16 -40
- indexify/function_executor/handlers/run_function/request_validator.py +7 -5
- indexify/function_executor/handlers/run_function/response_helper.py +6 -8
- indexify/function_executor/initialize_request_validator.py +1 -2
- indexify/function_executor/invocation_state/invocation_state_proxy_server.py +1 -1
- indexify/function_executor/invocation_state/proxied_invocation_state.py +1 -3
- indexify/function_executor/main.py +50 -0
- indexify/function_executor/proto/configuration.py +8 -0
- indexify/function_executor/proto/function_executor.proto +9 -4
- indexify/function_executor/proto/function_executor_pb2.py +24 -24
- indexify/function_executor/proto/function_executor_pb2.pyi +24 -4
- indexify/function_executor/server.py +4 -6
- indexify/function_executor/{function_executor_service.py → service.py} +35 -18
- indexify/utils/README.md +3 -0
- indexify/{common_util.py → utils/http_client.py} +2 -2
- indexify/{logging.py → utils/logging.py} +36 -2
- indexify-0.3.0.dist-info/METADATA +38 -0
- indexify-0.3.0.dist-info/RECORD +44 -0
- {indexify-0.2.47.dist-info → indexify-0.3.0.dist-info}/WHEEL +1 -1
- indexify-0.3.0.dist-info/entry_points.txt +4 -0
- indexify/__init__.py +0 -31
- indexify/data_loaders/__init__.py +0 -58
- indexify/data_loaders/local_directory_loader.py +0 -37
- indexify/data_loaders/url_loader.py +0 -52
- indexify/error.py +0 -8
- indexify/functions_sdk/data_objects.py +0 -27
- indexify/functions_sdk/graph.py +0 -364
- indexify/functions_sdk/graph_definition.py +0 -63
- indexify/functions_sdk/graph_validation.py +0 -70
- indexify/functions_sdk/image.py +0 -210
- indexify/functions_sdk/indexify_functions.py +0 -354
- indexify/functions_sdk/invocation_state/invocation_state.py +0 -22
- indexify/functions_sdk/invocation_state/local_invocation_state.py +0 -30
- indexify/functions_sdk/object_serializer.py +0 -68
- indexify/functions_sdk/pipeline.py +0 -33
- indexify/http_client.py +0 -379
- indexify/remote_graph.py +0 -138
- indexify/remote_pipeline.py +0 -25
- indexify/settings.py +0 -1
- indexify-0.2.47.dist-info/LICENSE.txt +0 -201
- indexify-0.2.47.dist-info/METADATA +0 -154
- indexify-0.2.47.dist-info/RECORD +0 -60
- indexify-0.2.47.dist-info/entry_points.txt +0 -3
@@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default()
|
|
24
24
|
|
25
25
|
|
26
26
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
|
27
|
-
b'\n8indexify/function_executor/proto/function_executor.proto\x12\x19\x66unction_executor_service"i\n\x10SerializedObject\x12\x0f\n\x05\x62ytes\x18\x01 \x01(\x0cH\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x19\n\x0c\x63ontent_type\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x06\n\x04\x64\x61taB\x0f\n\r_content_type"\x88\x02\n\x11InitializeRequest\x12\x16\n\tnamespace\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ngraph_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rgraph_version\x18\x03 \x01(\
|
27
|
+
b'\n8indexify/function_executor/proto/function_executor.proto\x12\x19\x66unction_executor_service"i\n\x10SerializedObject\x12\x0f\n\x05\x62ytes\x18\x01 \x01(\x0cH\x00\x12\x10\n\x06string\x18\x02 \x01(\tH\x00\x12\x19\n\x0c\x63ontent_type\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\x06\n\x04\x64\x61taB\x0f\n\r_content_type"\x88\x02\n\x11InitializeRequest\x12\x16\n\tnamespace\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ngraph_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rgraph_version\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rfunction_name\x18\x05 \x01(\tH\x03\x88\x01\x01\x12?\n\x05graph\x18\x07 \x01(\x0b\x32+.function_executor_service.SerializedObjectH\x04\x88\x01\x01\x42\x0c\n\n_namespaceB\r\n\x0b_graph_nameB\x10\n\x0e_graph_versionB\x10\n\x0e_function_nameB\x08\n\x06_graph"f\n\x12InitializeResponse\x12\x14\n\x07success\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0e\x63ustomer_error\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\n\n\x08_successB\x11\n\x0f_customer_error"\x80\x01\n\x19SetInvocationStateRequest\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12?\n\x05value\x18\x02 \x01(\x0b\x32+.function_executor_service.SerializedObjectH\x01\x88\x01\x01\x42\x06\n\x04_keyB\x08\n\x06_value"\x1c\n\x1aSetInvocationStateResponse"5\n\x19GetInvocationStateRequest\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x06\n\x04_key"\x81\x01\n\x1aGetInvocationStateResponse\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12?\n\x05value\x18\x02 \x01(\x0b\x32+.function_executor_service.SerializedObjectH\x01\x88\x01\x01\x42\x06\n\x04_keyB\x08\n\x06_value"\xf7\x01\n\x16InvocationStateRequest\x12\x17\n\nrequest_id\x18\x01 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07task_id\x18\x02 \x01(\tH\x02\x88\x01\x01\x12\x43\n\x03set\x18\x03 \x01(\x0b\x32\x34.function_executor_service.SetInvocationStateRequestH\x00\x12\x43\n\x03get\x18\x04 \x01(\x0b\x32\x34.function_executor_service.GetInvocationStateRequestH\x00\x42\t\n\x07requestB\r\n\x0b_request_idB\n\n\x08_task_id"\xfb\x01\n\x17InvocationStateResponse\x12\x17\n\nrequest_id\x18\x01 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07success\x18\x02 \x01(\x08H\x02\x88\x01\x01\x12\x44\n\x03set\x18\x03 \x01(\x0b\x32\x35.function_executor_service.SetInvocationStateResponseH\x00\x12\x44\n\x03get\x18\x04 \x01(\x0b\x32\x35.function_executor_service.GetInvocationStateResponseH\x00\x42\n\n\x08responseB\r\n\x0b_request_idB\n\n\x08_success"N\n\x0e\x46unctionOutput\x12<\n\x07outputs\x18\x01 \x03(\x0b\x32+.function_executor_service.SerializedObject"\x1d\n\x0cRouterOutput\x12\r\n\x05\x65\x64ges\x18\x01 \x03(\t"\xda\x03\n\x0eRunTaskRequest\x12\x16\n\tnamespace\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\ngraph_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rgraph_version\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rfunction_name\x18\x04 \x01(\tH\x03\x88\x01\x01\x12 \n\x13graph_invocation_id\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x14\n\x07task_id\x18\x06 \x01(\tH\x05\x88\x01\x01\x12H\n\x0e\x66unction_input\x18\x07 \x01(\x0b\x32+.function_executor_service.SerializedObjectH\x06\x88\x01\x01\x12M\n\x13\x66unction_init_value\x18\x08 \x01(\x0b\x32+.function_executor_service.SerializedObjectH\x07\x88\x01\x01\x42\x0c\n\n_namespaceB\r\n\x0b_graph_nameB\x10\n\x0e_graph_versionB\x10\n\x0e_function_nameB\x16\n\x14_graph_invocation_idB\n\n\x08_task_idB\x11\n\x0f_function_inputB\x16\n\x14_function_init_value"\xf1\x02\n\x0fRunTaskResponse\x12\x14\n\x07task_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12G\n\x0f\x66unction_output\x18\x02 \x01(\x0b\x32).function_executor_service.FunctionOutputH\x01\x88\x01\x01\x12\x43\n\rrouter_output\x18\x03 \x01(\x0b\x32\'.function_executor_service.RouterOutputH\x02\x88\x01\x01\x12\x13\n\x06stdout\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06stderr\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x17\n\nis_reducer\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x14\n\x07success\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\n\n\x08_task_idB\x12\n\x10_function_outputB\x10\n\x0e_router_outputB\t\n\x07_stdoutB\t\n\x07_stderrB\r\n\x0b_is_reducerB\n\n\x08_success2\xf2\x02\n\x10\x46unctionExecutor\x12i\n\ninitialize\x12,.function_executor_service.InitializeRequest\x1a-.function_executor_service.InitializeResponse\x12\x8f\x01\n"initialize_invocation_state_server\x12\x32.function_executor_service.InvocationStateResponse\x1a\x31.function_executor_service.InvocationStateRequest(\x01\x30\x01\x12\x61\n\x08run_task\x12).function_executor_service.RunTaskRequest\x1a*.function_executor_service.RunTaskResponseb\x06proto3'
|
28
28
|
)
|
29
29
|
|
30
30
|
_globals = globals()
|
@@ -39,27 +39,27 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
39
39
|
_globals["_INITIALIZEREQUEST"]._serialized_start = 195
|
40
40
|
_globals["_INITIALIZEREQUEST"]._serialized_end = 459
|
41
41
|
_globals["_INITIALIZERESPONSE"]._serialized_start = 461
|
42
|
-
_globals["_INITIALIZERESPONSE"]._serialized_end =
|
43
|
-
_globals["_SETINVOCATIONSTATEREQUEST"]._serialized_start =
|
44
|
-
_globals["_SETINVOCATIONSTATEREQUEST"]._serialized_end =
|
45
|
-
_globals["_SETINVOCATIONSTATERESPONSE"]._serialized_start =
|
46
|
-
_globals["_SETINVOCATIONSTATERESPONSE"]._serialized_end =
|
47
|
-
_globals["_GETINVOCATIONSTATEREQUEST"]._serialized_start =
|
48
|
-
_globals["_GETINVOCATIONSTATEREQUEST"]._serialized_end =
|
49
|
-
_globals["_GETINVOCATIONSTATERESPONSE"]._serialized_start =
|
50
|
-
_globals["_GETINVOCATIONSTATERESPONSE"]._serialized_end =
|
51
|
-
_globals["_INVOCATIONSTATEREQUEST"]._serialized_start =
|
52
|
-
_globals["_INVOCATIONSTATEREQUEST"]._serialized_end =
|
53
|
-
_globals["_INVOCATIONSTATERESPONSE"]._serialized_start =
|
54
|
-
_globals["_INVOCATIONSTATERESPONSE"]._serialized_end =
|
55
|
-
_globals["_FUNCTIONOUTPUT"]._serialized_start =
|
56
|
-
_globals["_FUNCTIONOUTPUT"]._serialized_end =
|
57
|
-
_globals["_ROUTEROUTPUT"]._serialized_start =
|
58
|
-
_globals["_ROUTEROUTPUT"]._serialized_end =
|
59
|
-
_globals["_RUNTASKREQUEST"]._serialized_start =
|
60
|
-
_globals["_RUNTASKREQUEST"]._serialized_end =
|
61
|
-
_globals["_RUNTASKRESPONSE"]._serialized_start =
|
62
|
-
_globals["_RUNTASKRESPONSE"]._serialized_end =
|
63
|
-
_globals["_FUNCTIONEXECUTOR"]._serialized_start =
|
64
|
-
_globals["_FUNCTIONEXECUTOR"]._serialized_end =
|
42
|
+
_globals["_INITIALIZERESPONSE"]._serialized_end = 563
|
43
|
+
_globals["_SETINVOCATIONSTATEREQUEST"]._serialized_start = 566
|
44
|
+
_globals["_SETINVOCATIONSTATEREQUEST"]._serialized_end = 694
|
45
|
+
_globals["_SETINVOCATIONSTATERESPONSE"]._serialized_start = 696
|
46
|
+
_globals["_SETINVOCATIONSTATERESPONSE"]._serialized_end = 724
|
47
|
+
_globals["_GETINVOCATIONSTATEREQUEST"]._serialized_start = 726
|
48
|
+
_globals["_GETINVOCATIONSTATEREQUEST"]._serialized_end = 779
|
49
|
+
_globals["_GETINVOCATIONSTATERESPONSE"]._serialized_start = 782
|
50
|
+
_globals["_GETINVOCATIONSTATERESPONSE"]._serialized_end = 911
|
51
|
+
_globals["_INVOCATIONSTATEREQUEST"]._serialized_start = 914
|
52
|
+
_globals["_INVOCATIONSTATEREQUEST"]._serialized_end = 1161
|
53
|
+
_globals["_INVOCATIONSTATERESPONSE"]._serialized_start = 1164
|
54
|
+
_globals["_INVOCATIONSTATERESPONSE"]._serialized_end = 1415
|
55
|
+
_globals["_FUNCTIONOUTPUT"]._serialized_start = 1417
|
56
|
+
_globals["_FUNCTIONOUTPUT"]._serialized_end = 1495
|
57
|
+
_globals["_ROUTEROUTPUT"]._serialized_start = 1497
|
58
|
+
_globals["_ROUTEROUTPUT"]._serialized_end = 1526
|
59
|
+
_globals["_RUNTASKREQUEST"]._serialized_start = 1529
|
60
|
+
_globals["_RUNTASKREQUEST"]._serialized_end = 2003
|
61
|
+
_globals["_RUNTASKRESPONSE"]._serialized_start = 2006
|
62
|
+
_globals["_RUNTASKRESPONSE"]._serialized_end = 2375
|
63
|
+
_globals["_FUNCTIONEXECUTOR"]._serialized_start = 2378
|
64
|
+
_globals["_FUNCTIONEXECUTOR"]._serialized_end = 2748
|
65
65
|
# @@protoc_insertion_point(module_scope)
|
@@ -34,23 +34,27 @@ class InitializeRequest(_message.Message):
|
|
34
34
|
GRAPH_FIELD_NUMBER: _ClassVar[int]
|
35
35
|
namespace: str
|
36
36
|
graph_name: str
|
37
|
-
graph_version:
|
37
|
+
graph_version: str
|
38
38
|
function_name: str
|
39
39
|
graph: SerializedObject
|
40
40
|
def __init__(
|
41
41
|
self,
|
42
42
|
namespace: _Optional[str] = ...,
|
43
43
|
graph_name: _Optional[str] = ...,
|
44
|
-
graph_version: _Optional[
|
44
|
+
graph_version: _Optional[str] = ...,
|
45
45
|
function_name: _Optional[str] = ...,
|
46
46
|
graph: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
47
47
|
) -> None: ...
|
48
48
|
|
49
49
|
class InitializeResponse(_message.Message):
|
50
|
-
__slots__ = ("success",)
|
50
|
+
__slots__ = ("success", "customer_error")
|
51
51
|
SUCCESS_FIELD_NUMBER: _ClassVar[int]
|
52
|
+
CUSTOMER_ERROR_FIELD_NUMBER: _ClassVar[int]
|
52
53
|
success: bool
|
53
|
-
|
54
|
+
customer_error: str
|
55
|
+
def __init__(
|
56
|
+
self, success: bool = ..., customer_error: _Optional[str] = ...
|
57
|
+
) -> None: ...
|
54
58
|
|
55
59
|
class SetInvocationStateRequest(_message.Message):
|
56
60
|
__slots__ = ("key", "value")
|
@@ -138,21 +142,37 @@ class RouterOutput(_message.Message):
|
|
138
142
|
|
139
143
|
class RunTaskRequest(_message.Message):
|
140
144
|
__slots__ = (
|
145
|
+
"namespace",
|
146
|
+
"graph_name",
|
147
|
+
"graph_version",
|
148
|
+
"function_name",
|
141
149
|
"graph_invocation_id",
|
142
150
|
"task_id",
|
143
151
|
"function_input",
|
144
152
|
"function_init_value",
|
145
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]
|
146
158
|
GRAPH_INVOCATION_ID_FIELD_NUMBER: _ClassVar[int]
|
147
159
|
TASK_ID_FIELD_NUMBER: _ClassVar[int]
|
148
160
|
FUNCTION_INPUT_FIELD_NUMBER: _ClassVar[int]
|
149
161
|
FUNCTION_INIT_VALUE_FIELD_NUMBER: _ClassVar[int]
|
162
|
+
namespace: str
|
163
|
+
graph_name: str
|
164
|
+
graph_version: str
|
165
|
+
function_name: str
|
150
166
|
graph_invocation_id: str
|
151
167
|
task_id: str
|
152
168
|
function_input: SerializedObject
|
153
169
|
function_init_value: SerializedObject
|
154
170
|
def __init__(
|
155
171
|
self,
|
172
|
+
namespace: _Optional[str] = ...,
|
173
|
+
graph_name: _Optional[str] = ...,
|
174
|
+
graph_version: _Optional[str] = ...,
|
175
|
+
function_name: _Optional[str] = ...,
|
156
176
|
graph_invocation_id: _Optional[str] = ...,
|
157
177
|
task_id: _Optional[str] = ...,
|
158
178
|
function_input: _Optional[_Union[SerializedObject, _Mapping]] = ...,
|
@@ -2,11 +2,9 @@ from concurrent.futures import ThreadPoolExecutor
|
|
2
2
|
|
3
3
|
import grpc
|
4
4
|
|
5
|
-
from .function_executor_service import FunctionExecutorService
|
6
5
|
from .proto.configuration import GRPC_SERVER_OPTIONS
|
7
|
-
from .proto.function_executor_pb2_grpc import
|
8
|
-
|
9
|
-
)
|
6
|
+
from .proto.function_executor_pb2_grpc import add_FunctionExecutorServicer_to_server
|
7
|
+
from .service import Service
|
10
8
|
|
11
9
|
# Temporary limit until we have a better way to control this.
|
12
10
|
# This limits the number of concurrent tasks that Function Executor can run.
|
@@ -14,9 +12,9 @@ MAX_RPC_CONCURRENCY = 100
|
|
14
12
|
|
15
13
|
|
16
14
|
class Server:
|
17
|
-
def __init__(self, server_address: str, service:
|
15
|
+
def __init__(self, server_address: str, service: Service):
|
18
16
|
self._server_address: str = server_address
|
19
|
-
self._service:
|
17
|
+
self._service: Service = service
|
20
18
|
|
21
19
|
def run(self):
|
22
20
|
"""Runs Function Executor Service at the configured address."""
|
@@ -2,21 +2,15 @@ from typing import Iterator, Optional, Union
|
|
2
2
|
|
3
3
|
import grpc
|
4
4
|
import structlog
|
5
|
-
|
6
|
-
from
|
7
|
-
IndexifyFunction,
|
8
|
-
IndexifyRouter,
|
9
|
-
)
|
10
|
-
from indexify.functions_sdk.object_serializer import get_serializer
|
5
|
+
from tensorlake.functions_sdk.functions import TensorlakeCompute
|
6
|
+
from tensorlake.functions_sdk.object_serializer import get_serializer
|
11
7
|
|
12
8
|
from .handlers.run_function.handler import Handler as RunTaskHandler
|
13
9
|
from .handlers.run_function.request_validator import (
|
14
10
|
RequestValidator as RunTaskRequestValidator,
|
15
11
|
)
|
16
12
|
from .initialize_request_validator import InitializeRequestValidator
|
17
|
-
from .invocation_state.invocation_state_proxy_server import
|
18
|
-
InvocationStateProxyServer,
|
19
|
-
)
|
13
|
+
from .invocation_state.invocation_state_proxy_server import InvocationStateProxyServer
|
20
14
|
from .invocation_state.proxied_invocation_state import ProxiedInvocationState
|
21
15
|
from .proto.function_executor_pb2 import (
|
22
16
|
InitializeRequest,
|
@@ -28,14 +22,14 @@ from .proto.function_executor_pb2 import (
|
|
28
22
|
from .proto.function_executor_pb2_grpc import FunctionExecutorServicer
|
29
23
|
|
30
24
|
|
31
|
-
class
|
25
|
+
class Service(FunctionExecutorServicer):
|
32
26
|
def __init__(self):
|
33
27
|
self._logger = structlog.get_logger(module=__name__)
|
34
28
|
self._namespace: Optional[str] = None
|
35
29
|
self._graph_name: Optional[str] = None
|
36
|
-
self._graph_version: Optional[
|
30
|
+
self._graph_version: Optional[str] = None
|
37
31
|
self._function_name: Optional[str] = None
|
38
|
-
self._function: Optional[Union[
|
32
|
+
self._function: Optional[Union[TensorlakeCompute, TensorlakeCompute]] = None
|
39
33
|
self._invocation_state_proxy_server: Optional[InvocationStateProxyServer] = None
|
40
34
|
|
41
35
|
def initialize(
|
@@ -55,18 +49,22 @@ class FunctionExecutorService(FunctionExecutorServicer):
|
|
55
49
|
# implementing smart caching in customer code. E.g. load a model into GPU only once and
|
56
50
|
# share the model's file descriptor between all tasks or download function configuration
|
57
51
|
# only once.
|
58
|
-
graph_serializer = get_serializer(request.graph.content_type)
|
59
|
-
graph = graph_serializer.deserialize(request.graph.bytes)
|
60
|
-
self._function = graph_serializer.deserialize(graph[request.function_name])
|
61
|
-
|
62
52
|
self._logger = self._logger.bind(
|
63
53
|
namespace=request.namespace,
|
64
54
|
graph_name=request.graph_name,
|
65
|
-
graph_version=
|
55
|
+
graph_version=request.graph_version,
|
66
56
|
function_name=request.function_name,
|
67
57
|
)
|
68
|
-
|
58
|
+
graph_serializer = get_serializer(request.graph.content_type)
|
59
|
+
try:
|
60
|
+
# Process user controlled input in a try-except block to not treat errors here as our
|
61
|
+
# internal platform errors.
|
62
|
+
graph = graph_serializer.deserialize(request.graph.bytes)
|
63
|
+
self._function = graph_serializer.deserialize(graph[request.function_name])
|
64
|
+
except Exception as e:
|
65
|
+
return InitializeResponse(success=False, customer_error=str(e))
|
69
66
|
|
67
|
+
self._logger.info("initialized function executor service")
|
70
68
|
return InitializeResponse(success=True)
|
71
69
|
|
72
70
|
def initialize_invocation_state_server(
|
@@ -88,6 +86,25 @@ class FunctionExecutorService(FunctionExecutorServicer):
|
|
88
86
|
# If our code raises an exception the grpc framework converts it into GRPC_STATUS_UNKNOWN
|
89
87
|
# error with the exception message. Differentiating errors is not needed for now.
|
90
88
|
RunTaskRequestValidator(request=request).check()
|
89
|
+
|
90
|
+
# Fail with internal error as this happened due to wrong task routing to this Server.
|
91
|
+
if request.namespace != self._namespace:
|
92
|
+
raise ValueError(
|
93
|
+
f"This Function Executor is not initialized for this namespace {request.namespace}"
|
94
|
+
)
|
95
|
+
if request.graph_name != self._graph_name:
|
96
|
+
raise ValueError(
|
97
|
+
f"This Function Executor is not initialized for this graph {request.graph_name}"
|
98
|
+
)
|
99
|
+
if request.graph_version != self._graph_version:
|
100
|
+
raise ValueError(
|
101
|
+
f"This Function Executor is not initialized for this graph version {request.graph_version}"
|
102
|
+
)
|
103
|
+
if request.function_name != self._function_name:
|
104
|
+
raise ValueError(
|
105
|
+
f"This Function Executor is not initialized for this function {request.function_name}"
|
106
|
+
)
|
107
|
+
|
91
108
|
return RunTaskHandler(
|
92
109
|
request=request,
|
93
110
|
graph_name=self._graph_name,
|
indexify/utils/README.md
ADDED
@@ -7,7 +7,7 @@ from httpx import AsyncClient, Client
|
|
7
7
|
|
8
8
|
def get_httpx_client(
|
9
9
|
config_path: Optional[str] = None, make_async: Optional[bool] = False
|
10
|
-
) -> AsyncClient
|
10
|
+
) -> Union[AsyncClient, Client]:
|
11
11
|
"""
|
12
12
|
Creates and returns an httpx.Client instance, optionally configured with TLS settings from a YAML config file.
|
13
13
|
|
@@ -54,7 +54,7 @@ def get_sync_or_async_client(
|
|
54
54
|
cert_path: Optional[str] = None,
|
55
55
|
key_path: Optional[str] = None,
|
56
56
|
ca_bundle_path: Optional[str] = None,
|
57
|
-
) -> AsyncClient
|
57
|
+
) -> Union[AsyncClient, Client]:
|
58
58
|
"""
|
59
59
|
Creates and returns either a synchronous or asynchronous httpx client with optional TLS configuration.
|
60
60
|
|
@@ -2,6 +2,9 @@ import logging
|
|
2
2
|
import sys
|
3
3
|
|
4
4
|
import structlog
|
5
|
+
from structlog.contextvars import merge_contextvars
|
6
|
+
from structlog.dev import ConsoleRenderer, set_exc_info
|
7
|
+
from structlog.processors import StackInfoRenderer, TimeStamper, add_log_level
|
5
8
|
|
6
9
|
# Using this module allows us to be consistent with the logging configuration across all Python programs.
|
7
10
|
|
@@ -24,9 +27,40 @@ def configure_logging_early():
|
|
24
27
|
)
|
25
28
|
|
26
29
|
|
27
|
-
def
|
30
|
+
def configure_development_mode_logging():
|
28
31
|
processors = [
|
29
|
-
|
32
|
+
structlog_suppressor,
|
33
|
+
merge_contextvars,
|
34
|
+
add_log_level,
|
35
|
+
StackInfoRenderer(),
|
36
|
+
set_exc_info,
|
37
|
+
TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=False),
|
38
|
+
ConsoleRenderer(),
|
39
|
+
]
|
40
|
+
structlog.configure(
|
41
|
+
processors=processors,
|
42
|
+
)
|
43
|
+
|
44
|
+
|
45
|
+
def configure_production_mode_logging():
|
46
|
+
processors = [
|
47
|
+
structlog_suppressor,
|
48
|
+
structlog.processors.format_exc_info,
|
30
49
|
structlog.processors.JSONRenderer(),
|
31
50
|
]
|
32
51
|
structlog.configure(processors=processors)
|
52
|
+
|
53
|
+
|
54
|
+
_suppress_logging = False
|
55
|
+
|
56
|
+
|
57
|
+
def structlog_suppressor(logger, name, event_dict):
|
58
|
+
global _suppress_logging
|
59
|
+
return None if _suppress_logging else event_dict
|
60
|
+
|
61
|
+
|
62
|
+
def suppress():
|
63
|
+
"""Sets the log level for the root logger to the new level."""
|
64
|
+
global _suppress_logging
|
65
|
+
_suppress_logging = True
|
66
|
+
logging.getLogger().setLevel(logging.CRITICAL)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: indexify
|
3
|
+
Version: 0.3.0
|
4
|
+
Summary: Open Source Indexify components and helper tools
|
5
|
+
Home-page: https://github.com/tensorlakeai/indexify
|
6
|
+
License: Apache 2.0
|
7
|
+
Author: Tensorlake Inc.
|
8
|
+
Author-email: support@tensorlake.ai
|
9
|
+
Requires-Python: >=3.9,<4.0
|
10
|
+
Classifier: License :: Other/Proprietary License
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
17
|
+
Requires-Dist: grpcio (==1.68.1)
|
18
|
+
Requires-Dist: grpcio-tools (==1.68.1)
|
19
|
+
Requires-Dist: httpx-sse (>=0.4.0,<0.5.0)
|
20
|
+
Requires-Dist: httpx[http2] (>=0.28.1,<0.29.0)
|
21
|
+
Requires-Dist: nanoid (>=2.0.0,<3.0.0)
|
22
|
+
Requires-Dist: pydantic (==2.10.4)
|
23
|
+
Requires-Dist: pyyaml (>=6,<7)
|
24
|
+
Requires-Dist: rich (>=13.9.2,<14.0.0)
|
25
|
+
Requires-Dist: structlog (>=24.4.0,<25.0.0)
|
26
|
+
Requires-Dist: tensorlake (==0.1.7)
|
27
|
+
Requires-Dist: typer (>=0.12,<0.13)
|
28
|
+
Project-URL: Repository, https://github.com/tensorlakeai/indexify
|
29
|
+
Description-Content-Type: text/markdown
|
30
|
+
|
31
|
+
## Overview
|
32
|
+
|
33
|
+
This a package with all Open Source Indexify components and helper tools
|
34
|
+
available via a CLI.
|
35
|
+
|
36
|
+
The CLI allows to:
|
37
|
+
* Setup a local or a distributed Indexify cluster.
|
38
|
+
* Build container images for Indexify functions.
|
@@ -0,0 +1,44 @@
|
|
1
|
+
indexify/cli/cli.py,sha256=II73vJlVeEy51pPLnrnBcYJbZQxCPItkFRFEN8MD37c,9122
|
2
|
+
indexify/executor/README.md,sha256=ozC6_hMkhQQNVCMEpBxwiUALz6lwErPQxNxQfQDqnG4,2029
|
3
|
+
indexify/executor/api_objects.py,sha256=QeXOZpS7nkVA_dsRQFlS3EuMvqFvLGaw1Spcr0c-5lA,1015
|
4
|
+
indexify/executor/downloader.py,sha256=Vrq1dAW4BifG62tlqFnImiMxdezIgOZcByTRnhDsnnw,6457
|
5
|
+
indexify/executor/executor.py,sha256=lln0p0cVN2aNY3bsHFp7Phbaa2q9gnQABi1xEPxo1Nc,5859
|
6
|
+
indexify/executor/function_executor/function_executor.py,sha256=a9pAWQWDLJL-i5bp1PEMD2eMYOTvXAh_1jQsXcL_JCQ,5226
|
7
|
+
indexify/executor/function_executor/function_executor_state.py,sha256=_85dpaudYM0sekOqwjMxKGdK7MNQdTGUhHi67sqVHyY,2853
|
8
|
+
indexify/executor/function_executor/invocation_state_client.py,sha256=jxElxnYFfdwCxKfKvQsjLIE-Z_1386wxednJ2pGKSL0,8581
|
9
|
+
indexify/executor/function_executor/server/function_executor_server.py,sha256=_DLivLDikupZusRk8gVWDk7fWPT9XjZ4un1yWSlOObs,883
|
10
|
+
indexify/executor/function_executor/server/function_executor_server_factory.py,sha256=pGbJMQfC5TNvyWOs6VDKdqd2PK5OHQh5_wSDP-E7DbI,1677
|
11
|
+
indexify/executor/function_executor/server/subprocess_function_executor_server.py,sha256=DxQMwAvQi03OGo2sFruUrxwcMPG8In4C62L3sped2FI,694
|
12
|
+
indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py,sha256=cVr2wXQL5zVlq-Ep44ZBXBFCQbrbZSMscjRmzVDakvk,4295
|
13
|
+
indexify/executor/function_executor/single_task_runner.py,sha256=NGji5iIoA9vxRzSvyUTL3Gs5g4HMq5b1LYN5ZsENcls,6244
|
14
|
+
indexify/executor/function_executor/task_input.py,sha256=8pBRuaQbBBPrDWwByOKZlOaXu6UDmJUO5w-6XxAYSgY,582
|
15
|
+
indexify/executor/function_executor/task_output.py,sha256=3-qcT1aigmOFEp6QSJtUcQfqeJfrxvo265qgk9WAUVg,1064
|
16
|
+
indexify/executor/runtime_probes.py,sha256=bo6Dq6AGZpJH099j0DHtVSDEH80tv3j9MXf3VXSx_p8,2182
|
17
|
+
indexify/executor/task_fetcher.py,sha256=Cpm-LRZz1MSfW-xHJbIaKc1wxzRhIrud9GTOIxWODt0,2883
|
18
|
+
indexify/executor/task_reporter.py,sha256=eueJNHYJIwAm8lY8SQJrUOWC-Nk-DPesDis1YTR4k7c,6643
|
19
|
+
indexify/executor/task_runner.py,sha256=RSFeJYhQ_agXXPBm8u13HErSUPZGsCGwV1stgS7g258,5035
|
20
|
+
indexify/function_executor/README.md,sha256=TAcbYYe6noUMriaQabJAaZ8a2SAYzlXl7hIdTfULqYY,950
|
21
|
+
indexify/function_executor/handlers/run_function/function_inputs_loader.py,sha256=StSJCp-kkOWUuUIzONnoqtcB37nzBYGcIVy2oTEwOIQ,1588
|
22
|
+
indexify/function_executor/handlers/run_function/handler.py,sha256=DY_aIR8MZsa1cnFxbVEHhcxQSqBwW4cYRN9NhzuDDFo,5090
|
23
|
+
indexify/function_executor/handlers/run_function/request_validator.py,sha256=GS7_zxAlyNg0vpUrhot-DpVWFyI9Y9P8jvb7UuO4b1A,856
|
24
|
+
indexify/function_executor/handlers/run_function/response_helper.py,sha256=FJVl-LyoRBx9HRaOo_umveiWzuh4anO7aXUmEMEki20,3074
|
25
|
+
indexify/function_executor/initialize_request_validator.py,sha256=agYWGRHUC-7IuYtm9NPjcVo5SVOWM4PxewA93dqdkJM,682
|
26
|
+
indexify/function_executor/invocation_state/invocation_state_proxy_server.py,sha256=YEnxvWV8NFVK_CxHI_C-BNizuagalY3ieN62IOxNttU,7023
|
27
|
+
indexify/function_executor/invocation_state/proxied_invocation_state.py,sha256=rjZ2192bSXonNKkaDaByeOL-wVx6x6Qrtio0UVzGSz8,944
|
28
|
+
indexify/function_executor/invocation_state/response_validator.py,sha256=05Y9_5s010owaDb6OUia9W9Alx1r1zJ179HboEkT-Xk,896
|
29
|
+
indexify/function_executor/main.py,sha256=uOzVUhl4LzGJ9Cw3kyyFddaEIMxRETEKFHPnvJVtc50,1152
|
30
|
+
indexify/function_executor/proto/configuration.py,sha256=oHp_Hh1_XdL4v7M2Ok-Z9r7ClTxiWdSP1Ip-NK4Ee6E,1096
|
31
|
+
indexify/function_executor/proto/function_executor.proto,sha256=Ae6vMCNnacHWmrF6aZVPzIVVzG5sJgP7LXV4vIUBKZM,3978
|
32
|
+
indexify/function_executor/proto/function_executor_pb2.py,sha256=X2G2xZQy8VRWqlDKV2dUgD3CkEecFx6Jp2EuTuXrx9o,7358
|
33
|
+
indexify/function_executor/proto/function_executor_pb2.pyi,sha256=TQEOl3W1s4fxtp1g8Hi5S-keMF25DY5-6miyDVHhBkE,7168
|
34
|
+
indexify/function_executor/proto/function_executor_pb2_grpc.py,sha256=xrqIDrcl1PTyQTGAAGrgSDKEtZilC445Op0tJ7LmS5Q,8716
|
35
|
+
indexify/function_executor/proto/message_validator.py,sha256=OKXPYgy5L9c-spnV9Zjv7PA_yxwzvykfhbYylYx8cwQ,1456
|
36
|
+
indexify/function_executor/server.py,sha256=tJzUy_v4BT8Le9G3hgtiuDJo9YVFkAU2dVISSsX36II,1061
|
37
|
+
indexify/function_executor/service.py,sha256=3JYcMcWiCgvxXhRPReUUBjTBNLIqUbhhsGZIsqIcVw4,5343
|
38
|
+
indexify/utils/README.md,sha256=2g8-H9GopacOW4YrViZc0QsaJPtK-Fox7GyfX01kcDk,86
|
39
|
+
indexify/utils/http_client.py,sha256=deMlmAu4E_ZXV3blCdWNag3uO_cyD-GsMZjFFmO5r7s,3541
|
40
|
+
indexify/utils/logging.py,sha256=c6NwzY7uVHMRJc8f2w2KF36rNkeZVoQfGdq7suIg9s8,2025
|
41
|
+
indexify-0.3.0.dist-info/METADATA,sha256=ZZHmhRQjHMzLT-l9rkqkZX_1YSvMEyo6XEY4j7Iw0GU,1376
|
42
|
+
indexify-0.3.0.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
43
|
+
indexify-0.3.0.dist-info/entry_points.txt,sha256=pJG0YRnypesbiNJHuObfHEkjk0p_ZvEDTyyTH0kGVTY,108
|
44
|
+
indexify-0.3.0.dist-info/RECORD,,
|
indexify/__init__.py
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
from . import data_loaders
|
2
|
-
from .functions_sdk.graph import Graph
|
3
|
-
from .functions_sdk.image import Image
|
4
|
-
from .functions_sdk.indexify_functions import (
|
5
|
-
IndexifyFunction,
|
6
|
-
IndexifyRouter,
|
7
|
-
get_ctx,
|
8
|
-
indexify_function,
|
9
|
-
indexify_router,
|
10
|
-
)
|
11
|
-
from .functions_sdk.pipeline import Pipeline
|
12
|
-
from .http_client import IndexifyClient
|
13
|
-
from .remote_graph import RemoteGraph
|
14
|
-
from .remote_pipeline import RemotePipeline
|
15
|
-
from .settings import DEFAULT_SERVICE_URL
|
16
|
-
|
17
|
-
__all__ = [
|
18
|
-
"data_loaders",
|
19
|
-
"Graph",
|
20
|
-
"RemoteGraph",
|
21
|
-
"Pipeline",
|
22
|
-
"RemotePipeline",
|
23
|
-
"Image",
|
24
|
-
"indexify_function",
|
25
|
-
"get_ctx",
|
26
|
-
"IndexifyFunction",
|
27
|
-
"IndexifyRouter",
|
28
|
-
"indexify_router",
|
29
|
-
"DEFAULT_SERVICE_URL",
|
30
|
-
"IndexifyClient",
|
31
|
-
]
|
@@ -1,58 +0,0 @@
|
|
1
|
-
import hashlib
|
2
|
-
import mimetypes
|
3
|
-
import os
|
4
|
-
from abc import ABC, abstractmethod
|
5
|
-
from typing import List
|
6
|
-
|
7
|
-
from pydantic import BaseModel
|
8
|
-
|
9
|
-
|
10
|
-
class FileMetadata(BaseModel):
|
11
|
-
path: str
|
12
|
-
file_size: int
|
13
|
-
mime_type: str
|
14
|
-
md5_hash: str
|
15
|
-
created_at: int
|
16
|
-
updated_at: int
|
17
|
-
|
18
|
-
@classmethod
|
19
|
-
def from_path(cls, path: str):
|
20
|
-
file_size = os.path.getsize(path)
|
21
|
-
mime_type = mimetypes.guess_type(path)[0]
|
22
|
-
|
23
|
-
# Compute MD5 hash
|
24
|
-
hash_md5 = hashlib.md5()
|
25
|
-
with open(path, "rb") as f:
|
26
|
-
for chunk in iter(lambda: f.read(4096), b""):
|
27
|
-
hash_md5.update(chunk)
|
28
|
-
md5_hash = hash_md5.hexdigest()
|
29
|
-
|
30
|
-
created_at = int(os.path.getctime(path))
|
31
|
-
updated_at = int(os.path.getmtime(path))
|
32
|
-
|
33
|
-
return cls(
|
34
|
-
path=path,
|
35
|
-
file_size=file_size,
|
36
|
-
mime_type=str(mime_type),
|
37
|
-
md5_hash=md5_hash,
|
38
|
-
created_at=created_at,
|
39
|
-
updated_at=updated_at,
|
40
|
-
)
|
41
|
-
|
42
|
-
|
43
|
-
class DataLoader(ABC):
|
44
|
-
@abstractmethod
|
45
|
-
def load(self) -> List[FileMetadata]:
|
46
|
-
pass
|
47
|
-
|
48
|
-
@abstractmethod
|
49
|
-
def read_all_bytes(self, file_metadata: FileMetadata) -> bytes:
|
50
|
-
pass
|
51
|
-
|
52
|
-
@abstractmethod
|
53
|
-
def state(self) -> dict:
|
54
|
-
pass
|
55
|
-
|
56
|
-
|
57
|
-
from .local_directory_loader import LocalDirectoryLoader
|
58
|
-
from .url_loader import UrlLoader
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
from typing import List, Optional
|
3
|
-
|
4
|
-
from . import DataLoader, FileMetadata
|
5
|
-
|
6
|
-
|
7
|
-
class LocalDirectoryLoader(DataLoader):
|
8
|
-
def __init__(
|
9
|
-
self,
|
10
|
-
directory: str,
|
11
|
-
file_extensions: Optional[List[str]] = None,
|
12
|
-
state: dict = {},
|
13
|
-
):
|
14
|
-
self.directory = directory
|
15
|
-
self.file_extensions = file_extensions
|
16
|
-
self.processed_files = set(state.get("processed_files", []))
|
17
|
-
|
18
|
-
def load(self) -> List[FileMetadata]:
|
19
|
-
file_metadata_list = []
|
20
|
-
for root, _, files in os.walk(self.directory):
|
21
|
-
for file in files:
|
22
|
-
if self.file_extensions is None or any(
|
23
|
-
file.endswith(ext) for ext in self.file_extensions
|
24
|
-
):
|
25
|
-
file_path = os.path.join(root, file)
|
26
|
-
if file_path not in self.processed_files:
|
27
|
-
file_metadata_list.append(FileMetadata.from_path(file_path))
|
28
|
-
self.processed_files.add(file_path)
|
29
|
-
|
30
|
-
return file_metadata_list
|
31
|
-
|
32
|
-
def read_all_bytes(self, file: FileMetadata) -> bytes:
|
33
|
-
with open(file.path, "rb") as f:
|
34
|
-
return f.read()
|
35
|
-
|
36
|
-
def state(self) -> dict:
|
37
|
-
return {"processed_files": list(self.processed_files)}
|
@@ -1,52 +0,0 @@
|
|
1
|
-
import email.utils
|
2
|
-
from typing import List
|
3
|
-
|
4
|
-
import httpx
|
5
|
-
|
6
|
-
from . import DataLoader, FileMetadata
|
7
|
-
|
8
|
-
|
9
|
-
def convert_date_to_epoch(date_str: str) -> int:
|
10
|
-
"""
|
11
|
-
Convert a date string from URL header to Unix epoch time.
|
12
|
-
|
13
|
-
Args:
|
14
|
-
date_str (str): The date string from the URL header.
|
15
|
-
|
16
|
-
Returns:
|
17
|
-
int: The Unix epoch time.
|
18
|
-
"""
|
19
|
-
if not date_str:
|
20
|
-
return 0
|
21
|
-
parsed_date = email.utils.parsedate_to_datetime(date_str)
|
22
|
-
return int(parsed_date.timestamp())
|
23
|
-
|
24
|
-
|
25
|
-
class UrlLoader(DataLoader):
|
26
|
-
def __init__(self, urls: List[str], state: dict = {}):
|
27
|
-
self.urls = urls
|
28
|
-
|
29
|
-
def load(self) -> List[FileMetadata]:
|
30
|
-
file_metadata_list = []
|
31
|
-
for url in self.urls:
|
32
|
-
response = httpx.head(url, follow_redirects=True)
|
33
|
-
file_metadata_list.append(
|
34
|
-
FileMetadata(
|
35
|
-
path=url,
|
36
|
-
file_size=response.headers.get("content-length", 0),
|
37
|
-
mime_type=response.headers.get("content-type"),
|
38
|
-
md5_hash="",
|
39
|
-
created_at=convert_date_to_epoch(response.headers.get("date")),
|
40
|
-
updated_at=convert_date_to_epoch(
|
41
|
-
response.headers.get("last-modified")
|
42
|
-
),
|
43
|
-
)
|
44
|
-
)
|
45
|
-
return file_metadata_list
|
46
|
-
|
47
|
-
def read_all_bytes(self, file: FileMetadata) -> bytes:
|
48
|
-
response = httpx.get(file.path, follow_redirects=True)
|
49
|
-
return response.content
|
50
|
-
|
51
|
-
def state(self) -> dict:
|
52
|
-
return {}
|