now that we have a cohesive look at workflow APIs, some issues remain:
createActivityHandleisnt really a handle, in the way thatcreateWorkflowHandleandcreateChildWorkflowHandleare. it returns a function that you call.- users are confused by the proxy destructure which a very fancy way of doing type safety and ensuring consistent naming
defineSignal/Querydont add much value since they just create an object- extra
setListenerapi that is doing the real work, basically 2 different functions branching bydef.type
- extra
just taking another crack at api design.
export const unblockSignal = wf.defineSignal('unblock');
export const isBlockedQuery = wf.defineQuery('isBlocked');
export async function unblockOrCancel() {
let isBlocked = true;
wf.setListener(unblockSignal, () => void (isBlocked = false));
wf.setListener(isBlockedQuery, () => isBlocked);
console.log('Blocked');
try {
await wf.condition(() => !isBlocked);
console.log('Unblocked');
}
catch (err) {
if (err instanceof wf.CancelledFailure) {
console.log('Cancelled');
}
throw err;
}
}if we eliminate setListener...
// using exportable definitions
export const onSetState = useSignal<boolean>('setState');
export const getIsBlocked = useQuery<boolean>('isBlocked');
export async function unblockOrCancel() {
let isBlocked = true;
onSetState((newState) => void (isBlocked = newState)); // boolean
getIsBlocked(() => isBlocked);
// ...
}if they dont like on (because of the subscribe implication) they can name it setStateHandler or BlockedQueryResolver or whatever they like... we dont prescribe the naming.
for those who
- don't need to export the signaldef/querydefs for strong typing for invocation (eg in the nextjs example its pretty inconvenient to import the types from the temporal folder into the nextjs folder, most people wont even bother)
- don't need to reassign the listener
this enables inlining and reduces naming need:
// using strings
export async function unblockOrCancel() {
let isBlocked = true;
useSignal('unblock', () => void (isBlocked = false));
useQuery('isBlocked', () => isBlocked);
// ...
}import { createActivityHandle } from '@temporalio/workflow';
import type * as activities from './activities';
const { greet } = createActivityHandle<typeof activities>({
startToCloseTimeout: '1 minute',
});
/** A workflow that simply calls an activity */
export async function example(name) {
return await greet(name);
}- this is decent tbh, but for some people (who would like to use typescript, but are not typescript gods),
<typeof activities>is a foreign language and hard to decipher. - i am worried that people will just copy paste this and not really intuitively understand how to manipulate activities to suit their code style.
- it also requires people to barrel all types into a single
activitiesfile (not really, but people will treat it that way)... would be nice to let people componentize or combine as they wish
i'd like to make clear that this is "just" a function and that we are importing from worker that must have this activity registered.
import { useActivity } from '@temporalio/workflow';
import type greet from './activities/greet'; // very clear that barrel file is optional
const invokeGreet = useActivity<greet>('greet', {
startToCloseTimeout: '1 minute',
// retries, etc
});
/** A workflow that simply calls an activity */
export async function example(name) {
return await invokeGreet('world')
}this means that you cant do the fancy multiple destructures, but hopefully usage will be much simplier because "less magic"...
import { useActivity, ActivityOptions } from '@temporalio/workflow';
import type foo, bar, baz from './activities'
const options: ActivityOptions = {
startToCloseTimeout: '1 minute',
// retries, etc
}
const invokeFoo = useActivity<foo>('foo', options)
const invokeBar = useActivity<bar>('bar', options)
const invokeBaz = useActivity<baz>('baz', options)
/** A workflow that simply calls an activity */
export async function example(name) {
await invokeFoo('world')
await invokeBar('world')
await invokeBaz(123, 345)
}
Uh oh!
There was an error while loading. Please reload this page.