-
Notifications
You must be signed in to change notification settings - Fork 95
Improve server-client communication error handling #6578
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 all commits
4ba360b
ff80511
cc15342
8529d37
43cab17
1415531
d6a21f5
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 |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Improved handling of any internal errors when executing commands against a running workflow. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,12 @@ | |
| import asyncio | ||
| import getpass | ||
| import json | ||
| from typing import Optional, Tuple | ||
| from typing import ( | ||
| TYPE_CHECKING, | ||
| Optional, | ||
| Tuple, | ||
| Union, | ||
| ) | ||
|
|
||
| import zmq | ||
| import zmq.asyncio | ||
|
|
@@ -30,32 +35,77 @@ | |
| CylcError, | ||
| CylcVersionError, | ||
| ServiceFileError, | ||
| WorkflowStopped | ||
| WorkflowStopped, | ||
| ) | ||
| from cylc.flow.hostuserutil import get_fqdn_by_host | ||
| from cylc.flow.workflow_files import ( | ||
| ContactFileFields, | ||
| KeyType, | ||
| KeyOwner, | ||
| KeyInfo, | ||
| KeyOwner, | ||
| KeyType, | ||
| get_workflow_srv_dir, | ||
| load_contact_file, | ||
| get_workflow_srv_dir | ||
| ) | ||
|
|
||
|
|
||
| if TYPE_CHECKING: | ||
| # BACK COMPAT: typing_extensions.TypedDict | ||
| # FROM: Python 3.7 | ||
| # TO: Python 3.11 | ||
| from typing_extensions import TypedDict | ||
|
|
||
|
|
||
| API = 5 # cylc API version | ||
| MSG_TIMEOUT = "TIMEOUT" | ||
|
|
||
| if TYPE_CHECKING: | ||
| class ResponseDict(TypedDict, total=False): | ||
| """Structure of server response messages. | ||
|
|
||
| def encode_(message): | ||
| """Convert the structure holding a message field from JSON to a string.""" | ||
| try: | ||
| return json.dumps(message) | ||
| except TypeError as exc: | ||
| return json.dumps({'errors': [{'message': str(exc)}]}) | ||
| Confusingly, has similar format to GraphQL execution result. | ||
| But if we change this now we could break compatibility for | ||
| issuing commands to/receiving responses from workflows running in | ||
| different versions of Cylc 8. | ||
| """ | ||
| data: object | ||
| """For most Cylc commands that issue GQL mutations, the data field will | ||
| look like: | ||
| data: { | ||
| <mutationName1>: { | ||
| result: [ | ||
| { | ||
| id: <workflow/task ID>, | ||
| response: [<success_bool>, <message>] | ||
| }, | ||
| ... | ||
| ] | ||
| } | ||
| } | ||
| but this is not 100% consistent unfortunately | ||
| """ | ||
| error: Union[Exception, str, dict] | ||
|
Member
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. When is
Member
Author
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. I think I tried to change it to |
||
| """If an error occurred that could not be handled. | ||
| (usually a dict {message: str, traceback?: str}). | ||
| """ | ||
| user: str | ||
| cylc_version: str | ||
| """Server (i.e. running workflow) Cylc version. | ||
|
|
||
| Going forward, we include this so we can more easily handle any future | ||
| back-compat issues.""" | ||
|
|
||
|
|
||
| def serialize(data: object) -> str: | ||
| """Convert the structure holding a message to a JSON message string.""" | ||
| # Abstract out the transport format in order to allow it to be changed | ||
| # in future. | ||
| return json.dumps(data) | ||
|
|
||
|
|
||
| def decode_(message): | ||
| """Convert an encoded message string to JSON with an added 'user' field.""" | ||
| def deserialize(message: str) -> 'ResponseDict': | ||
| """Convert a JSON message string to dict with an added 'user' field.""" | ||
| # Abstract out the transport format in order to allow it to be changed | ||
| # in future. | ||
| msg = json.loads(message) | ||
| msg['user'] = getpass.getuser() # assume this is the user | ||
| return msg | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.