Skip to content

Commit 0c7f0bd

Browse files
authored
IWF-468: Describe Workflow API (#91)
* IWF-468: Describe Workflow API * IWF-468: Fix lint errors * IWF-468: Fix lint errors
1 parent d68a706 commit 0c7f0bd

File tree

4 files changed

+104
-1
lines changed

4 files changed

+104
-1
lines changed

iwf/client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from iwf.utils.iwf_typing import unset_to_none
1919
from iwf.utils.persistence_utils import get_search_attribute_value
2020
from iwf.workflow import ObjectWorkflow, get_workflow_type_by_class
21+
from iwf.workflow_info import WorkflowInfo
2122
from iwf.workflow_options import WorkflowOptions
2223
from iwf.workflow_state import (
2324
WorkflowState,
@@ -199,6 +200,16 @@ def reset_workflow(
199200
workflow_id, "", reset_workflow_type_and_options
200201
)
201202

203+
def describe_workflow(
204+
self,
205+
workflow_id: str,
206+
workflow_run_id: Optional[str] = None,
207+
):
208+
run_id = workflow_run_id if workflow_run_id is not None else ""
209+
210+
response = self._unregistered_client.get_workflow(workflow_id, run_id)
211+
return WorkflowInfo(workflow_status=response.workflow_status)
212+
202213
def skip_timer_by_command_id(
203214
self,
204215
workflow_id: str,

iwf/tests/test_describe_workflow.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import inspect
2+
import time
3+
import unittest
4+
5+
from iwf.client import Client
6+
from iwf.command_request import CommandRequest, TimerCommand
7+
from iwf.command_results import CommandResults
8+
from iwf.communication import Communication
9+
from iwf.errors import WorkflowNotExistsError
10+
from iwf.iwf_api.models import WorkflowStatus
11+
from iwf.persistence import Persistence
12+
from iwf.state_decision import StateDecision
13+
from iwf.state_schema import StateSchema
14+
from iwf.tests.worker_server import registry
15+
from iwf.workflow import ObjectWorkflow
16+
from iwf.workflow_context import WorkflowContext
17+
from iwf.workflow_state import T, WorkflowState
18+
19+
20+
class WaitState(WorkflowState[None]):
21+
def wait_until(
22+
self,
23+
ctx: WorkflowContext,
24+
input: T,
25+
persistence: Persistence,
26+
communication: Communication,
27+
) -> CommandRequest:
28+
return CommandRequest.for_all_command_completed(
29+
TimerCommand.by_seconds(10),
30+
)
31+
32+
def execute(
33+
self,
34+
ctx: WorkflowContext,
35+
input: T,
36+
command_results: CommandResults,
37+
persistence: Persistence,
38+
communication: Communication,
39+
) -> StateDecision:
40+
41+
return StateDecision.graceful_complete_workflow()
42+
43+
44+
class DescribeWorkflow(ObjectWorkflow):
45+
def get_workflow_states(self) -> StateSchema:
46+
return StateSchema.with_starting_state(WaitState())
47+
48+
49+
wf = DescribeWorkflow()
50+
registry.add_workflow(wf)
51+
client = Client(registry)
52+
53+
54+
class TestDescribeWorkflow(unittest.TestCase):
55+
def test_describe_workflow(self):
56+
wf_id = f"{inspect.currentframe().f_code.co_name}-{time.time_ns()}"
57+
58+
client.start_workflow(DescribeWorkflow, wf_id, 100)
59+
workflow_info = client.describe_workflow(wf_id)
60+
assert workflow_info.workflow_status == WorkflowStatus.RUNNING
61+
62+
# Stop the workflow
63+
client.stop_workflow(wf_id)
64+
65+
def test_describe_workflow_when_workflow_not_exists(self):
66+
wf_id = f"{inspect.currentframe().f_code.co_name}-{time.time_ns()}"
67+
68+
with self.assertRaises(WorkflowNotExistsError):
69+
client.describe_workflow(wf_id)

iwf/unregistered_client.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from iwf.iwf_api import Client, errors
1818
from iwf.iwf_api.api.default import (
1919
post_api_v1_workflow_dataobjects_get,
20+
post_api_v1_workflow_get,
2021
post_api_v1_workflow_reset,
2122
post_api_v1_workflow_rpc,
2223
post_api_v1_workflow_search,
@@ -96,7 +97,7 @@ def add_http_status(name, value, phrase, description=""):
9697
HTTPStatus.__class__
9798
) # store the enum's member parent class
9899
setattr(HTTPStatus, name, new_status) # add it to the global HTTPStatus namespace
99-
HTTPStatus._member_map_[name] = new_status # add it to the name=>member map
100+
HTTPStatus._member_map_[name] = new_status # add it to the name=>member map
100101
HTTPStatus._member_names_.append(
101102
name
102103
) # append the names so it appears in __members__
@@ -415,6 +416,21 @@ def stop_workflow(
415416
)
416417
return handler_error_and_return(response)
417418

419+
def get_workflow(
420+
self,
421+
workflow_id: str,
422+
workflow_run_id: str,
423+
) -> WorkflowGetResponse:
424+
request = WorkflowGetRequest(
425+
workflow_id=workflow_id,
426+
workflow_run_id=workflow_run_id,
427+
)
428+
response = post_api_v1_workflow_get.sync_detailed(
429+
client=self.api_client,
430+
json_body=request,
431+
)
432+
return handler_error_and_return(response)
433+
418434
def get_workflow_data_attributes(
419435
self,
420436
workflow_id: str,

iwf/workflow_info.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from dataclasses import dataclass
2+
from iwf.iwf_api.models.workflow_status import WorkflowStatus
3+
4+
5+
@dataclass
6+
class WorkflowInfo:
7+
workflow_status: WorkflowStatus

0 commit comments

Comments
 (0)