Example #1
0
def resume_workflow_job(workflow_id: str, store_url: str) -> ray.ObjectRef:
    """Resume a workflow job.

    Args:
        workflow_id: The ID of the workflow job. The ID is used to identify
            the workflow.
        store_url: The url of the storage to access the workflow.

    Raises:
        WorkflowNotResumableException: fail to resume the workflow.

    Returns:
        The execution result of the workflow, represented by Ray ObjectRef.
    """
    try:
        store = storage.create_storage(store_url)
        wf_store = workflow_storage.WorkflowStorage(workflow_id, store)
        entrypoint_step_id: StepID = wf_store.get_entrypoint_step_id()
        r = _construct_resume_workflow_from_step(wf_store, entrypoint_step_id)
    except Exception as e:
        raise WorkflowNotResumableError(workflow_id) from e

    if isinstance(r, Workflow):
        with workflow_context.workflow_step_context(workflow_id,
                                                    store.storage_url):
            from ray.experimental.workflow.step_executor import (
                execute_workflow)
            return execute_workflow(r)
    return wf_store.load_step_output(r)
Example #2
0
def resume_workflow_job(workflow_id: str,
                        store: storage.Storage) -> ray.ObjectRef:
    """Resume a workflow job.

    Args:
        workflow_id: The ID of the workflow job. The ID is used to identify
            the workflow.
        store: The storage to access the workflow.

    Raises:
        WorkflowNotResumableException: fail to resume the workflow.

    Returns:
        The execution result of the workflow, represented by Ray ObjectRef.
    """
    reader = workflow_storage.WorkflowStorage(workflow_id, store)
    try:
        entrypoint_step_id: StepID = reader.get_entrypoint_step_id()
        r = _construct_resume_workflow_from_step(reader, entrypoint_step_id)
    except Exception as e:
        raise WorkflowNotResumableError(workflow_id) from e

    if isinstance(r, Workflow):
        try:
            workflow_context.init_workflow_step_context(
                workflow_id, store.storage_url)
            return execute_workflow(r)
        finally:
            workflow_context.set_workflow_step_context(None)

    return ray.put(reader.load_step_output(r))
Example #3
0
def _resume_workflow_step_executor(
        workflow_id: str, step_id: "StepID", store_url: str,
        current_output: [ray.ObjectRef
                         ]) -> Tuple[ray.ObjectRef, ray.ObjectRef]:
    # TODO (yic): We need better dependency management for virtual actor
    # The current output will always be empty for normal workflow
    # For virtual actor, if it's not empty, it means the previous job is
    # running. This is a really bad one.
    for ref in current_output:
        try:
            while isinstance(ref, ray.ObjectRef):
                ref = ray.get(ref)
        except Exception:
            pass
    try:
        store = storage.create_storage(store_url)
        wf_store = workflow_storage.WorkflowStorage(workflow_id, store)
        r = _construct_resume_workflow_from_step(wf_store, step_id)
    except Exception as e:
        raise WorkflowNotResumableError(workflow_id) from e

    if isinstance(r, Workflow):
        with workflow_context.workflow_step_context(workflow_id,
                                                    store.storage_url):
            from ray.experimental.workflow.step_executor import (
                execute_workflow)
            result = execute_workflow(r, last_step_of_workflow=True)
            return result.persisted_output, result.volatile_output
    assert isinstance(r, StepID)
    return wf_store.load_step_output(r), None
Example #4
0
 def _actor_method_call(self, method_name: str, args,
                        kwargs) -> "ObjectRef":
     cls = self._metadata.cls
     method = getattr(cls, method_name, None)
     if method is None:
         raise AttributeError(f"Method '{method_name}' does not exist.")
     with workflow_context.workflow_step_context(self._actor_id,
                                                 self._storage.storage_url):
         wf = method.step(*args, **kwargs)
         readonly = getattr(method, "__virtual_actor_readonly__", False)
         if readonly:
             return execute_workflow(wf).volatile_output
         else:
             return wf.run_async(self._actor_id)
Example #5
0
def _resume_workflow_step_executor(
        workflow_id: str, step_id: "StepID",
        store_url: str) -> Tuple[ray.ObjectRef, ray.ObjectRef]:
    try:
        store = storage.create_storage(store_url)
        wf_store = workflow_storage.WorkflowStorage(workflow_id, store)
        r = _construct_resume_workflow_from_step(wf_store, step_id)
    except Exception as e:
        raise WorkflowNotResumableError(workflow_id) from e

    if isinstance(r, Workflow):
        with workflow_context.workflow_step_context(workflow_id,
                                                    store.storage_url):
            from ray.experimental.workflow.step_executor import (
                execute_workflow)
            result = execute_workflow(r, last_step_of_workflow=True)
            return result.persisted_output, result.volatile_output
    return wf_store.load_step_output(r), None
Example #6
0
    def _actor_method_call(self, method_name: str, args,
                           kwargs) -> "ObjectRef":
        cls = self._metadata.cls
        method = getattr(cls, method_name, None)
        if method is None:
            raise AttributeError(f"Method '{method_name}' does not exist.")
        readonly = getattr(method, "__virtual_actor_readonly__", False)

        flattened_args = self._metadata.flatten_args(method_name, args, kwargs)
        if not readonly:
            if method_name == "__init__":
                state_ref = None
            else:
                ws = WorkflowStorage(self._actor_id, self._storage)
                state_ref = WorkflowRef(ws.get_entrypoint_step_id())
            # This is a hack to insert a positional argument.
            flattened_args = [signature.DUMMY_TYPE, state_ref] + flattened_args
        workflow_inputs = serialization_context.make_workflow_inputs(
            flattened_args)

        if readonly:
            _actor_method = _wrap_readonly_actor_method(
                self._actor_id, cls, method_name)
            step_type = StepType.READONLY_ACTOR_METHOD
        else:
            _actor_method = _wrap_actor_method(cls, method_name)
            step_type = StepType.ACTOR_METHOD
        # TODO(suquark): Support actor options.
        workflow_data = WorkflowData(
            func_body=_actor_method,
            step_type=step_type,
            inputs=workflow_inputs,
            max_retries=1,
            catch_exceptions=False,
            ray_options={},
        )
        wf = Workflow(workflow_data)
        with workflow_context.workflow_step_context(self._actor_id,
                                                    self._storage.storage_url):
            if readonly:
                return execute_workflow(wf).volatile_output
            else:
                return wf.run_async(self._actor_id)