dapr / python-sdk

Dapr SDK for Python
Apache License 2.0
230 stars 128 forks source link

[Workflow] DaprWorkflowClient workflow state is opaque #573

Closed cgillum closed 1 year ago

cgillum commented 1 year ago

Expected Behavior

WorkflowState objects, which are returned from methods like wait_for_workflow_completion, should be easy to inspect, whether using a debugger or via printing.

Actual Behavior

It's really difficult to inspect the state of a workflow from the WorkflowState objects. For example, if I try to print an object using print(state), I get this:

<dapr.ext.workflow.workflow_state.WorkflowState object at 0x7f5891813350>

I also can't dump the object to JSON:

json.dumps(state)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.3/lib/python3.11/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.3/lib/python3.11/json/encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.3/lib/python3.11/json/encoder.py", line 258, in iterencode
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
  File "/home/linuxbrew/.linuxbrew/Cellar/python@3.11/3.11.3/lib/python3.11/json/encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type WorkflowState is not JSON serializable

Even visualizing the object in the VS Code debugger is awkward because the useful properties are hidden behind a _WorkflowState__obj property.

image

Steps to Reproduce the Problem

Use the DaprWorkflowClient to start and inspect a workflow, similar to the following:

import dapr.ext.workflow as wf

def my_workflow(ctx: wf.DaprWorkflowContext, input: int):
    return input

if __name__ == '__main__':
    workflowRuntime = wf.WorkflowRuntime("localhost", "50001")
    workflowRuntime.register_workflow(my_workflow)
    workflowRuntime.start()

    wf_client = wf.DaprWorkflowClient()
    instance_id = wf_client.schedule_new_workflow(workflow=my_workflow, input=42)
    print(f'Workflow started. Instance ID: {instance_id}')
    state = wf_client.wait_for_workflow_completion(instance_id)
    print(state)

    workflowRuntime.shutdown()

Release Note

RELEASE NOTE: FIX Improved usability of the WorkflowState class

cgillum commented 1 year ago

/cc @DeepanshuA

cgillum commented 1 year ago

Related issue: WorkflowState exposes a runtime_status property, but it returns a WorkflowStatus enum which isn't exported (it's not listed in __init__.py) and therefore isn't directly usable. This also needs to be fixed.

DeepanshuA commented 1 year ago

/assign