dagster-ray 0.2.0.post7.dev0__tar.gz → 0.2.0.post10.dev0__tar.gz
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.
- dagster_ray-0.2.0.post10.dev0/.claude/settings.local.json +12 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/CHANDELOG.md +9 -3
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/PKG-INFO +1 -1
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/pyproject.toml +1 -3
- dagster_ray-0.2.0.post10.dev0/src/dagster_ray/_version.py +1 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/base.py +0 -5
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/raycluster.py +2 -11
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/resources.py +0 -1
- dagster_ray-0.2.0.post7.dev0/dagster_ray/_base/resources.py +0 -293
- dagster_ray-0.2.0.post7.dev0/src/dagster_ray/_version.py +0 -1
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.basedpyright/baseline.json +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.dockerignore +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.github/workflows/CI.yml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.github/workflows/release.yml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.gitignore +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.pre-commit-config.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/Dockerfile +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/LICENSE +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/README.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api/core.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api/kuberay.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/assets/stylesheets/extra.css +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/contributing/documentation.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/index.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/external.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/index.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/kuberay.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/Dockerfile +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/README.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/dagster.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/definitions.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/docker-compose.yml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/workspace.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/README.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/dagster.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/definitions.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/workspace.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/README.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/dagster.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/definitions.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/workspace.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/README.md +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/dagster.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/definitions.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/workspace.yaml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/flake.lock +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/flake.nix +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/justfile +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/mkdocs.yml +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/renovate.json +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/scripts/check_deps.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/constants.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/resources.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/config.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/executor.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/io_manager.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/base.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/raycluster/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/raycluster/client.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/rayjob/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/rayjob/client.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/configs.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/jobs.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/ops.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/pipes.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/rayjob.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/schedules.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/pipes.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/py.typed +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/run_launcher.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/types.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/conftest.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/example.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/examples/test_examples.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/__init__.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/__snapshots__/test_utils.ambr +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/conftest.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_interactive_rayjob.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_pipes.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_raycluster.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/scripts/launch_dagster_run_with_kuberay_interactive_job.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/scripts/remote_job.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_executor.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_io_manager.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_pipes.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_resources.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/utils.py +0 -0
- {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/uv.lock +0 -0
|
@@ -5,20 +5,26 @@ All notable user-facing changes to `dagster-ray` will be documented in this file
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.2.1
|
|
9
|
+
|
|
10
|
+
### Fixes
|
|
11
|
+
|
|
12
|
+
- Fixed broken wheel on PyPI
|
|
13
|
+
|
|
8
14
|
## 0.2.0
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
### Changed
|
|
11
17
|
- `KubeRayInteractiveJob.deletion_strategy` now defaults to `DeleteCluster` for both successful and failed executions. This is a reasonable default for the use case.
|
|
12
18
|
- `KubeRayInteractiveJob.ttl_seconds_after_finished` now defaults to `600` seconds.
|
|
13
19
|
- `KubeRayCluster.lifecycle.cleanup` now defaults to `always`
|
|
14
20
|
- [:bomb: breaking] `RayJob` and `RayCluster` clients and resources Kubernetes init parameters have been renamed to `kube_config` and `kube_context`.
|
|
15
21
|
|
|
16
|
-
|
|
22
|
+
### Added
|
|
17
23
|
- new `enable_legacy_debugger` configuration parameter to subclasses of `RayResource`
|
|
18
24
|
- new `on_exception` option for `lifecycle.cleanup` policy. It's triggered during resource setup/cleanup (including `KeyboardInterrupt`), but not by user `@op`/`@asset` code.
|
|
19
25
|
- `KubeRayInteractiveJob` now respects `lifecycle.cleanup`. It defaults to `on_exception`. Users are advised to rely on built-in `RayJob` cleanup mechanisms, such as `ttlSecondsAfterFinished` and `deletionStrategy`.
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
### Fixes
|
|
22
28
|
- removed `ignore_reinit_error` from `RayResource` init options: it's potentially dangerous, for example in case the user has accidentally connected to another Ray cluster (including local ray) before initializing the resource.
|
|
23
29
|
|
|
24
30
|
## 0.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dagster-ray
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.post10.dev0
|
|
4
4
|
Summary: Dagster integration library for Ray
|
|
5
5
|
Project-URL: GitHub, https://github.com/danielgafni/dagster-ray
|
|
6
6
|
Project-URL: documentation, https://danielgafni.github.io/dagster-ray/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.0.post10.dev0" # managed by hatch
|
|
@@ -2,20 +2,15 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
4
|
from abc import abstractmethod
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
5
|
from uuid import uuid4
|
|
7
6
|
|
|
8
7
|
import dagster as dg
|
|
9
8
|
from pydantic import Field, PrivateAttr
|
|
10
|
-
from ray._private.worker import BaseContext as RayBaseContext # noqa
|
|
11
9
|
|
|
12
10
|
from dagster_ray._base.constants import DEFAULT_DEPLOYMENT_NAME
|
|
13
11
|
from dagster_ray.kuberay.utils import get_k8s_object_name
|
|
14
12
|
from dagster_ray.types import AnyDagsterContext
|
|
15
13
|
|
|
16
|
-
if TYPE_CHECKING:
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
14
|
|
|
20
15
|
class BaseKubeRayResourceConfig(dg.Config):
|
|
21
16
|
image: str | None = Field(
|
|
@@ -1,26 +1,17 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
from typing import Optional
|
|
3
2
|
|
|
4
3
|
import dagster as dg
|
|
5
4
|
from pydantic import Field, PrivateAttr
|
|
6
5
|
from typing_extensions import override
|
|
7
6
|
|
|
7
|
+
from dagster_ray._base.resources import BaseRayResource, Lifecycle
|
|
8
8
|
from dagster_ray.kuberay.client import RayClusterClient
|
|
9
|
+
from dagster_ray.kuberay.client.base import load_kubeconfig
|
|
9
10
|
from dagster_ray.kuberay.configs import RayClusterConfig
|
|
10
11
|
from dagster_ray.kuberay.resources.base import BaseKubeRayResourceConfig
|
|
11
12
|
from dagster_ray.kuberay.utils import normalize_k8s_label_values
|
|
12
13
|
from dagster_ray.types import AnyDagsterContext
|
|
13
14
|
|
|
14
|
-
if sys.version_info >= (3, 11):
|
|
15
|
-
pass
|
|
16
|
-
else:
|
|
17
|
-
pass
|
|
18
|
-
|
|
19
|
-
from ray._private.worker import BaseContext as RayBaseContext # noqa
|
|
20
|
-
|
|
21
|
-
from dagster_ray._base.resources import BaseRayResource, Lifecycle
|
|
22
|
-
from dagster_ray.kuberay.client.base import load_kubeconfig
|
|
23
|
-
|
|
24
15
|
|
|
25
16
|
class KubeRayClusterClientResource(dg.ConfigurableResource[RayClusterClient]):
|
|
26
17
|
"""This configurable resource provides a `dagster_ray.kuberay.client.RayClusterClient`."""
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import contextlib
|
|
4
|
-
from abc import ABC, abstractmethod
|
|
5
|
-
from collections.abc import Generator
|
|
6
|
-
from typing import TYPE_CHECKING, Any, Literal, Optional, cast
|
|
7
|
-
|
|
8
|
-
import dagster as dg
|
|
9
|
-
from pydantic import Field, PrivateAttr
|
|
10
|
-
|
|
11
|
-
# yes, `python-client` is actually the KubeRay package name
|
|
12
|
-
# https://github.com/ray-project/kuberay/issues/2078
|
|
13
|
-
from requests.exceptions import ConnectionError
|
|
14
|
-
from tenacity import retry, retry_if_exception_type, stop_after_delay
|
|
15
|
-
from typing_extensions import Self
|
|
16
|
-
|
|
17
|
-
from dagster_ray._base.utils import get_dagster_tags
|
|
18
|
-
from dagster_ray.config import RayDataExecutionOptions
|
|
19
|
-
from dagster_ray.types import AnyDagsterContext
|
|
20
|
-
from dagster_ray.utils import _process_dagster_env_vars, get_current_job_id
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from ray._private.worker import BaseContext as RayBaseContext # noqa
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class Lifecycle(dg.Config):
|
|
27
|
-
create: bool = Field(
|
|
28
|
-
default=True,
|
|
29
|
-
description="Whether to create the resource. If set to `False`, the user can manually call `.create` instead.",
|
|
30
|
-
)
|
|
31
|
-
wait: bool = Field(
|
|
32
|
-
default=True,
|
|
33
|
-
description="Whether to wait for the remote Ray cluster to become ready to accept connections. If set to `False`, the user can manually call `.wait` instead.",
|
|
34
|
-
)
|
|
35
|
-
connect: bool = Field(
|
|
36
|
-
default=True,
|
|
37
|
-
description="Whether to run `ray.init` against the remote Ray cluster. If set to `False`, the user can manually call `.connect` instead.",
|
|
38
|
-
)
|
|
39
|
-
cleanup: Literal["never", "always", "on_exception"] = Field(
|
|
40
|
-
default="always",
|
|
41
|
-
description="Resource cleanup policy. Determines when the resource should be deleted after Dagster step execution or during interruption.",
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class BaseRayResource(dg.ConfigurableResource, ABC):
|
|
46
|
-
"""Base class for Ray Resources providing a common interface for Ray cluster management.
|
|
47
|
-
|
|
48
|
-
This abstract base class defines the interface that all Ray resources must implement,
|
|
49
|
-
providing a backend-agnostic way to interact with Ray clusters. Concrete implementations
|
|
50
|
-
include LocalRay for local development and KubeRay resources for Kubernetes deployments.
|
|
51
|
-
|
|
52
|
-
The BaseRayResource handles the lifecycle of Ray clusters including creation, connection,
|
|
53
|
-
and cleanup, with configurable policies for each stage.
|
|
54
|
-
|
|
55
|
-
Example:
|
|
56
|
-
Use as a type annotation for backend-agnostic code:
|
|
57
|
-
```python
|
|
58
|
-
from dagster import asset
|
|
59
|
-
from dagster_ray import RayResource
|
|
60
|
-
|
|
61
|
-
@asset
|
|
62
|
-
def my_asset(ray_cluster: RayResource):
|
|
63
|
-
# Works with any Ray backend
|
|
64
|
-
import ray
|
|
65
|
-
return ray.get(ray.put("hello"))
|
|
66
|
-
```
|
|
67
|
-
Example:
|
|
68
|
-
Manual lifecycle management:
|
|
69
|
-
```python
|
|
70
|
-
from dagster_ray import Lifecycle
|
|
71
|
-
|
|
72
|
-
ray_resource = SomeRayResource(
|
|
73
|
-
lifecycle=Lifecycle(
|
|
74
|
-
create=False, # Don't auto-create
|
|
75
|
-
connect=False # Don't auto-connect
|
|
76
|
-
)
|
|
77
|
-
)
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Note:
|
|
81
|
-
This is an abstract class and cannot be instantiated directly. Use concrete
|
|
82
|
-
implementations like LocalRay or KubeRayCluster instead.
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
lifecycle: Lifecycle = Field(default_factory=Lifecycle, description="Actions to perform during resource setup.")
|
|
86
|
-
timeout: float = Field(default=600.0, description="Timeout for Ray readiness in seconds")
|
|
87
|
-
ray_init_options: dict[str, Any] = Field(
|
|
88
|
-
default_factory=dict,
|
|
89
|
-
description="Additional keyword arguments to pass to `ray.init()` call, such as `runtime_env`, `num_cpus`, etc. Dagster's `EnvVar` is supported. More details in [Ray docs](https://docs.ray.io/en/latest/ray-core/api/doc/ray.init.html).",
|
|
90
|
-
)
|
|
91
|
-
data_execution_options: RayDataExecutionOptions = Field(default_factory=RayDataExecutionOptions)
|
|
92
|
-
redis_port: int = Field(
|
|
93
|
-
default=10001, description="Redis port for connection. Make sure to match with the actual available port."
|
|
94
|
-
)
|
|
95
|
-
dashboard_port: int = Field(
|
|
96
|
-
default=8265, description="Dashboard port for connection. Make sure to match with the actual available port."
|
|
97
|
-
)
|
|
98
|
-
env_vars: dict[str, str] | None = Field(
|
|
99
|
-
default_factory=dict, description="Environment variables to pass to the Ray cluster."
|
|
100
|
-
)
|
|
101
|
-
enable_tracing: bool = Field(
|
|
102
|
-
default=False,
|
|
103
|
-
description="Enable tracing: inject `RAY_PROFILING=1` and `RAY_task_events_report_interval_ms=0` into the Ray cluster configuration. This allows using `ray.timeline()` to fetch recorded task events. Learn more: https://docs.ray.io/en/latest/ray-core/api/doc/ray.timeline.html#ray-timeline",
|
|
104
|
-
)
|
|
105
|
-
enable_actor_task_logging: bool = Field(
|
|
106
|
-
default=False,
|
|
107
|
-
description="Enable actor task logging: inject `RAY_ENABLE_RECORD_ACTOR_TASK_LOGGING=1` into the Ray cluster configuration.",
|
|
108
|
-
)
|
|
109
|
-
enable_debug_post_mortem: bool = Field(
|
|
110
|
-
default=False,
|
|
111
|
-
description="Enable post-mortem debugging: inject `RAY_DEBUG_POST_MORTEM=1` into the Ray cluster configuration. Learn more: https://docs.ray.io/en/latest/ray-observability/ray-distributed-debugger.html",
|
|
112
|
-
)
|
|
113
|
-
enable_legacy_debugger: bool = Field(
|
|
114
|
-
default=False,
|
|
115
|
-
description="Enable legacy debugger: inject `RAY_DEBUG=legacy` into the Ray cluster configuration. Learn more: https://docs.ray.io/en/latest/ray-observability/user-guides/debug-apps/ray-debugging.html#using-the-ray-debugger",
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
_context: RayBaseContext | None = PrivateAttr()
|
|
119
|
-
|
|
120
|
-
@property
|
|
121
|
-
def context(self) -> RayBaseContext:
|
|
122
|
-
assert self._context is not None, "RayClusterResource not initialized"
|
|
123
|
-
return self._context
|
|
124
|
-
|
|
125
|
-
@property
|
|
126
|
-
@abstractmethod
|
|
127
|
-
def host(self) -> str:
|
|
128
|
-
raise NotImplementedError()
|
|
129
|
-
|
|
130
|
-
@property
|
|
131
|
-
@abstractmethod
|
|
132
|
-
def name(self) -> str:
|
|
133
|
-
raise NotImplementedError()
|
|
134
|
-
|
|
135
|
-
@property
|
|
136
|
-
def display_name(self) -> str:
|
|
137
|
-
return self.name
|
|
138
|
-
|
|
139
|
-
@property
|
|
140
|
-
def ray_address(self) -> str:
|
|
141
|
-
return f"ray://{self.host}:{self.redis_port}"
|
|
142
|
-
|
|
143
|
-
@property
|
|
144
|
-
def dashboard_url(self) -> str:
|
|
145
|
-
return f"http://{self.host}:{self.dashboard_port}"
|
|
146
|
-
|
|
147
|
-
@property
|
|
148
|
-
def runtime_job_id(self) -> str:
|
|
149
|
-
"""
|
|
150
|
-
Returns the Ray Job ID for the current job which was created with `ray.init()`.
|
|
151
|
-
:return:
|
|
152
|
-
"""
|
|
153
|
-
return get_current_job_id()
|
|
154
|
-
|
|
155
|
-
@contextlib.contextmanager
|
|
156
|
-
def yield_for_execution(self, context: dg.InitResourceContext) -> Generator[Self, None, None]:
|
|
157
|
-
exception_occurred = None
|
|
158
|
-
try:
|
|
159
|
-
if self.lifecycle.create:
|
|
160
|
-
self._create(context)
|
|
161
|
-
if self.lifecycle.wait:
|
|
162
|
-
self._wait(context)
|
|
163
|
-
if self.lifecycle.connect:
|
|
164
|
-
self._connect(context)
|
|
165
|
-
yield self
|
|
166
|
-
except BaseException as e:
|
|
167
|
-
exception_occurred = e
|
|
168
|
-
raise
|
|
169
|
-
finally:
|
|
170
|
-
self.cleanup(context, exception_occurred)
|
|
171
|
-
|
|
172
|
-
def _create(self, context: AnyDagsterContext):
|
|
173
|
-
assert context.log is not None
|
|
174
|
-
if not self.created:
|
|
175
|
-
try:
|
|
176
|
-
self.create(context)
|
|
177
|
-
context.log.info(f"Created {self.display_name}.")
|
|
178
|
-
except BaseException:
|
|
179
|
-
context.log.exception(f"Failed to create {self.display_name}")
|
|
180
|
-
raise
|
|
181
|
-
|
|
182
|
-
def _wait(self, context: AnyDagsterContext):
|
|
183
|
-
assert context.log is not None
|
|
184
|
-
self._create(context)
|
|
185
|
-
if not self.ready:
|
|
186
|
-
context.log.info(f"Waiting for {self.display_name} to become ready (timeout={self.timeout:.0f}s)...")
|
|
187
|
-
try:
|
|
188
|
-
self.wait(context)
|
|
189
|
-
except BaseException:
|
|
190
|
-
context.log.exception(f"Failed to wait for {self.display_name} readiness")
|
|
191
|
-
raise
|
|
192
|
-
|
|
193
|
-
def _connect(self, context: AnyDagsterContext):
|
|
194
|
-
assert context.log is not None
|
|
195
|
-
self._wait(context)
|
|
196
|
-
if not self.connected:
|
|
197
|
-
try:
|
|
198
|
-
self.connect(context)
|
|
199
|
-
except BaseException:
|
|
200
|
-
context.log.exception(f"Failed to connect to {self.display_name}")
|
|
201
|
-
raise
|
|
202
|
-
context.log.info(f"Initialized Ray Client with {self.display_name}")
|
|
203
|
-
|
|
204
|
-
def create(self, context: AnyDagsterContext):
|
|
205
|
-
pass
|
|
206
|
-
|
|
207
|
-
def wait(self, context: AnyDagsterContext):
|
|
208
|
-
pass
|
|
209
|
-
|
|
210
|
-
@retry(stop=stop_after_delay(120), retry=retry_if_exception_type(ConnectionError), reraise=True)
|
|
211
|
-
def connect(self, context: AnyDagsterContext) -> RayBaseContext:
|
|
212
|
-
assert context.log is not None
|
|
213
|
-
|
|
214
|
-
import ray
|
|
215
|
-
|
|
216
|
-
init_options = _process_dagster_env_vars(self.ray_init_options.copy())
|
|
217
|
-
|
|
218
|
-
# cleanup None values from runtime_env.env_vars since Ray doesn't like them
|
|
219
|
-
|
|
220
|
-
if "runtime_env" in init_options and "env_vars" in init_options["runtime_env"]:
|
|
221
|
-
init_options["runtime_env"]["env_vars"] = {
|
|
222
|
-
k: v for k, v in init_options["runtime_env"]["env_vars"].items() if v is not None
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
init_options["runtime_env"] = init_options.get("runtime_env", {})
|
|
226
|
-
init_options["runtime_env"]["env_vars"] = init_options["runtime_env"].get("env_vars", {})
|
|
227
|
-
|
|
228
|
-
for var, value in self.get_env_vars_to_inject().items():
|
|
229
|
-
init_options["runtime_env"]["env_vars"][var] = value
|
|
230
|
-
|
|
231
|
-
self.data_execution_options.apply()
|
|
232
|
-
|
|
233
|
-
self._context = ray.init(
|
|
234
|
-
address=self.ray_address,
|
|
235
|
-
**init_options,
|
|
236
|
-
)
|
|
237
|
-
self.data_execution_options.apply()
|
|
238
|
-
self.data_execution_options.apply_remote()
|
|
239
|
-
context.log.info("Initialized Ray in client mode!")
|
|
240
|
-
return cast("RayBaseContext", self._context)
|
|
241
|
-
|
|
242
|
-
def delete(self, context: AnyDagsterContext):
|
|
243
|
-
pass
|
|
244
|
-
|
|
245
|
-
def cleanup(self, context: AnyDagsterContext, exception: Optional[BaseException]): # noqa: UP007
|
|
246
|
-
assert context.log is not None
|
|
247
|
-
|
|
248
|
-
if self.lifecycle.cleanup == "never":
|
|
249
|
-
to_delete = False
|
|
250
|
-
elif not self.created:
|
|
251
|
-
to_delete = False
|
|
252
|
-
elif self.lifecycle.cleanup == "always":
|
|
253
|
-
to_delete = True
|
|
254
|
-
elif self.lifecycle.cleanup == "on_exception":
|
|
255
|
-
to_delete = exception is not None
|
|
256
|
-
else:
|
|
257
|
-
to_delete = False
|
|
258
|
-
|
|
259
|
-
if to_delete:
|
|
260
|
-
self.delete(context)
|
|
261
|
-
context.log.info(f'Deleted {self.display_name} according to cleanup policy "{self.lifecycle.cleanup}"')
|
|
262
|
-
|
|
263
|
-
if self.connected and hasattr(self, "_context") and self._context is not None:
|
|
264
|
-
self._context.disconnect()
|
|
265
|
-
|
|
266
|
-
def get_dagster_tags(self, context: AnyDagsterContext) -> dict[str, str]:
|
|
267
|
-
tags = get_dagster_tags(context)
|
|
268
|
-
return tags
|
|
269
|
-
|
|
270
|
-
def get_env_vars_to_inject(self) -> dict[str, str]:
|
|
271
|
-
vars: dict[str, str] = self.env_vars or {}
|
|
272
|
-
if self.enable_debug_post_mortem:
|
|
273
|
-
vars["RAY_DEBUG_POST_MORTEM"] = "1"
|
|
274
|
-
if self.enable_tracing:
|
|
275
|
-
vars["RAY_PROFILING"] = "1"
|
|
276
|
-
vars["RAY_task_events_report_interval_ms"] = "0"
|
|
277
|
-
if self.enable_actor_task_logging:
|
|
278
|
-
vars["RAY_ENABLE_RECORD_ACTOR_TASK_LOGGING"] = "1"
|
|
279
|
-
if self.enable_legacy_debugger:
|
|
280
|
-
vars["RAY_DEBUG"] = "legacy"
|
|
281
|
-
return vars
|
|
282
|
-
|
|
283
|
-
@property
|
|
284
|
-
def created(self) -> bool:
|
|
285
|
-
return hasattr(self, "_name") and self._name is not None
|
|
286
|
-
|
|
287
|
-
@property
|
|
288
|
-
def ready(self) -> bool:
|
|
289
|
-
return hasattr(self, "_host") and self._host is not None
|
|
290
|
-
|
|
291
|
-
@property
|
|
292
|
-
def connected(self) -> bool:
|
|
293
|
-
return hasattr(self, "_context") and self._context is not None
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0.post7.dev0" # managed by hatch
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.github/workflows/release.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/assets/stylesheets/extra.css
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/contributing/documentation.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/README.md
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/dagster.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/__init__.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/constants.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/resources.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/io_manager.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/configs.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/jobs.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/ops.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/pipes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/schedules.py
RENAMED
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/run_launcher.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/examples/test_examples.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_raycluster.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|