Skip to content

feat(worker): Add a workflow metadata query #1319

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

Merged

Conversation

antlai-temporal
Copy link
Contributor

What was changed

Typescript SDK implementation of temporalio/features#51 providing a built-in query to return
metadata of registered query, signal, and update handlers.

Why?

See temporalio/features#51

Checklist

  1. Closes
    [Proposal] Built-in registered handlers query #1081
  2. How was this tested:

Added two integration tests.

@antlai-temporal antlai-temporal requested a review from a team as a code owner December 15, 2023 04:55
Copy link
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, had one clarifying question.

{
handler: (): temporal.api.sdk.v1.IWorkflowMetadata => {
const workflowType = this.info.workflowType;
const description = this.info?.memo?.__temporal_workflow_description;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I wasn't part of the design but why put this in the memo? And if we're putting this in the memo, why also return it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started adding a new field, but I saw that memo is sometimes used to add a description to the workflow, and it was confusing why a new field was needed if we had memo...

The reason to also return it with the query is just convenience. There is nothing else returned by the query that associates with the queried workflow, so to make the result standalone they will have to patch it...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should question if we want to put this in memo since we now have the standard query (although I see some advantages to it such as not needing a worker up to get the description).

If we want to use both memo and query, it might be better to have a dedicated method to set the description for a workflow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit reluctant with configuring this through a memo. At present, given that we don't support upsertMemo, that means the description would have to be provided by the code scheduling the workflow (i.e. client or parent workflow), which isn't desirable. Or, if we have upsertMemo, description would have to be set after starting the workflow, through a command, making this a billable feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really want to change WorkflowExecutionInfo protos for something that is going to be rarely used, and its functionality is redundant to memo. And it has to work across continueAsNew, or multiple workers, so I cannot see how to do that without a proto change.

I'm inclined to just not set it at all, and if someone needs extra workflow info they can use memo + lookup with the workflow id. Alternatively, we could do an explicit setter as @bergundy mentioned, after upsertMemo is implemented in TS.

About the cost of upsertMemo, I don't think the WF description is needed to use the query method, today the UI just uses the handlers names, and, in any case, the query costs are going to dominate anyway...

Any thoughts @bergundy @mjameswh ?

Copy link
Member

@cretz cretz Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memo is not a good place to put this IMO. Memo takes up visibility store room and is only for information that needs to be returned on list/describe.

I don't really want to change WorkflowExecutionInfo protos for something that is going to be rarely used, and its functionality is redundant to memo.

I don't think this information is related to existing protos and such. This is just a query return value. If there is a TS-SDK-specific problem of being able to set metadata for a workflow, ok we can discuss this TS-SDK-specific problem with a TS-SDK-specific solution (e.g. mutable value on TS info class/iface), but this issue should be just about returning this information from query and nothing more IMO. We shouldn't reuse general purpose Temporal constructs like memo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cretz I was following your proto schema that included a workflow description. What kind of workflow description you don't want to appear in list/describe? Do we need this at all?
I though that in all SDKs you need to modify protos if you want some workflow info to propagate across continueAsNew and worker's multiple execution resume. Is there a standard way across SDKs to do that without modifying protos?

Copy link
Member

@cretz cretz Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was following your proto schema that included a workflow description

Which proto schema? If you mean temporalio/api#336, that was meant purely as a query result and those messages aren't used otherwise (yet).

What kind of workflow description you don't want to appear in list/describe? Do we need this at all?

I wasn't expecting list/describe to be affected by this at all. Those are server-side calls. Maybe one day, but for now this is just querying a running workflow for information about itself at this time (sorry if there was confusion on the feature repo issue, it got a bit scatted).

I though that in all SDKs you need to modify protos if you want some workflow info to propagate across continueAsNew and worker's multiple execution resume. Is there a standard way across SDKs to do that without modifying protos?

This is fixed code-based metadata, it is not runtime data necessarily. You should just answer the query with the information the workflow code knows about itself and nothing more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fixed code-based metadata, it is not runtime data necessarily. You should just answer the query with the >information the workflow code knows about itself and nothing more.

OK, that changes things, I thought it could change per workflow instance and not only per workflow type.

I don't know a clean way to decorate a function in a way that works both for TS and JS. We could patch the function object to add a static method/getter, or define a static map mapping function names to descriptions, but they both look like a hack...

We could also just return the function name in the description for now...

Copy link
Member

@cretz cretz Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it could change per workflow instance and not only per workflow type.

It can change per workflow instance. People manually register signal handlers. But for the vast majority it won't change per instance. In Go you can't preregister anything, so it's always per instance (and there is no such thing as a signal handler). For other langs, yes, they have metadata facilities (decorators, attributes, annotations, etc). As for workflow description, I don't know of a good way for TS SDK to provide this kind of metadata and I'd be ok leaving it unset until decided.

I don't know a clean way to decorate a function in a way that works both for TS and JS. We could patch the function object to add a static method/getter, or define a static map mapping function names to descriptions, but they both look like a hack...

Same. Users could call setDescription inside the workflow at runtime or somehow at registration time, but in the meantime I'm ok leaving this unset for TS SDK while we think about it.

We could also just return the function name in the description for now...

I vote leave it unset

@@ -398,7 +398,7 @@ export function runIntegrationTests(codec?: PayloadCodec): void {
await t.throwsAsync(workflow.query('not found'), {
instanceOf: QueryNotRegisteredError,
message:
'Workflow did not register a handler for not found. Registered queries: [__stack_trace __enhanced_stack_trace isBlocked]',
'Workflow did not register a handler for not found. Registered queries: [__stack_trace __enhanced_stack_trace __temporal_workflow_metadata isBlocked]',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's getting messy. I think we should consider not listing "internals" queries.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be useful for knowing what built-in queries, like __temporal_workflow_metadata, are supported by the WF.
Also the UI today may expect some handlers present when parsing the error message...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI doesn't and shouldn't expect specific handlers to be present in the list returned on query not found error message. Using that error message to report existing queries is hack, not normalized across SDKs, and going forward, UI should call __temporal_workflow_metadata directly anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you on the UI, but unfortunately, depending on how the UI parses the query today, we may break it if we return an empty set. It is also unfortunate that isBlocked does not have the __ internal prefix. Once they switch, we can do the cleanup with them...

Copy link
Member

@cretz cretz Jan 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Fixing the query-failed string to not include all queries anymore should be a separate task once we feel comfortable enough modern UIs are no longer using it (i.e. fixed version has been out there a while). There are other approaches too such as having this error return the workflow metadata as extra error details. Hrmm, I wonder if we should do that...can discuss separately.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point was not about query-failed no longer returning any queries, but only about not returning SDK built-in queries. For example, if using an old UI, they should not see __stack_trace, __enhanced_stack_trace and __temporal_workflow_metadata in the query drop down. Returning user queries is still fine, for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If needed that's easy to filter by the UI using the __ prefix. I like that we can quickly know what internal queries are supported for a given workflow...

@mjameswh
Copy link
Contributor

I think we should prevent overriding built-in query handlers...

@antlai-temporal antlai-temporal force-pushed the add-get-workflow-metadata branch from 5a050fb to 0c3a6b5 Compare January 17, 2024 00:40
@antlai-temporal
Copy link
Contributor Author

I think we should prevent overriding built-in query handlers...

Yes, I have opened an issue for that #1343 I don't want to delay this one anymore...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants