indexify 0.3.11__py3-none-any.whl → 0.3.13__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 +13 -3
- indexify/executor/executor.py +24 -16
- indexify/executor/function_executor/function_executor.py +28 -1
- indexify/executor/function_executor/metrics/function_executor.py +16 -0
- indexify/executor/metrics/executor.py +10 -1
- {indexify-0.3.11.dist-info → indexify-0.3.13.dist-info}/METADATA +2 -9
- {indexify-0.3.11.dist-info → indexify-0.3.13.dist-info}/RECORD +9 -9
- {indexify-0.3.11.dist-info → indexify-0.3.13.dist-info}/WHEEL +0 -0
- {indexify-0.3.11.dist-info → indexify-0.3.13.dist-info}/entry_points.txt +0 -0
indexify/cli/cli.py
CHANGED
@@ -7,6 +7,7 @@ from tensorlake.utils.logging import (
|
|
7
7
|
configure_logging_early()
|
8
8
|
|
9
9
|
import os
|
10
|
+
import re
|
10
11
|
import shutil
|
11
12
|
import signal
|
12
13
|
import subprocess
|
@@ -185,6 +186,9 @@ def executor(
|
|
185
186
|
executor_cache: Optional[str] = typer.Option(
|
186
187
|
"~/.indexify/executor_cache", help="Path to the executor cache directory"
|
187
188
|
),
|
189
|
+
executor_id: Optional[str] = typer.Option(
|
190
|
+
None, help="ID of the executor, if not provided, a random ID will be generated"
|
191
|
+
),
|
188
192
|
# Registred ports range ends at 49151.
|
189
193
|
ports: Tuple[int, int] = typer.Option(
|
190
194
|
(50000, 51000),
|
@@ -221,9 +225,15 @@ def executor(
|
|
221
225
|
"At least one function must be specified when not running in development mode"
|
222
226
|
)
|
223
227
|
|
228
|
+
if executor_id is None:
|
229
|
+
executor_id = nanoid.generate()
|
230
|
+
elif not re.compile(r"^[a-zA-Z0-9_-]{10,}$").match(executor_id):
|
231
|
+
raise typer.BadParameter(
|
232
|
+
"--executor-id should be at least 10 characters long and only include characters _-[0-9][a-z][A-Z]"
|
233
|
+
)
|
234
|
+
|
224
235
|
executor_version = version("indexify")
|
225
|
-
|
226
|
-
logger = structlog.get_logger(module=__name__, executor_id=id)
|
236
|
+
logger = structlog.get_logger(module=__name__, executor_id=executor_id)
|
227
237
|
|
228
238
|
logger.info(
|
229
239
|
"starting executor",
|
@@ -262,7 +272,7 @@ def executor(
|
|
262
272
|
)
|
263
273
|
|
264
274
|
Executor(
|
265
|
-
id=
|
275
|
+
id=executor_id,
|
266
276
|
version=executor_version,
|
267
277
|
health_checker=GenericHealthChecker(),
|
268
278
|
code_path=executor_cache,
|
indexify/executor/executor.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import asyncio
|
2
2
|
import signal
|
3
|
+
import time
|
3
4
|
from pathlib import Path
|
4
5
|
from socket import gethostname
|
5
6
|
from typing import Any, Dict, List, Optional
|
@@ -23,6 +24,7 @@ from .metrics.executor import (
|
|
23
24
|
METRIC_TASKS_COMPLETED_OUTCOME_SUCCESS,
|
24
25
|
metric_executor_info,
|
25
26
|
metric_executor_state,
|
27
|
+
metric_task_completion_latency,
|
26
28
|
metric_task_outcome_report_latency,
|
27
29
|
metric_task_outcome_report_retries,
|
28
30
|
metric_task_outcome_reports,
|
@@ -157,26 +159,12 @@ class Executor:
|
|
157
159
|
"""Runs the supplied task.
|
158
160
|
|
159
161
|
Doesn't raise any Exceptions. All errors are reported to the server."""
|
162
|
+
start_time: float = time.monotonic()
|
160
163
|
logger = self._task_logger(task)
|
161
164
|
output: Optional[TaskOutput] = None
|
162
165
|
|
163
166
|
try:
|
164
|
-
|
165
|
-
input: SerializedObject = await self._downloader.download_input(task)
|
166
|
-
init_value: Optional[SerializedObject] = (
|
167
|
-
None
|
168
|
-
if task.reducer_output_id is None
|
169
|
-
else (await self._downloader.download_init_value(task))
|
170
|
-
)
|
171
|
-
output: TaskOutput = await self._task_runner.run(
|
172
|
-
TaskInput(
|
173
|
-
task=task,
|
174
|
-
graph=graph,
|
175
|
-
input=input,
|
176
|
-
init_value=init_value,
|
177
|
-
),
|
178
|
-
logger=logger,
|
179
|
-
)
|
167
|
+
output = await self._run_task_and_get_output(task, logger)
|
180
168
|
logger.info("task execution finished", success=output.success)
|
181
169
|
except Exception as e:
|
182
170
|
output = TaskOutput.internal_error(task)
|
@@ -189,6 +177,26 @@ class Executor:
|
|
189
177
|
metric_task_outcome_reports.inc()
|
190
178
|
await self._report_task_outcome(output=output, logger=logger)
|
191
179
|
|
180
|
+
metric_task_completion_latency.observe(time.monotonic() - start_time)
|
181
|
+
|
182
|
+
async def _run_task_and_get_output(self, task: Task, logger: Any) -> TaskOutput:
|
183
|
+
graph: SerializedObject = await self._downloader.download_graph(task)
|
184
|
+
input: SerializedObject = await self._downloader.download_input(task)
|
185
|
+
init_value: Optional[SerializedObject] = (
|
186
|
+
None
|
187
|
+
if task.reducer_output_id is None
|
188
|
+
else (await self._downloader.download_init_value(task))
|
189
|
+
)
|
190
|
+
return await self._task_runner.run(
|
191
|
+
TaskInput(
|
192
|
+
task=task,
|
193
|
+
graph=graph,
|
194
|
+
input=input,
|
195
|
+
init_value=init_value,
|
196
|
+
),
|
197
|
+
logger=logger,
|
198
|
+
)
|
199
|
+
|
192
200
|
async def _report_task_outcome(self, output: TaskOutput, logger: Any) -> None:
|
193
201
|
"""Reports the task with the given output to the server.
|
194
202
|
|
@@ -3,12 +3,15 @@ from typing import Any, Optional
|
|
3
3
|
|
4
4
|
import grpc
|
5
5
|
from tensorlake.function_executor.proto.function_executor_pb2 import (
|
6
|
+
InfoRequest,
|
7
|
+
InfoResponse,
|
6
8
|
InitializeRequest,
|
7
9
|
InitializeResponse,
|
8
10
|
)
|
9
11
|
from tensorlake.function_executor.proto.function_executor_pb2_grpc import (
|
10
12
|
FunctionExecutorStub,
|
11
13
|
)
|
14
|
+
from tensorlake.function_executor.proto.message_validator import MessageValidator
|
12
15
|
from tensorlake.utils.http_client import get_httpx_client
|
13
16
|
|
14
17
|
from .health_checker import HealthChecker
|
@@ -36,7 +39,10 @@ from .metrics.function_executor import (
|
|
36
39
|
metric_destroys,
|
37
40
|
metric_establish_channel_errors,
|
38
41
|
metric_establish_channel_latency,
|
42
|
+
metric_function_executor_infos,
|
39
43
|
metric_function_executors_count,
|
44
|
+
metric_get_info_rpc_errors,
|
45
|
+
metric_get_info_rpc_latency,
|
40
46
|
metric_initialize_rpc_errors,
|
41
47
|
metric_initialize_rpc_latency,
|
42
48
|
)
|
@@ -96,6 +102,7 @@ class FunctionExecutor:
|
|
96
102
|
await self._create_server(config)
|
97
103
|
await self._establish_channel()
|
98
104
|
stub: FunctionExecutorStub = FunctionExecutorStub(self._channel)
|
105
|
+
await _collect_server_info(stub)
|
99
106
|
await _initialize_server(stub, initialize_request)
|
100
107
|
await self._create_invocation_state_client(
|
101
108
|
stub=stub,
|
@@ -262,9 +269,29 @@ class FunctionExecutor:
|
|
262
269
|
self._health_checker = None
|
263
270
|
|
264
271
|
|
272
|
+
async def _collect_server_info(stub: FunctionExecutorStub) -> None:
|
273
|
+
with (
|
274
|
+
metric_get_info_rpc_errors.count_exceptions(),
|
275
|
+
metric_get_info_rpc_latency.time(),
|
276
|
+
):
|
277
|
+
info: InfoResponse = await stub.get_info(InfoRequest())
|
278
|
+
validator = MessageValidator(info)
|
279
|
+
validator.required_field("version")
|
280
|
+
validator.required_field("sdk_version")
|
281
|
+
validator.required_field("sdk_language")
|
282
|
+
validator.required_field("sdk_language_version")
|
283
|
+
|
284
|
+
metric_function_executor_infos.labels(
|
285
|
+
version=info.version,
|
286
|
+
sdk_version=info.sdk_version,
|
287
|
+
sdk_language=info.sdk_language,
|
288
|
+
sdk_language_version=info.sdk_language_version,
|
289
|
+
).inc()
|
290
|
+
|
291
|
+
|
265
292
|
async def _initialize_server(
|
266
293
|
stub: FunctionExecutorStub, initialize_request: InitializeRequest
|
267
|
-
):
|
294
|
+
) -> None:
|
268
295
|
with (
|
269
296
|
metric_initialize_rpc_errors.count_exceptions(),
|
270
297
|
metric_initialize_rpc_latency.time(),
|
@@ -78,6 +78,22 @@ metric_destroy_channel_errors: prometheus_client.Counter = prometheus_client.Cou
|
|
78
78
|
"Number of Function Executor channel destruction errors",
|
79
79
|
)
|
80
80
|
|
81
|
+
# FE get_info RPC metrics.
|
82
|
+
metric_get_info_rpc_latency: prometheus_client.Histogram = (
|
83
|
+
latency_metric_for_fast_operation(
|
84
|
+
"function_executor_get_info_rpc", "Function Executor get_info RPC"
|
85
|
+
)
|
86
|
+
)
|
87
|
+
metric_get_info_rpc_errors: prometheus_client.Counter = prometheus_client.Counter(
|
88
|
+
"function_executor_get_info_rpc_errors",
|
89
|
+
"Number of Function Executor get_info RPC errors",
|
90
|
+
)
|
91
|
+
metric_function_executor_infos: prometheus_client.Counter = prometheus_client.Counter(
|
92
|
+
"function_executor_infos",
|
93
|
+
"Number of Function Executors with particular info",
|
94
|
+
["version", "sdk_version", "sdk_language", "sdk_language_version"],
|
95
|
+
)
|
96
|
+
|
81
97
|
# FE initialization RPC metrics.
|
82
98
|
metric_initialize_rpc_latency: prometheus_client.Histogram = (
|
83
99
|
latency_metric_for_customer_controlled_operation(
|
@@ -1,6 +1,9 @@
|
|
1
1
|
import prometheus_client
|
2
2
|
|
3
|
-
from ..monitoring.metrics import
|
3
|
+
from ..monitoring.metrics import (
|
4
|
+
latency_metric_for_customer_controlled_operation,
|
5
|
+
latency_metric_for_fast_operation,
|
6
|
+
)
|
4
7
|
|
5
8
|
# This file contains all metrics used by Executor.
|
6
9
|
|
@@ -31,6 +34,12 @@ metric_tasks_completed.labels(
|
|
31
34
|
outcome=METRIC_TASKS_COMPLETED_OUTCOME_ERROR_CUSTOMER_CODE
|
32
35
|
)
|
33
36
|
metric_tasks_completed.labels(outcome=METRIC_TASKS_COMPLETED_OUTCOME_ERROR_PLATFORM)
|
37
|
+
metric_task_completion_latency: prometheus_client.Histogram = (
|
38
|
+
latency_metric_for_customer_controlled_operation(
|
39
|
+
"task_completion",
|
40
|
+
"task completion from the moment it got fetched until its outcome got reported",
|
41
|
+
)
|
42
|
+
)
|
34
43
|
|
35
44
|
# Task outcome reporting metrics.
|
36
45
|
metric_task_outcome_reports: prometheus_client.Counter = prometheus_client.Counter(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: indexify
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.13
|
4
4
|
Summary: Open Source Indexify components and helper tools
|
5
5
|
Home-page: https://github.com/tensorlakeai/indexify
|
6
6
|
License: Apache 2.0
|
@@ -15,16 +15,9 @@ Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
17
17
|
Requires-Dist: aiohttp (>=3.11.0,<4.0.0)
|
18
|
-
Requires-Dist: grpcio (==1.70.0)
|
19
|
-
Requires-Dist: httpx-sse (>=0.4.0,<0.5.0)
|
20
|
-
Requires-Dist: httpx[http2] (>=0.27,<0.28)
|
21
|
-
Requires-Dist: nanoid (>=2.0.0,<3.0.0)
|
22
18
|
Requires-Dist: prometheus-client (>=0.21.1,<0.22.0)
|
23
|
-
Requires-Dist: pydantic (==2.10.4)
|
24
|
-
Requires-Dist: pyyaml (>=6,<7)
|
25
19
|
Requires-Dist: rich (>=13.9.2,<14.0.0)
|
26
|
-
Requires-Dist:
|
27
|
-
Requires-Dist: tensorlake (>=0.1.20)
|
20
|
+
Requires-Dist: tensorlake (>=0.1)
|
28
21
|
Requires-Dist: typer (>=0.12,<0.13)
|
29
22
|
Project-URL: Repository, https://github.com/tensorlakeai/indexify
|
30
23
|
Description-Content-Type: text/markdown
|
@@ -1,14 +1,14 @@
|
|
1
|
-
indexify/cli/cli.py,sha256=
|
1
|
+
indexify/cli/cli.py,sha256=SQOVWIr-ZNPilFAVQw1qRC42V8T0VEbVt_E1eClsnpM,10946
|
2
2
|
indexify/executor/README.md,sha256=ozC6_hMkhQQNVCMEpBxwiUALz6lwErPQxNxQfQDqnG4,2029
|
3
3
|
indexify/executor/api_objects.py,sha256=TaYwDoo7EjuLBusxH512-KdvAJRtBwbEP2IObWraabU,1100
|
4
4
|
indexify/executor/downloader.py,sha256=XjaGCzsGM3ex2HxbKGkIsB50OhlXgdnywWGCjUBdW2k,8127
|
5
|
-
indexify/executor/executor.py,sha256=
|
6
|
-
indexify/executor/function_executor/function_executor.py,sha256=
|
5
|
+
indexify/executor/executor.py,sha256=r5do6k7Izp9SIzebgOn2psYjzKZmNqHx3iuTW3vWrhg,10035
|
6
|
+
indexify/executor/function_executor/function_executor.py,sha256=sQ5FOdrjybDDsjagghlfjV06IXTpWWDBSTHqQXI-w9M,11245
|
7
7
|
indexify/executor/function_executor/function_executor_state.py,sha256=IWPLWa7LaN0Eq8PDu-0kFzkuKJB0COShu7wCO1oyiNA,3141
|
8
8
|
indexify/executor/function_executor/function_executor_states_container.py,sha256=x4hlF7ZBWswk9dkA06Rvgeqar6H9TWjZ7Etyy2CzBDE,2682
|
9
9
|
indexify/executor/function_executor/health_checker.py,sha256=YT24ajPLdYOpdt2UNyJGviGbivCDXIJpeQOxQofcl50,3258
|
10
10
|
indexify/executor/function_executor/invocation_state_client.py,sha256=p-xgM4__cHR1ApvMV9hShrGWee_Je0VDhICZUGjpQY4,9644
|
11
|
-
indexify/executor/function_executor/metrics/function_executor.py,sha256=
|
11
|
+
indexify/executor/function_executor/metrics/function_executor.py,sha256=KHzf4cMh_HqnOAE7TZ6_oIqUH3nExOkt9LSekAEN69w,6304
|
12
12
|
indexify/executor/function_executor/metrics/function_executor_state.py,sha256=M7cMA7JY8_8FW9xjuSqtp6o2xxUgB31LJowo7kzcexg,352
|
13
13
|
indexify/executor/function_executor/metrics/function_executor_state_container.py,sha256=6rrAfml-TivjkHatCM4BLY7jmVs523Wzb6QIysncc-0,302
|
14
14
|
indexify/executor/function_executor/metrics/health_checker.py,sha256=EaeIYJPrQ-qqNMGZVGkvjPoeQSCl4FzPKXEv3Cly1NE,456
|
@@ -23,7 +23,7 @@ indexify/executor/function_executor/single_task_runner.py,sha256=Td28vF6pNemKZEs
|
|
23
23
|
indexify/executor/function_executor/task_input.py,sha256=wSrHR4m0juiGClQyeVdhRC37QzDt6Rrjq-ZXJkfBi9k,584
|
24
24
|
indexify/executor/function_executor/task_output.py,sha256=Qg7vojYi0WmeHRf2qlC-5h46jcwis13EgiN63OmWpcg,1229
|
25
25
|
indexify/executor/metrics/downloader.py,sha256=lctPh8xjkXeLEFJnl1hNrD1yEhLhIl5sggsR4Yoe_Zc,2746
|
26
|
-
indexify/executor/metrics/executor.py,sha256=
|
26
|
+
indexify/executor/metrics/executor.py,sha256=ua-Vv_k1CB4juJdF7tEBQbBMksqWAA3iXKKMKXZUCLk,2369
|
27
27
|
indexify/executor/metrics/task_fetcher.py,sha256=iJEwCLzYr2cuz7hRvNiqaa2nvQP4OrA0hm0iJY0YKG0,736
|
28
28
|
indexify/executor/metrics/task_reporter.py,sha256=zUA9RpkSgx5lG_ZqDDuela5VuhtsnC0IKoQcEvHND0Y,730
|
29
29
|
indexify/executor/metrics/task_runner.py,sha256=o5ERNePKPmVKknFoSZUr-r597dEOOWvWn3ocbiL2jxI,1699
|
@@ -40,7 +40,7 @@ indexify/executor/runtime_probes.py,sha256=bo6Dq6AGZpJH099j0DHtVSDEH80tv3j9MXf3V
|
|
40
40
|
indexify/executor/task_fetcher.py,sha256=NpFfHgaY99bSL-K2D5kcDAMNUG2FArq0-qF_mgF-LBQ,3375
|
41
41
|
indexify/executor/task_reporter.py,sha256=t7FzSKV7fG1fEtxyTcFh-sTWZ8WXApbG-qXaAMq_gRQ,7363
|
42
42
|
indexify/executor/task_runner.py,sha256=tcS7hHdSVQexC3XEIsDTwX51bJK4iSQqC8CbWeNoud0,5590
|
43
|
-
indexify-0.3.
|
44
|
-
indexify-0.3.
|
45
|
-
indexify-0.3.
|
46
|
-
indexify-0.3.
|
43
|
+
indexify-0.3.13.dist-info/METADATA,sha256=zaJ7N4LFWTxgUPXsA01xxhPY8Dvo8D7tcPwNH6x2F5U,1158
|
44
|
+
indexify-0.3.13.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
|
45
|
+
indexify-0.3.13.dist-info/entry_points.txt,sha256=GU9wmsgvN7nQw3N2X0PMYn1RSvF6CrhH9RuC2D8d3Gk,53
|
46
|
+
indexify-0.3.13.dist-info/RECORD,,
|
File without changes
|
File without changes
|