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.
Files changed (100) hide show
  1. dagster_ray-0.2.0.post10.dev0/.claude/settings.local.json +12 -0
  2. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/CHANDELOG.md +9 -3
  3. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/PKG-INFO +1 -1
  4. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/pyproject.toml +1 -3
  5. dagster_ray-0.2.0.post10.dev0/src/dagster_ray/_version.py +1 -0
  6. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/base.py +0 -5
  7. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/raycluster.py +2 -11
  8. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/resources.py +0 -1
  9. dagster_ray-0.2.0.post7.dev0/dagster_ray/_base/resources.py +0 -293
  10. dagster_ray-0.2.0.post7.dev0/src/dagster_ray/_version.py +0 -1
  11. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.basedpyright/baseline.json +0 -0
  12. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.dockerignore +0 -0
  13. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.github/workflows/CI.yml +0 -0
  14. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.github/workflows/release.yml +0 -0
  15. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.gitignore +0 -0
  16. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/.pre-commit-config.yaml +0 -0
  17. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/Dockerfile +0 -0
  18. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/LICENSE +0 -0
  19. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/README.md +0 -0
  20. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api/core.md +0 -0
  21. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api/kuberay.md +0 -0
  22. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/api.md +0 -0
  23. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/assets/stylesheets/extra.css +0 -0
  24. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/contributing/documentation.md +0 -0
  25. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/index.md +0 -0
  26. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/external.md +0 -0
  27. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/index.md +0 -0
  28. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/docs/tutorial/kuberay.md +0 -0
  29. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/Dockerfile +0 -0
  30. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/README.md +0 -0
  31. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/dagster.yaml +0 -0
  32. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/definitions.py +0 -0
  33. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/docker-compose.yml +0 -0
  34. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/docker/run_launcher/workspace.yaml +0 -0
  35. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/README.md +0 -0
  36. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/dagster.yaml +0 -0
  37. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/definitions.py +0 -0
  38. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/executor/workspace.yaml +0 -0
  39. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/README.md +0 -0
  40. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/dagster.yaml +0 -0
  41. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/definitions.py +0 -0
  42. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher/workspace.yaml +0 -0
  43. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/README.md +0 -0
  44. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/dagster.yaml +0 -0
  45. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/definitions.py +0 -0
  46. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/examples/local/run_launcher_and_executor/workspace.yaml +0 -0
  47. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/flake.lock +0 -0
  48. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/flake.nix +0 -0
  49. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/justfile +0 -0
  50. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/mkdocs.yml +0 -0
  51. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/renovate.json +0 -0
  52. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/scripts/check_deps.py +0 -0
  53. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/__init__.py +0 -0
  54. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/__init__.py +0 -0
  55. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/constants.py +0 -0
  56. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/resources.py +0 -0
  57. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/_base/utils.py +0 -0
  58. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/config.py +0 -0
  59. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/executor.py +0 -0
  60. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/io_manager.py +0 -0
  61. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/__init__.py +0 -0
  62. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/__init__.py +0 -0
  63. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/base.py +0 -0
  64. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/raycluster/__init__.py +0 -0
  65. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/raycluster/client.py +0 -0
  66. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/rayjob/__init__.py +0 -0
  67. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/client/rayjob/client.py +0 -0
  68. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/configs.py +0 -0
  69. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/jobs.py +0 -0
  70. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/ops.py +0 -0
  71. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/pipes.py +0 -0
  72. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/__init__.py +0 -0
  73. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/resources/rayjob.py +0 -0
  74. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/schedules.py +0 -0
  75. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/kuberay/utils.py +0 -0
  76. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/pipes.py +0 -0
  77. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/py.typed +0 -0
  78. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/run_launcher.py +0 -0
  79. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/types.py +0 -0
  80. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/src/dagster_ray/utils.py +0 -0
  81. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/__init__.py +0 -0
  82. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/conftest.py +0 -0
  83. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/example.py +0 -0
  84. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/examples/test_examples.py +0 -0
  85. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/__init__.py +0 -0
  86. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/__snapshots__/test_utils.ambr +0 -0
  87. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/conftest.py +0 -0
  88. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_interactive_rayjob.py +0 -0
  89. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_pipes.py +0 -0
  90. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_raycluster.py +0 -0
  91. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/test_utils.py +0 -0
  92. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/kuberay/utils.py +0 -0
  93. {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
  94. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/scripts/remote_job.py +0 -0
  95. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_executor.py +0 -0
  96. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_io_manager.py +0 -0
  97. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_pipes.py +0 -0
  98. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/test_resources.py +0 -0
  99. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/tests/utils.py +0 -0
  100. {dagster_ray-0.2.0.post7.dev0 → dagster_ray-0.2.0.post10.dev0}/uv.lock +0 -0
@@ -0,0 +1,12 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(ls:*)",
5
+ "Bash(hatch build:*)",
6
+ "Bash(unzip:*)",
7
+ "Bash(, unzip)",
8
+ "Bash(nix-shell:*)"
9
+ ],
10
+ "deny": []
11
+ }
12
+ }
@@ -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
- # Changed
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
- # Added
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
- ## Fixes
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.post7.dev0
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/
@@ -91,9 +91,7 @@ docs = [
91
91
 
92
92
 
93
93
  [tool.hatch.build.targets.wheel]
94
- include = [
95
- "src/dagster_ray",
96
- ]
94
+ packages = ["src/dagster_ray"]
97
95
 
98
96
  [tool.hatch.version]
99
97
  path = "src/dagster_ray/_version.py"
@@ -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`."""
@@ -9,7 +9,6 @@ if sys.version_info >= (3, 11):
9
9
  else:
10
10
  pass
11
11
 
12
- from ray._private.worker import BaseContext as RayBaseContext # noqa
13
12
 
14
13
  from dagster_ray._base.resources import BaseRayResource
15
14
 
@@ -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