Open bergundy opened 3 years ago
There are other things that are only registered at the SDK level, e.g. signal handlers. I wonder if we want a more generic "get SDK workflow details" query that also shows signal handlers and potentially any other SDK-side-only metadata. Whatever is decided, of course it needs to be well specified since all SDKs need to support it in the exact same way.
That's a good suggestion @cretz, let's do that.
We should define the message in the API proto repo
is it possible in theory to also provide input data type definitions? for both Queries and Signals in case we want to dynamically construct the UI
@feedmeapples - Can discuss in separate issue/discussion as that's much more complex (and due to signals persisting in history even on bad input poses some issues alleviated by the upcoming synchronous update feature).
This should be represented as proto which every language and the UI can use. Granted the format will be JSON-based proto not binary.
Here would be my idea (expressed in TS terms, but applicable to all SDKs):
// This can be per workflow run or per workflow type
message WorkflowMetadata {
WorkflowDefinition definition = 1;
// TODO(cretz): Future possibilities
// * Stack information
// * Worker metadata sans workflow list
}
message WorkflowDefinition {
// If empty, this is a "dynamic" form of the workflow
string type = 1;
// Optional
string description = 2;
// When fetching at a worker level these are obviously fixed to the workflow
// definition which means that languages like Go need to provide a way to
// allow developers to define these things ahead of time if they want (unlike
// today which is runtime). When fetching at a workflow level, these may be
// specific to a run since handlers can be added inside of workflows.
//
// We can break these out to separate message types for each definition type
// if/when there are fields specific to each.
repeated InteractionDefinition signal_definitions = 3;
repeated InteractionDefinition query_definitions = 4;
repeated InteractionDefinition update_definitions = 5;
}
message InteractionDefinition {
// If empty, this is a "dynamic" form of the interaction
string name = 1;
// Optional. While we can support type hinting information for callers in
// more well-typed fields in the future, it gets complicated quickly.
// Therefore, all information a caller may need should currently be in English
// in this field (even if it's generated by the SDK).
string description = 2;
}
message ActivityDefinition {
// If empty, this is a "dynamic" form of the activity
string type = 1;
// Optional
string description = 2;
}
message WorkerMetadata {
repeated WorkflowDefinition workflow_definitions = 1;
repeated ActivityDefinition activity_definitions = 2;
// TODO(cretz): There are so many options here to add things such as:
// * Registration/config options
// * Cache info
// * Identity information we usually have for workers
// * SDK language and version
// * General process/metric info (but don't overdo this)
}
Here are the calls one can make:
UpdateWorker
top-level RPC call that accepts a task queue and optional worker identityrepeated temporal.api.protocol.v1.Message messages
needs to also be added to PollActivityTaskQueueResponse
PollWorkflowTaskQueueResponse
or PollActivityTaskQueueResponse
will be the
worker update which is represented as:RespondWorkerUpdate
top-level call which takes arbitrary protocol
messages/identifiersFor discussion:
__doc__
and also add type hint information, but most other languages do not have docs at runtime so a
separate field at the registration/declaration/definition/decoration/annotation/attribute site would be requiredI would love to get this listQueries
feature in all the SDKs. We are envisioning building custom UIs based on query names and it would be a lot nicer to do this without the current hack. Happy to work with whoever on this from the SDK side.
// If empty, this is a "dynamic" form of the workflow
@cretz I wonder if we need to report dynamic workflow/interactions at all. In particular, if they don't have a description either, there is no proper way to identify them...
I wonder if we need to report dynamic workflow/interactions at all. In particular, if they don't have a description either, there is no proper way to identify them...
This is about providing information to the caller about the shape of what is defined on the workflow. The caller may want to know that any query could be accepted because dynamic query is enabled. This can affect things like the UI where they may make it clear to a user that any arbitrary string query name would be accepted if they knew that dynamic queries were supported.
Btw, if you are tackling this now, I would ignore anything about "worker queries" in this issue, that can be done somewhere else.
. The caller may want to know that any query could be accepted because dynamic query is enabled Do we have the same concept for updates and signals, or just only for queries?
The examples I'm seeing define a generic signal first, and add extra info in the payload, soMistery solved, dynamic handlers are not supported in TS, only Java/Python/.Net, and go uses GetUnhandledSignalNames for signals. For update, there is no GetUnhandledUpdateNames in go (I'm adding an issue), Java seems to support it, not sure about .Net/Python...name
will not be missing...
This issue is known and #201 exists to bring parity here.
Signals in Go for this feature request are going to be a bit interesting. My suggestion: there is no such thing as a signal definition in Go so we should never populate that repeated field in metadata. However, we can create helper API in Go like workflow.DefineSignalChannel(workflow.SignalDefinition{Name: "my-signal", Description: "whatever"})
and people can call that to populate this info but it won't relate to their actual channel use. It would be a bad idea IMO to populate Go signal definitions in this metadata just based on whether a signal channel was ever asked for and similarly bad if it included any signal name that had been seen.
We're going to need to design how to provide "descriptions" to these interactions in every language anyways. In Go, SetUpdateHandlerWithOptions
's options can have it, but you'd need a new SetQueryHandlerWithOptions
for queries. In Java, Python, and .NET you can use a field on the annotation, decorator, and attribute respectively though you need to still accept them on runtime-added forms. In TS these are likely just options on the define calls.
I can provide clarification here if unclear.
This needs to be done in every SDK other than TypeScript
Note from UI sync: Good idea to have an "is visible in UI" flag for interactions
Other possible future options:
Up until now we've used a hack to get the list of registered queries from a workflow execution. The hack is to send a query to a workflow, which responds with something like "query not found, list of registered queries...", parse the response and show in the UI.
A standard way to support listing workflow queries would be to have a "listQueries" (name TBD) built-in query provided by the Workflow runtime.
We'd have to keep the hack around to support SDKs that still do not support the listQueries built-in query (all at the time of this writing).
UPDATE: Here is the roadmap: