temporalio / temporalio/sdk-typescript

[Feature Request] Less boiler plate.

Open
#813 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
917
Forks
224
Avg merge
3d 16h
Merged PRs (30d)
43

Description

I've been using temporal in production for about 3 months now. We have 11 workers, so still small, but moving more of our system over to it. In many ways I love it, it really is like React for the Backend. I'm primarily a FE dev, but now that I run my own startup, I have evolved to be full stack.

The main thing that puts me off from moving more of my stack over to Temporal is the boiler plate. Right now it feels like React Classes, I want React Functions.

Below is my current flow to get to the point of being able to write a worker:

  1. Make file for worker:

    type activities = {
      deleteUser: typeOf deleteUserActivity
    }
    
    const {
      deleteUser
    } = proxyActivities<activities>({
      startToCloseTimeout: '30s', // recommended
      scheduleToCloseTimeout: '5m', // useful
      // The below is a Retry Policy. It is used to retry the Activity if it fails.
      retry: {
        // These are the values of the Default Retry Policy
        initialInterval: '1s',
        backoffCoefficient: 2,
        nonRetryableErrorTypes: [],
      },
    })
    
    export async function deleteUser(params: DeleteUserRequest): Promise<void> {
      await deleteUser(params)
    }
    
  2. Make new activity

    export const deleteUser = async (params: {
      userId: string
      orgId: string
    }) => {
      await Promise.all([
        deleteFromDB(`users/${userId}`),
        removeUserFromOrganization(params),
      ])
    }
    
  3. Update worker.ts

    const deleteUserActivities = {
      deleteUser
    }
    
    async function run() {
      const workers = await Promise.all([
        // deleteUser
        Worker.create({
          ...workflowOption('workflows/users/deleteUser.workflow.ts'),
          namespace: env.NAMESPACE,
          connection,
          interceptors: {
            activityInbound: [
              (ctx) => new ActivityInboundLogInterceptor(ctx, activityLogger),
            ],
            workflowModules: [require.resolve('workflows/workflowsInterceptor')],
          },
          activities: deleteUserActivities,
          taskQueue: TaskQueue.DeleteUser,
          sinks,
          maxCachedWorkflows: 4,
          maxConcurrentWorkflowTaskExecutions: 4,
        }),
      ])
    }
    

This is a lot to start making a single workflow. If you mess anything up along the way, everything breaks. It feels like Temporal needs JSX. What I mean by that is some kind of preprocessor that will spit all this out for you.

In a perfect world:

  1. Workflow definition and options should be colocated.
    1. Workflow options can be overridden when they are called.
  2. Activities should just work with default settings.
    1. Activities should be anything that is a promise or anything that leads to a promise. I have lots of code that prepares a promise, eg () => async () => unknown.
  3. Type checking of input and output with zod should be standard, and enforced. Use the good work that tRPC is doing in making typesafe api's.
  4. Autoworkflow wrapper. I have a bunch of non temporal node code that I wish I didn't have to rewrite from the ground up. Having something that could wrap it as one giant activity, a la dangerouslySetInnerHtml. You know the risk going it, but it can jump start your switch to Temporal.

Pseudo Example:

export const deleteUser = Worker
  .create<
    'deleteUser',
    DeleteUserRequest,
    DeleteUserResponse,
  >('deleteUser',
  {
    /* workflow options */
    input: DeleteUserRequest,
    output: DeleteUserResponse,
    async resolve(request) {
      const { userId, orgId } = request
      
      await deleteUser({ userId, orgId })
    }
  })

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the Worker.create and proxyActivities APIs, along with the worker.ts setup shown in the issue. Compare the requested colocated workflows, default activities, type validation, and autowrapping ideas with existing SDK entry points; the work is done only when a specific, agreed API and scope has been implemented and tested.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, distributed-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.