1

I have the following Temporal workflow, written in Python:

@workflow.defn
class YourSchedulesWorkflow:

@workflow.run
async def run(self, name: str) -> str:
    //call javascript activity

I have a part of code written already in JavaScript, so I want to call that JavaScript code as an activity, from my Python workflow. How do I do this?

2
  • Hello, without context on your problem and the environment that you are working on I said that you could introduce a "proxy" between the two script. Using a bash script (if you are on Unix) that runs a "JavaScript" script file from your "python" code throug the subprocess python module, ofc. that I am not considering some "data interaction" between those scripts. So the flow that comes to my mind is, python -> bash -> JavaScript. Commented Aug 11, 2023 at 20:59
  • @FrancoGil Tag is saying temporal-workflow, which is an open source workflow-as-code platform (temporal.io). Indeed, OP should have indicated this more clearly, as the question can't make sense outside of that specific context. Commented Aug 11, 2023 at 21:08

1 Answer 1

1

From Temporal’s point of view, scheduling an activity only requires the activity's name (which we formally call the "activity type") and its task queue; the Temporal server itself doesn't "need" the activity function, nor care in which language is it coded.

The easiest way for your Python workflow to invoke a TypeScript activity is therefore to simply provide the correct activity type, as a string, to the execute_activity function, as well as the task queue name (plus any other args/options you would otherwise want to pass). From the workflow's perspective, it makes no difference that the activity is implemented in a different language, except for the fact that it can't benefit from type safety checks that having an actual function definition allows.

For example, you might do this in your workflow:

@workflow.run
async def run(self, name: str) -> str:
    return await workflow.execute_activity(
        "composeGreeting",
        ComposeGreetingInput("Hello", name),
        start_to_close_timeout=timedelta(seconds=10),
        task_queue="typescript-activities",
    )

and then, start a TypeScript worker listening on task queue "typescript-activities", with the following activity:

  async function composeGreeting(input: ComposeGreetingInput): Promise<string> {
    return input.items.join(" ");
  }

Alternatively, it is also possible to define a stub function on your workflow side, to make cross-language activity calls looks more like regular, same-language activity calls. For example:

@workflow.run
async def run(self, name: str) -> str:
    return await workflow.execute_activity(
        compose_greeting,
        ComposeGreetingInput("Hello", name),
        start_to_close_timeout=timedelta(seconds=10),
        task_queue="typescript-activities",
    )

@activity.defn(name="composeGreeting")
async def compose_greeting(name: ComposeGreetingInput) -> str:
    # This function is meant to be a stub; it doesn't need to be registered
    # as an activity on a worker, and it will never get called. You however
    # need to make sure that this function's signature exactly matches that
    # of its TypeScript counterpart. Note the `name="composeGreeting"` arg
    # on the decorator above. That means that the activity type will be
    # `composeGreeting` (following the TS convention), rather than
    # `compose_greeting`, which is the name of this Python function and
    # would therefore have been the default workflow type.
    return f""

A few things to consider:

  • You will need a different task queue for your Python activities vs TS activities
  • Different languages have different conventions regarding function naming, and different SDKs may have different rules regarding how function names relate to activity types. When doing activity call across SDK, you may need to force the activity type on the activity worker, or use the correct syntax of the Activity Type on the Workflow side.
  • SDKs should generally encode/decode args and return values correctly, but cross-SDK calls may expose differences in how various JSON libraries handle some particular cases. You should therefore be more cautious in defining your data structures. Only use simple types that are natively understood by JSON. Beware of “big integers”, dates, and similar.
  • Similarly, SDK will correctly route errors thrown from activities back to the Workflow. You may however note some discrepancies in how “language native” errors get encoded/decoded. Make sure you test error handling properly.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.