indexify 0.3.5__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.
Files changed (39) hide show
  1. indexify/cli/cli.py +2 -2
  2. indexify/executor/downloader.py +2 -3
  3. indexify/executor/executor.py +2 -3
  4. indexify/executor/function_executor/function_executor.py +3 -4
  5. indexify/executor/function_executor/health_checker.py +2 -3
  6. indexify/executor/function_executor/invocation_state_client.py +3 -4
  7. indexify/executor/function_executor/single_task_runner.py +2 -4
  8. indexify/executor/function_executor/task_input.py +1 -1
  9. indexify/executor/function_executor/task_output.py +1 -1
  10. indexify/executor/task_fetcher.py +1 -2
  11. indexify/executor/task_reporter.py +3 -4
  12. {indexify-0.3.5.dist-info → indexify-0.3.6.dist-info}/METADATA +3 -4
  13. indexify-0.3.6.dist-info/RECORD +25 -0
  14. indexify-0.3.6.dist-info/entry_points.txt +3 -0
  15. indexify/function_executor/README.md +0 -18
  16. indexify/function_executor/handlers/run_function/function_inputs_loader.py +0 -53
  17. indexify/function_executor/handlers/run_function/handler.py +0 -126
  18. indexify/function_executor/handlers/run_function/request_validator.py +0 -26
  19. indexify/function_executor/handlers/run_function/response_helper.py +0 -96
  20. indexify/function_executor/info.py +0 -16
  21. indexify/function_executor/initialize_request_validator.py +0 -21
  22. indexify/function_executor/invocation_state/invocation_state_proxy_server.py +0 -170
  23. indexify/function_executor/invocation_state/proxied_invocation_state.py +0 -22
  24. indexify/function_executor/invocation_state/response_validator.py +0 -29
  25. indexify/function_executor/main.py +0 -51
  26. indexify/function_executor/proto/function_executor.proto +0 -148
  27. indexify/function_executor/proto/function_executor_pb2.py +0 -73
  28. indexify/function_executor/proto/function_executor_pb2.pyi +0 -247
  29. indexify/function_executor/proto/function_executor_pb2_grpc.py +0 -307
  30. indexify/function_executor/proto/message_validator.py +0 -38
  31. indexify/function_executor/proto/server_configuration.py +0 -19
  32. indexify/function_executor/server.py +0 -29
  33. indexify/function_executor/service.py +0 -145
  34. indexify/utils/README.md +0 -3
  35. indexify/utils/http_client.py +0 -88
  36. indexify/utils/logging.py +0 -66
  37. indexify-0.3.5.dist-info/RECORD +0 -47
  38. indexify-0.3.5.dist-info/entry_points.txt +0 -4
  39. {indexify-0.3.5.dist-info → indexify-0.3.6.dist-info}/WHEEL +0 -0
@@ -1,145 +0,0 @@
1
- from typing import Iterator, Optional
2
-
3
- import grpc
4
- import structlog
5
- from tensorlake.functions_sdk.functions import TensorlakeFunctionWrapper
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 .info import info_response_kv_args
13
- from .initialize_request_validator import InitializeRequestValidator
14
- from .invocation_state.invocation_state_proxy_server import InvocationStateProxyServer
15
- from .invocation_state.proxied_invocation_state import ProxiedInvocationState
16
- from .proto.function_executor_pb2 import (
17
- HealthCheckRequest,
18
- HealthCheckResponse,
19
- InfoRequest,
20
- InfoResponse,
21
- InitializeRequest,
22
- InitializeResponse,
23
- InvocationStateResponse,
24
- RunTaskRequest,
25
- RunTaskResponse,
26
- )
27
- from .proto.function_executor_pb2_grpc import FunctionExecutorServicer
28
-
29
-
30
- class Service(FunctionExecutorServicer):
31
- def __init__(self):
32
- self._logger = structlog.get_logger(module=__name__).bind(
33
- **info_response_kv_args()
34
- )
35
- self._namespace: Optional[str] = None
36
- self._graph_name: Optional[str] = None
37
- self._graph_version: Optional[str] = None
38
- self._function_name: Optional[str] = None
39
- self._function_wrapper: Optional[TensorlakeFunctionWrapper] = None
40
- self._invocation_state_proxy_server: Optional[InvocationStateProxyServer] = None
41
-
42
- def initialize(
43
- self, request: InitializeRequest, context: grpc.ServicerContext
44
- ) -> InitializeResponse:
45
- request_validator: InitializeRequestValidator = InitializeRequestValidator(
46
- request
47
- )
48
- request_validator.check()
49
-
50
- self._namespace = request.namespace
51
- self._graph_name = request.graph_name
52
- self._graph_version = request.graph_version
53
- self._function_name = request.function_name
54
- # The function is only loaded once per Function Executor. It's important to use a single
55
- # loaded function so all the tasks when executed are sharing the same memory. This allows
56
- # implementing smart caching in customer code. E.g. load a model into GPU only once and
57
- # share the model's file descriptor between all tasks or download function configuration
58
- # only once.
59
- self._logger = self._logger.bind(
60
- namespace=request.namespace,
61
- graph_name=request.graph_name,
62
- graph_version=request.graph_version,
63
- function_name=request.function_name,
64
- )
65
- graph_serializer = get_serializer(request.graph.content_type)
66
- try:
67
- # Process user controlled input in a try-except block to not treat errors here as our
68
- # internal platform errors.
69
- # TODO: capture stdout and stderr and report exceptions the same way as when we run a task.
70
- graph = graph_serializer.deserialize(request.graph.bytes)
71
- function = graph_serializer.deserialize(graph[request.function_name])
72
- self._function_wrapper = TensorlakeFunctionWrapper(function)
73
- except Exception as e:
74
- return InitializeResponse(success=False, customer_error=str(e))
75
-
76
- self._logger.info("initialized function executor service")
77
- return InitializeResponse(success=True)
78
-
79
- def initialize_invocation_state_server(
80
- self,
81
- client_responses: Iterator[InvocationStateResponse],
82
- context: grpc.ServicerContext,
83
- ):
84
- self._invocation_state_proxy_server = InvocationStateProxyServer(
85
- client_responses, self._logger
86
- )
87
- self._logger.info("initialized invocation proxy server")
88
- yield from self._invocation_state_proxy_server.run()
89
-
90
- def run_task(
91
- self, request: RunTaskRequest, context: grpc.ServicerContext
92
- ) -> RunTaskResponse:
93
- # Customer function code never raises an exception because we catch all of them and add
94
- # their details to the response. We can only get an exception here if our own code failed.
95
- # If our code raises an exception the grpc framework converts it into GRPC_STATUS_UNKNOWN
96
- # error with the exception message. Differentiating errors is not needed for now.
97
- RunTaskRequestValidator(request=request).check()
98
- self._check_task_routed_correctly(request)
99
-
100
- return RunTaskHandler(
101
- request=request,
102
- graph_name=self._graph_name,
103
- graph_version=self._graph_version,
104
- function_name=self._function_name,
105
- invocation_state=ProxiedInvocationState(
106
- request.task_id, self._invocation_state_proxy_server
107
- ),
108
- function_wrapper=self._function_wrapper,
109
- logger=self._logger,
110
- ).run()
111
-
112
- def _check_task_routed_correctly(self, request: RunTaskRequest):
113
- # Fail with internal error as this happened due to wrong task routing to this Server.
114
- # If we run the wrongly routed task then it can steal data from this Server if it belongs
115
- # to a different customer.
116
- if request.namespace != self._namespace:
117
- raise ValueError(
118
- f"This Function Executor is not initialized for this namespace {request.namespace}"
119
- )
120
- if request.graph_name != self._graph_name:
121
- raise ValueError(
122
- f"This Function Executor is not initialized for this graph_name {request.graph_name}"
123
- )
124
- if request.graph_version != self._graph_version:
125
- raise ValueError(
126
- f"This Function Executor is not initialized for this graph_version {request.graph_version}"
127
- )
128
- if request.function_name != self._function_name:
129
- raise ValueError(
130
- f"This Function Executor is not initialized for this function_name {request.function_name}"
131
- )
132
-
133
- def check_health(
134
- self, request: HealthCheckRequest, context: grpc.ServicerContext
135
- ) -> HealthCheckResponse:
136
- # This health check validates that the Server:
137
- # - Has its process alive (not exited).
138
- # - Didn't exhaust its thread pool.
139
- # - Is able to communicate over its server socket.
140
- return HealthCheckResponse(healthy=True)
141
-
142
- def get_info(
143
- self, request: InfoRequest, context: grpc.ServicerContext
144
- ) -> InfoResponse:
145
- return InfoResponse(**info_response_kv_args())
indexify/utils/README.md DELETED
@@ -1,3 +0,0 @@
1
- ## Overview
2
-
3
- Put here common functionality that is useful for code written in Python.
@@ -1,88 +0,0 @@
1
- from typing import Optional, Union
2
-
3
- import httpx
4
- import yaml
5
- from httpx import AsyncClient, Client
6
-
7
-
8
- def get_httpx_client(
9
- config_path: Optional[str] = None, make_async: Optional[bool] = False
10
- ) -> Union[AsyncClient, Client]:
11
- """
12
- Creates and returns an httpx.Client instance, optionally configured with TLS settings from a YAML config file.
13
-
14
- The function creates a basic httpx.Client by default. If a config path is provided and the config specifies
15
- 'use_tls' as True, it creates a TLS-enabled client with HTTP/2 support using the provided certificate settings.
16
- To get https.AsyncClient, provide make_async as True.
17
-
18
- Args:
19
- config_path (Optional[str]): Path to a YAML configuration file. If provided, the file should contain TLS
20
- configuration with the following structure:
21
- {
22
- "use_tls": bool,
23
- "tls_config": {
24
- "cert_path": str, # Path to client certificate
25
- "key_path": str, # Path to client private key
26
- "ca_bundle_path": str # Optional: Path to CA bundle for verification
27
- }
28
- }
29
- make_async (Optional[bool]): Whether to make an asynchronous httpx client instance.
30
-
31
- Returns:
32
- httpx.Client: An initialized httpx client instance, either with basic settings or TLS configuration
33
- if specified in the config file.
34
-
35
- Example:
36
- # Basic client without TLS
37
- client = get_httpx_client()
38
-
39
- # Client with TLS configuration from config file
40
- client = get_httpx_client("/path/to/config.yaml")
41
- """
42
- if config_path:
43
- with open(config_path, "r") as file:
44
- config = yaml.safe_load(file)
45
- if config.get("use_tls", False):
46
- print(f"Configuring client with TLS config: {config}")
47
- tls_config = config["tls_config"]
48
- return get_sync_or_async_client(make_async, **tls_config)
49
- return get_sync_or_async_client(make_async)
50
-
51
-
52
- def get_sync_or_async_client(
53
- make_async: Optional[bool] = False,
54
- cert_path: Optional[str] = None,
55
- key_path: Optional[str] = None,
56
- ca_bundle_path: Optional[str] = None,
57
- ) -> Union[AsyncClient, Client]:
58
- """
59
- Creates and returns either a synchronous or asynchronous httpx client with optional TLS configuration.
60
-
61
- Args:
62
- make_async (Optional[bool]): If True, returns an AsyncClient; if False, returns a synchronous Client.
63
- Defaults to False.
64
- cert_path (Optional[str]): Path to the client certificate file. Required for TLS configuration
65
- when key_path is also provided.
66
- key_path (Optional[str]): Path to the client private key file. Required for TLS configuration
67
- when cert_path is also provided.
68
- ca_bundle_path (Optional[str]): Path to the CA bundle file for certificate verification.
69
- If not provided, defaults to system CA certificates.
70
- """
71
- if make_async:
72
- if cert_path and key_path:
73
- return httpx.AsyncClient(
74
- http2=True,
75
- cert=(cert_path, key_path),
76
- verify=ca_bundle_path if ca_bundle_path else True,
77
- )
78
- else:
79
- return httpx.AsyncClient()
80
- else:
81
- if cert_path and key_path:
82
- return httpx.Client(
83
- http2=True,
84
- cert=(cert_path, key_path),
85
- verify=ca_bundle_path if ca_bundle_path else True,
86
- )
87
- else:
88
- return httpx.Client()
indexify/utils/logging.py DELETED
@@ -1,66 +0,0 @@
1
- import logging
2
- import sys
3
-
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
8
-
9
- # Using this module allows us to be consistent with the logging configuration across all Python programs.
10
-
11
-
12
- def configure_logging_early():
13
- """Configures standard Python logging module.
14
-
15
- By default 3rd party modules that are using standard Python logging module
16
- (logging.getLogger()) have their log lines dropped unless the module gets configured.
17
-
18
- Not dropping log lines from 3rd party modules is useful for debugging. E.g. this helps
19
- debugging errors in grpc servers if exceptions happen inside grpc module code.
20
- """
21
- logging.basicConfig(
22
- level=logging.WARNING,
23
- # This log message format is a bit similar to the default structlog format.
24
- format="%(asctime)s [%(levelname)s] %(message)s logger=%(name)s",
25
- datefmt="%Y-%m-%d %H:%M:%S",
26
- handlers=[logging.StreamHandler(sys.stdout)],
27
- )
28
-
29
-
30
- def configure_development_mode_logging():
31
- processors = [
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,
49
- structlog.processors.JSONRenderer(),
50
- ]
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)
@@ -1,47 +0,0 @@
1
- indexify/cli/cli.py,sha256=WcQy4QrO2NM4Xfenzb11WzJbC8lOpMgE8GgHAkUNcZE,11504
2
- indexify/executor/README.md,sha256=ozC6_hMkhQQNVCMEpBxwiUALz6lwErPQxNxQfQDqnG4,2029
3
- indexify/executor/api_objects.py,sha256=k5tKYxaWml0sSECoEDzamCYeJnlD7zO2M7E_qGwyMrg,1032
4
- indexify/executor/downloader.py,sha256=Vrq1dAW4BifG62tlqFnImiMxdezIgOZcByTRnhDsnnw,6457
5
- indexify/executor/executor.py,sha256=hyAQKJ80IaPB-A_YRRld4yqYhAifLvMkQ8qYNMQimPI,5892
6
- indexify/executor/function_executor/function_executor.py,sha256=837r91kL1Nt5Ct9LVFdpB89fhtHctV-c2PrgbyVSFlE,5833
7
- indexify/executor/function_executor/function_executor_state.py,sha256=_85dpaudYM0sekOqwjMxKGdK7MNQdTGUhHi67sqVHyY,2853
8
- indexify/executor/function_executor/health_checker.py,sha256=UzAqqWO2y0DLhxm639mTDrEIYNY7gZ3T_zdgPSDuVJ4,2747
9
- indexify/executor/function_executor/invocation_state_client.py,sha256=jxElxnYFfdwCxKfKvQsjLIE-Z_1386wxednJ2pGKSL0,8581
10
- indexify/executor/function_executor/server/client_configuration.py,sha256=gOywMus0cotlX6NKIadEJwvOmBE-LbGE_wvoMi5-HzY,994
11
- indexify/executor/function_executor/server/function_executor_server.py,sha256=_DLivLDikupZusRk8gVWDk7fWPT9XjZ4un1yWSlOObs,883
12
- indexify/executor/function_executor/server/function_executor_server_factory.py,sha256=pGbJMQfC5TNvyWOs6VDKdqd2PK5OHQh5_wSDP-E7DbI,1677
13
- indexify/executor/function_executor/server/subprocess_function_executor_server.py,sha256=JekDOqF7oFD4J6zcN3xB0Dxd1cgpEXMOsb_rKZOeBlI,668
14
- indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py,sha256=FYExuYZZ7CUcznUobtnxvd2hVjUjpB9Dkav0FFcA0hM,4118
15
- indexify/executor/function_executor/single_task_runner.py,sha256=CwLN2pLJpORDjxgxME5-xQCBJ_mzmrdnrzjB7n4sqZo,7794
16
- indexify/executor/function_executor/task_input.py,sha256=8pBRuaQbBBPrDWwByOKZlOaXu6UDmJUO5w-6XxAYSgY,582
17
- indexify/executor/function_executor/task_output.py,sha256=3-qcT1aigmOFEp6QSJtUcQfqeJfrxvo265qgk9WAUVg,1064
18
- indexify/executor/runtime_probes.py,sha256=bo6Dq6AGZpJH099j0DHtVSDEH80tv3j9MXf3VXSx_p8,2182
19
- indexify/executor/task_fetcher.py,sha256=59Cn79bXpbPFEj2bZCVFRaLaNKPAeRyJeiEsZE3F7Ys,2911
20
- indexify/executor/task_reporter.py,sha256=eueJNHYJIwAm8lY8SQJrUOWC-Nk-DPesDis1YTR4k7c,6643
21
- indexify/executor/task_runner.py,sha256=RSFeJYhQ_agXXPBm8u13HErSUPZGsCGwV1stgS7g258,5035
22
- indexify/function_executor/README.md,sha256=TAcbYYe6noUMriaQabJAaZ8a2SAYzlXl7hIdTfULqYY,950
23
- indexify/function_executor/handlers/run_function/function_inputs_loader.py,sha256=StSJCp-kkOWUuUIzONnoqtcB37nzBYGcIVy2oTEwOIQ,1588
24
- indexify/function_executor/handlers/run_function/handler.py,sha256=-GPM9G9GkkJtmB776RPKReFnus5hMoAw6IC0rV2WE5s,5209
25
- indexify/function_executor/handlers/run_function/request_validator.py,sha256=GS7_zxAlyNg0vpUrhot-DpVWFyI9Y9P8jvb7UuO4b1A,856
26
- indexify/function_executor/handlers/run_function/response_helper.py,sha256=FJVl-LyoRBx9HRaOo_umveiWzuh4anO7aXUmEMEki20,3074
27
- indexify/function_executor/info.py,sha256=kR_i84pLqAQI5AKLYuXg3mEaVIMmHZK-Hx8Dmv-_slA,454
28
- indexify/function_executor/initialize_request_validator.py,sha256=agYWGRHUC-7IuYtm9NPjcVo5SVOWM4PxewA93dqdkJM,682
29
- indexify/function_executor/invocation_state/invocation_state_proxy_server.py,sha256=YEnxvWV8NFVK_CxHI_C-BNizuagalY3ieN62IOxNttU,7023
30
- indexify/function_executor/invocation_state/proxied_invocation_state.py,sha256=rjZ2192bSXonNKkaDaByeOL-wVx6x6Qrtio0UVzGSz8,944
31
- indexify/function_executor/invocation_state/response_validator.py,sha256=05Y9_5s010owaDb6OUia9W9Alx1r1zJ179HboEkT-Xk,896
32
- indexify/function_executor/main.py,sha256=LvcEAPPi-yy2eyatNssihcJRXjAzz5GCcMftvLF9ciU,1224
33
- indexify/function_executor/proto/function_executor.proto,sha256=GZ2cAkwrNQTC6GRFTckmyGo3P-ywgY8ZKsVuuQL-x8c,4915
34
- indexify/function_executor/proto/function_executor_pb2.py,sha256=MtvY7kAxf-O6zu6XUkV3-IBew3Np19ceuPtmk-sxWsQ,8559
35
- indexify/function_executor/proto/function_executor_pb2.pyi,sha256=QYZ3MH7Z72-xCsrzyMEeUVCcxRg2mjOIosV2bLlwSAI,8179
36
- indexify/function_executor/proto/function_executor_pb2_grpc.py,sha256=OGSzzbZKtOSNGemTJLX0L96_jkxUiZSYJQM56LHzZ-o,12734
37
- indexify/function_executor/proto/message_validator.py,sha256=OKXPYgy5L9c-spnV9Zjv7PA_yxwzvykfhbYylYx8cwQ,1456
38
- indexify/function_executor/proto/server_configuration.py,sha256=FzrusxLU62IfvbZ42IjwmPROsDQMi5mCOu41hRA4E7s,1052
39
- indexify/function_executor/server.py,sha256=gOAl_-cT8Z4yC_bjD4adaHY4EzsjRm9RuykeCNGp8Mc,1068
40
- indexify/function_executor/service.py,sha256=OUqlh0lirRbHNsgpDOEwbaGpDptAs1-GoeKveYCq7zk,6506
41
- indexify/utils/README.md,sha256=2g8-H9GopacOW4YrViZc0QsaJPtK-Fox7GyfX01kcDk,86
42
- indexify/utils/http_client.py,sha256=deMlmAu4E_ZXV3blCdWNag3uO_cyD-GsMZjFFmO5r7s,3541
43
- indexify/utils/logging.py,sha256=c6NwzY7uVHMRJc8f2w2KF36rNkeZVoQfGdq7suIg9s8,2025
44
- indexify-0.3.5.dist-info/METADATA,sha256=bn5MHa523My7wk17i-8_ev8hnFrhABt1Q4GLXcsoKpk,1373
45
- indexify-0.3.5.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
46
- indexify-0.3.5.dist-info/entry_points.txt,sha256=pJG0YRnypesbiNJHuObfHEkjk0p_ZvEDTyyTH0kGVTY,108
47
- indexify-0.3.5.dist-info/RECORD,,
@@ -1,4 +0,0 @@
1
- [console_scripts]
2
- function-executor=indexify.function_executor.main:main
3
- indexify-cli=indexify.cli.cli:app
4
-