-
Notifications
You must be signed in to change notification settings - Fork 134
Workflow management python SDK #554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 85 commits
d3ac21a
575bba0
9acdf2c
3e23139
c4e9ef7
487e97f
0733570
26380ee
eb995b8
cd044d1
6fde40c
128a1fa
e074e58
2682d72
9361b30
49c78d7
0516400
f82bb8e
ffde1df
8d62488
28690f0
3015073
de23696
15938b4
19ea43f
40fe904
1be2447
ab2d201
a537862
75ae2bf
7a31c66
3c11d6c
f5c7796
325dedb
b8bca56
2f81812
3185586
2ff152e
347c0bf
2ebf20c
a8fa501
05194c8
b2aff5c
cc25bd7
1a8af1d
7598dd1
74dbc9f
bf69dea
0968b8e
94f915b
4886c9e
18bc883
9d8ec7f
49f960a
c64a091
f3207fc
2bfc44a
82b33e5
de33a9b
363a0df
ba2087a
a3fb750
135d3d7
a9be483
0e0203d
003e25b
b9865b3
0a0e94b
23ae6f7
9cc7e4a
30ab277
da401e8
8b7dec9
e1d050c
d7e9ebd
9f5f138
d08907e
722e5b3
57af017
40da262
4c985f0
a4769d5
cbed6a2
739f145
6932f97
9c6ae6f
efd8420
ff513f2
04be191
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -16,12 +16,15 @@ | |||||||||||
import asyncio | ||||||||||||
import time | ||||||||||||
import socket | ||||||||||||
import json | ||||||||||||
import uuid | ||||||||||||
|
||||||||||||
from datetime import datetime | ||||||||||||
from urllib.parse import urlencode | ||||||||||||
|
||||||||||||
from warnings import warn | ||||||||||||
|
||||||||||||
from typing import Callable, Dict, Optional, Text, Union, Sequence, List | ||||||||||||
from typing import Callable, Dict, Optional, Text, Union, Sequence, List, Any | ||||||||||||
from typing_extensions import Self | ||||||||||||
|
||||||||||||
from google.protobuf.message import Message as GrpcMessage | ||||||||||||
|
@@ -35,7 +38,9 @@ | |||||||||||
StreamStreamClientInterceptor | ||||||||||||
) | ||||||||||||
|
||||||||||||
from dapr.clients.exceptions import DaprInternalError | ||||||||||||
from dapr.clients.grpc._state import StateOptions, StateItem | ||||||||||||
from dapr.clients.grpc._helpers import getWorkflowRuntimeStatus | ||||||||||||
from dapr.conf import settings | ||||||||||||
from dapr.proto import api_v1, api_service_v1, common_v1 | ||||||||||||
from dapr.proto.runtime.v1.dapr_pb2 import UnsubscribeConfigurationResponse | ||||||||||||
|
@@ -71,6 +76,8 @@ | |||||||||||
ConfigurationWatcher, | ||||||||||||
TryLockResponse, | ||||||||||||
UnlockResponse, | ||||||||||||
GetWorkflowResponse, | ||||||||||||
StartWorkflowResponse, | ||||||||||||
) | ||||||||||||
|
||||||||||||
|
||||||||||||
|
@@ -1103,6 +1110,278 @@ async def unlock( | |||||||||||
return UnlockResponse(status=UnlockResponseStatus(response.status), | ||||||||||||
headers=await call.initial_metadata()) | ||||||||||||
|
||||||||||||
async def start_workflow( | ||||||||||||
self, | ||||||||||||
workflow_component: str, | ||||||||||||
workflow_name: str, | ||||||||||||
input: Union[Any, bytes, None] = None, | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This still needs updating |
||||||||||||
instance_id: Optional[str] = None, | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also add parameter |
||||||||||||
workflow_options: Optional[Dict[str, str]] = dict()) -> StartWorkflowResponse: | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are assigning a default value of |
||||||||||||
"""Starts a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
workflow_name (str): the name of the workflow that will be executed. | ||||||||||||
input (Union[Any, bytes, None]): the input that the workflow will receive. | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
RyanLettieri marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update |
||||||||||||
instance_id (Optional[str]): the name of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_options (Optional[Dict[str, str]]): the key-value options | ||||||||||||
that the workflow will receive. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`StartWorkflowResponse`: Instance ID associated with the started workflow | ||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component, | ||||||||||||
workflow_name=workflow_name) | ||||||||||||
|
||||||||||||
if instance_id is None: | ||||||||||||
instance_id = str(uuid.uuid4()) | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
if isinstance(input, bytes): | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
encoded_data = input | ||||||||||||
else: | ||||||||||||
encoded_data = json.dumps(input).encode("utf-8") if input is not None else bytes([]) | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Add try except around this step In the except block, please throw a DaprInteralError exception with a message indicating that the input value must be json serializable. |
||||||||||||
|
||||||||||||
# Actual start workflow invocation | ||||||||||||
req = api_v1.StartWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component, | ||||||||||||
workflow_name=workflow_name, | ||||||||||||
options=workflow_options, | ||||||||||||
input=encoded_data) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
response = self._stub.StartWorkflowAlpha1(req) | ||||||||||||
return StartWorkflowResponse(instance_id=response.instance_id) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def get_workflow( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str) -> GetWorkflowResponse: | ||||||||||||
"""Gets information on a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`GetWorkflowResponse`: Instance ID associated with the started workflow | ||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
# Actual get workflow invocation | ||||||||||||
req = api_v1.GetWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
resp = self._stub.GetWorkflowAlpha1(req) | ||||||||||||
if resp.created_at is None: | ||||||||||||
resp.created_at = datetime.now | ||||||||||||
if resp.last_updated_at is None: | ||||||||||||
resp.last_updated_at = datetime.now | ||||||||||||
return GetWorkflowResponse(instance_id=instance_id, | ||||||||||||
workflow_name=resp.workflow_name, | ||||||||||||
created_at=resp.created_at, | ||||||||||||
last_updated_at=resp.last_updated_at, | ||||||||||||
runtime_status=getWorkflowRuntimeStatus(resp.runtime_status), | ||||||||||||
properties=resp.properties) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def terminate_workflow( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str) -> DaprResponse: | ||||||||||||
"""Terminates a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, e.g. | ||||||||||||
`order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`DaprResponse` gRPC metadata returned from callee | ||||||||||||
|
||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
# Actual terminate workflow invocation | ||||||||||||
req = api_v1.TerminateWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
_, call = self._stub.TerminateWorkflowAlpha1.with_call(req) | ||||||||||||
return DaprResponse( | ||||||||||||
headers=call.initial_metadata()) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def raise_workflow_event( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str, | ||||||||||||
event_name: str, | ||||||||||||
event_data: Union[Any, bytes, None] = None) -> DaprResponse: | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add param |
||||||||||||
"""Raises an event on a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
event_name (str): the name of the event to be raised on | ||||||||||||
the workflow. | ||||||||||||
event_data (Union[Any, bytes, None]): the input to the event. | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`DaprResponse` gRPC metadata returned from callee | ||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component, | ||||||||||||
event_name=event_name) | ||||||||||||
if isinstance(input, bytes): | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
encoded_data = event_data | ||||||||||||
else: | ||||||||||||
if event_data is not None: | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
encoded_data = json.dumps(event_data).encode("utf-8") | ||||||||||||
berndverst marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
else: | ||||||||||||
encoded_data = bytes([]) | ||||||||||||
# Actual workflow raise event invocation | ||||||||||||
req = api_v1.raise_workflow_event( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component, | ||||||||||||
event_name=event_name, | ||||||||||||
event_data=encoded_data) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
_, call = self._stub.RaiseEventWorkflowAlpha1.with_call(req) | ||||||||||||
RyanLettieri marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
return DaprResponse( | ||||||||||||
headers=call.initial_metadata()) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def pause_workflow( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str) -> DaprResponse: | ||||||||||||
"""Pause a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`DaprResponse` gRPC metadata returned from callee | ||||||||||||
|
||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
# Actual pause workflow invocation | ||||||||||||
req = api_v1.PauseWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
_, call = self._stub.PauseWorkflowAlpha1.with_call(req) | ||||||||||||
RyanLettieri marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
|
||||||||||||
return DaprResponse( | ||||||||||||
headers=call.initial_metadata()) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def resume_workflow( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str) -> DaprResponse: | ||||||||||||
"""Resumes a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`DaprResponse` gRPC metadata returned from callee | ||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
# Actual resume workflow invocation | ||||||||||||
req = api_v1.ResumeWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
_, call = self._stub.ResumeWorkflowAlpha1.with_call(req) | ||||||||||||
|
||||||||||||
return DaprResponse( | ||||||||||||
headers=call.initial_metadata()) | ||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def purge_workflow( | ||||||||||||
self, | ||||||||||||
instance_id: str, | ||||||||||||
workflow_component: str) -> DaprResponse: | ||||||||||||
"""Purges a workflow. | ||||||||||||
|
||||||||||||
Args: | ||||||||||||
instance_id (str): the ID of the workflow instance, | ||||||||||||
e.g. `order_processing_workflow-103784`. | ||||||||||||
workflow_component (str): the name of the workflow component | ||||||||||||
that will run the workflow. e.g. `dapr`. | ||||||||||||
|
||||||||||||
Returns: | ||||||||||||
:class:`DaprResponse` gRPC metadata returned from callee | ||||||||||||
""" | ||||||||||||
# Warnings and input validation | ||||||||||||
warn('The Workflow API is an Alpha version and is subject to change.', | ||||||||||||
UserWarning, stacklevel=2) | ||||||||||||
validateNotBlankString(instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
# Actual purge workflow invocation | ||||||||||||
req = api_v1.PurgeWorkflowRequest( | ||||||||||||
instance_id=instance_id, | ||||||||||||
workflow_component=workflow_component) | ||||||||||||
|
||||||||||||
try: | ||||||||||||
_, call = self._stub.PurgeWorkflowAlpha1.with_call(req) | ||||||||||||
|
||||||||||||
return DaprResponse( | ||||||||||||
headers=call.initial_metadata()) | ||||||||||||
|
||||||||||||
except grpc.aio.AioRpcError as err: | ||||||||||||
raise DaprInternalError(err.details()) | ||||||||||||
|
||||||||||||
async def wait(self, timeout_s: float): | ||||||||||||
"""Waits for sidecar to be available within the timeout. | ||||||||||||
|
||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.