indexify 0.3.10__py3-none-any.whl → 0.3.12__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 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
@@ -25,7 +26,7 @@ import typer
25
26
  from rich.console import Console
26
27
  from rich.text import Text
27
28
  from rich.theme import Theme
28
- from tensorlake.functions_sdk.image import GetDefaultPythonImage, Image
29
+ from tensorlake.functions_sdk.image import Image
29
30
 
30
31
  from indexify.executor.api_objects import FunctionURI
31
32
  from indexify.executor.executor import Executor
@@ -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
- id = nanoid.generate()
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=id,
275
+ id=executor_id,
266
276
  version=executor_version,
267
277
  health_checker=GenericHealthChecker(),
268
278
  code_path=executor_cache,
@@ -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
- graph: SerializedObject = await self._downloader.download_graph(task)
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
 
@@ -28,8 +28,7 @@ class SubprocessFunctionExecutorServerFactory(FunctionExecutorServerFactory):
28
28
  try:
29
29
  port = self._allocate_port()
30
30
  args = [
31
- "--executor-id",
32
- config.executor_id,
31
+ f"--executor-id={config.executor_id}", # use = as executor_id can start with -
33
32
  "--address",
34
33
  _server_address(port),
35
34
  ]
@@ -1,6 +1,9 @@
1
1
  import prometheus_client
2
2
 
3
- from ..monitoring.metrics import latency_metric_for_fast_operation
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.10
3
+ Version: 0.3.12
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: structlog (>=24.4.0,<25.0.0)
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,8 +1,8 @@
1
- indexify/cli/cli.py,sha256=ssXc0zalHS7vbCvetZ0cX4BkxIuPIw590jam3c2YVME,10532
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=hij_EkB1_lueakCf3pfi_0O3wxSLYFBkvbpwlsMm-ao,9784
5
+ indexify/executor/executor.py,sha256=r5do6k7Izp9SIzebgOn2psYjzKZmNqHx3iuTW3vWrhg,10035
6
6
  indexify/executor/function_executor/function_executor.py,sha256=BxNhsW0uXxKjdKT5ixMAyIo5F7otdIT2c0FMQ09Lsrs,10234
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
@@ -18,12 +18,12 @@ indexify/executor/function_executor/server/client_configuration.py,sha256=gOywMu
18
18
  indexify/executor/function_executor/server/function_executor_server.py,sha256=_DLivLDikupZusRk8gVWDk7fWPT9XjZ4un1yWSlOObs,883
19
19
  indexify/executor/function_executor/server/function_executor_server_factory.py,sha256=oBEuOwuGsZrvOZsv9v8M4JEtfproirE-cH28XCr0HoY,1739
20
20
  indexify/executor/function_executor/server/subprocess_function_executor_server.py,sha256=JekDOqF7oFD4J6zcN3xB0Dxd1cgpEXMOsb_rKZOeBlI,668
21
- indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py,sha256=xm_EL2Gouwi0qAuKsyJVAQJRBZ0VB-NYsWUM4mOi3nQ,4187
21
+ indexify/executor/function_executor/server/subprocess_function_executor_server_factory.py,sha256=xbH0-73tBM-i0dh1x_k0fDrNAi8WgDKjqiQ9xveU4Zg,4214
22
22
  indexify/executor/function_executor/single_task_runner.py,sha256=Td28vF6pNemKZEs4mNWeLKzy22XRmmMVgp2ipYO_OXU,9262
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=UkJTa8NerbdC1p7jrwl4obLUS2xGSzEYwONPZpoKhT0,2064
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.10.dist-info/METADATA,sha256=WZfdgioEIs_yVFdyELZb9NLcHeKxgsxmxouLpKsZpZM,1428
44
- indexify-0.3.10.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
45
- indexify-0.3.10.dist-info/entry_points.txt,sha256=GU9wmsgvN7nQw3N2X0PMYn1RSvF6CrhH9RuC2D8d3Gk,53
46
- indexify-0.3.10.dist-info/RECORD,,
43
+ indexify-0.3.12.dist-info/METADATA,sha256=OkLYjGB3yomMTO21dsw1YR5q3swzqRsaWvsOzrPQTKg,1158
44
+ indexify-0.3.12.dist-info/WHEEL,sha256=RaoafKOydTQ7I_I3JTrPCg6kUmTgtm4BornzOqyEfJ8,88
45
+ indexify-0.3.12.dist-info/entry_points.txt,sha256=GU9wmsgvN7nQw3N2X0PMYn1RSvF6CrhH9RuC2D8d3Gk,53
46
+ indexify-0.3.12.dist-info/RECORD,,