-
Notifications
You must be signed in to change notification settings - Fork 126
Special behaviour for temporal prefixes #1644
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
base: main
Are you sure you want to change the base?
Conversation
In this change, users are prevented from registering signals/updates/queries with reserved names from the handler. Users can still Alternatively, we can do the blocking in |
8170bc5
to
5f5103a
Compare
this is blocked on #1640 so we can handle the same prefix cases for updates as well |
packages/workflow/src/internals.ts
Outdated
@@ -619,6 +625,8 @@ export class Activator implements ActivationHandler { | |||
protected queryWorkflowNextHandler({ queryName, args }: QueryInput): Promise<unknown> { | |||
let fn = this.queryHandlers.get(queryName)?.handler; | |||
if (fn === undefined && this.defaultQueryHandler !== undefined) { | |||
// Do not call default query handler with reserved query name. | |||
throwIfReservedName('query', queryName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should not be throwing this way here. Code below is clearly designed to make sure that we are not throwing synchronously. Also, UI expects that we'll answer back with a list of accepted query types.
Actually, I'd just skip the default handler if query name is reserved. We'll still throw below, but we'll then be going the same code path as if that wasn't a reserved type name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved reserved prefix handling to the parent function queryWorkflow
, it throws if a reserved query tries to use a default query handler
packages/workflow/src/internals.ts
Outdated
@@ -797,6 +816,8 @@ export class Activator implements ActivationHandler { | |||
if (fn) { | |||
return await fn(...args); | |||
} else if (this.defaultSignalHandler) { | |||
// Do not call default signal handler with reserved signal name. | |||
throwIfReservedName('signal', signalName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely shouldn't throw here, as that means that adding reserved signals in the future would make those poison pills for any workers that don't yet know about them if there's a default signal handler registered. In fact, we should simply not enter signalWorkflowNextHandler
if that's a reserved name and there is no registered signalHandlers
for that name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, moved reserved prefix handling to signalWorkflow
, it throws if a reserved query tries to use a default signal handler
… test needs to be fixed, need to add behaviour reserving prefixes from workflows, and waiting for default update to be merged to add behaviour preventing default update handler to be called with reserved names
5f5103a
to
8237158
Compare
1a7b249
to
55c641f
Compare
} | ||
} | ||
|
||
export function maybeGetReservedPrefix(name: string): string | undefined { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check needs to vary based on type; not all reserved name patterns apply to all types. Also, not all reserved name patterns are prefixes; __stack_trace
and __enhanced_stack_trace
are exact matches.
With that in mind, I don't think using a loop makes sense. Also, I have no strong opinion about having the check logic externalized to this file, but it looks that's not what we did in other SDKs.
ENHANCED_STACK_TRACE_RESERVED_PREFIX, | ||
]; | ||
|
||
export class ReservedPrefixError extends Error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a good reason to make a custom error type for this, rather than just throwing a TypeError
? It's not like users will want to catch that error and do instanceof
on it.
But if we'd want to keep that error class (I don't think so), it should have the @SymbolBasedInstanceOfError('...')
annotation, and be exported from index.ts
.
} | ||
} | ||
|
||
export function throwIfReservedName(type: string, name: string): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type
should be a union of expected values, rather than any string.
@@ -953,6 +954,9 @@ export function compileWorkerOptions( | |||
} | |||
|
|||
const activities = new Map(Object.entries(opts.activities ?? {}).filter(([_, v]) => typeof v === 'function')); | |||
for (const activityName of activities.keys()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need to check sinks.
@@ -467,6 +468,7 @@ export class Worker { | |||
* This method initiates a connection to the server and will throw (asynchronously) on connection failure. | |||
*/ | |||
public static async create(options: WorkerOptions): Promise<Worker> { | |||
throwIfReservedName('task queue', options.taskQueue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, taskQueue
can be undefined. Won't that cause an NPE in throwIfServedName?
@@ -0,0 +1,31 @@ | |||
export const TEMPORAL_RESERVED_PREFIX = '__temporal_'; | |||
export const STACK_TRACE_RESERVED_PREFIX = '__stack_trace'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not a prefix. Same for next line.
What was changed
Special behavior handling reserved temporal prefixes. Prevent users from:
Note: this change does not cover handling reserved temporal prefixes for workflows, as it involves non-trivial changes to the workflow bundling.
Closes [Feature Request] Special behavior for Temporal built-in prefixes #1599
How was this tested:
unit/integration tests
Any docs updates needed?
I'm not sure.