Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
{
"editor.formatOnSave": true
}
2 changes: 1 addition & 1 deletion docs/cloud/get-started/api-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ To use your API key with a Temporal SDK, see the instructions in each SDK sectio

[How to connect to Temporal Cloud using an API Key with the Java SDK](/develop/java/temporal-client#connect-to-temporal-cloud)

[How to connect to Temporal Cloud using an API Key with the Python SDK](/develop/python/temporal-client#connect-to-temporal-cloud)
[How to connect to Temporal Cloud using an API Key with the Python SDK](/develop/python/client/temporal-client#connect-to-temporal-cloud)

[How to connect to Temporal Cloud using an API Key with the TypeScript SDK](/develop/typescript/temporal-client#connect-to-temporal-cloud)

Expand Down
2 changes: 1 addition & 1 deletion docs/cloud/get-started/certificates.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ To view the current certificate filters, use the
- [Go SDK](/develop/go/temporal-client#connect-to-temporal-cloud)
- [Java SDK](/develop/java/temporal-client#connect-to-temporal-cloud)
- [PHP SDK](/develop/php/temporal-client#connect-to-a-dev-cluster)
- [Python SDK](/develop/python/temporal-client#connect-to-temporal-cloud)
- [Python SDK](/develop/python/client/temporal-client#connect-to-temporal-cloud)
- [TypeScript SDK](/develop/typescript/temporal-client#connect-to-temporal-cloud)
- [.NET SDK](/develop/dotnet/temporal-client#connect-to-temporal-cloud)

Expand Down
4 changes: 2 additions & 2 deletions docs/cloud/get-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ See our guides for connecting each SDK to your Temporal Cloud Namespace:

- [Connect to Temporal Cloud in Go](/develop/go/temporal-client#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in Java](/develop/java/temporal-client#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in Python](/develop/python/temporal-client#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in Python](/develop/python/client/temporal-client#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in TypeScript](/develop/typescript/core-application#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in .NET](/develop/dotnet/temporal-client#connect-to-temporal-cloud)
- [Connect to Temporal Cloud in PHP](/develop/php/temporal-client#connect-to-temporal-cloud)
Expand All @@ -66,7 +66,7 @@ See our guides for starting a workflow using each SDK:

- [Start a workflow in Go](/develop/go/temporal-client#start-workflow-execution)
- [Start a workflow in Java](/develop/java/temporal-client#start-workflow-execution)
- [Start a workflow in Python](/develop/python/temporal-client#start-workflow-execution)
- [Start a workflow in Python](/develop/python/client/temporal-client#start-workflow-execution)
- [Start a workflow in TypeScript](/develop/typescript/core-application#start-workflow-execution)
- [Start a workflow in .NET](/develop/dotnet/temporal-client#start-workflow)
- [Start a workflow in PHP](/develop/php/temporal-client#start-workflow-execution)
Expand Down
4 changes: 2 additions & 2 deletions docs/cloud/metrics/prometheus-grafana.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ If you're following through with the examples provided here, ensure that you hav
- [Go](/develop/go/temporal-client#connect-to-temporal-cloud)
- [Java](/develop/java/temporal-client#connect-to-temporal-cloud)
- [PHP](/develop/php/temporal-client#connect-to-a-dev-cluster)
- [Python](/develop/python/temporal-client#connect-to-temporal-cloud)
- [Python](/develop/python/client/temporal-client#connect-to-temporal-cloud)
- [TypeScript](/develop/typescript/core-application#connect-to-temporal-cloud)
- [.NET](/develop/dotnet/temporal-client#connect-to-temporal-cloud)

Expand Down Expand Up @@ -95,7 +95,7 @@ Each language development guide has details on how to set this up.
- [Go SDK](/develop/go/observability#metrics)
- [Java SDK](/develop/java/observability#metrics)
- [TypeScript SDK](/develop/typescript/observability#metrics)
- [Python](/develop/python/observability#metrics)
- [Python](/develop/python/workers/observability#metrics)
- [.NET](/develop/dotnet/observability#metrics)

The following example uses the Java SDK to set the Prometheus registry and Micrometer stats reporter, set the scope, and expose an endpoint from which Prometheus can scrape the SDK metrics.
Expand Down
6 changes: 3 additions & 3 deletions docs/develop/plugins-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ plugin = SimplePlugin(

### Interceptors

Interceptors are middleware that can run before and after various calls such as Activities, Workflows, and Signals. You can [learn more about interceptors](/develop/python/interceptors) for the details of implementing them. They're used to:
Interceptors are middleware that can run before and after various calls such as Activities, Workflows, and Signals. You can [learn more about interceptors](/develop/python/workers/interceptors) for the details of implementing them. They're used to:

- Create side effects such as logging and tracing.
- Modify arguments, such as adding headers for authorization or tracing propagation.
Expand All @@ -222,7 +222,7 @@ plugin = SimplePlugin(

Each of the SDKs has nuances you should be aware of so you can account for it in your code.

For example, you can choose to [run your Workflows in a sandbox in Python](/develop/python/python-sdk-sandbox). This lets you run Workflow code in a sandbox environment to help prevent non-determinism errors in your application. To work for users who use sandboxing, your Plugin should specify the Workflow runner that it uses.
For example, you can choose to [run your Workflows in a sandbox in Python](/develop/python/best-practices/python-sdk-sandbox). This lets you run Workflow code in a sandbox environment to help prevent non-determinism errors in your application. To work for users who use sandboxing, your Plugin should specify the Workflow runner that it uses.

Here's an example of how to explicitly define the Workflow runner for your Plugin with Python:

Expand Down Expand Up @@ -250,7 +250,7 @@ Two special concerns are versioning tests, for when you're making changes to you

### Versioning tests

When you make changes to your plugin after it has already shipped to users, it's recommended that you set up [replay testing](/develop/python/testing-suite#replay) on each important change to make sure that you’re not causing non-determinism errors for your users.
When you make changes to your plugin after it has already shipped to users, it's recommended that you set up [replay testing](/develop/python/best-practices/testing-suite#replay) on each important change to make sure that you’re not causing non-determinism errors for your users.

### Side effects tests

Expand Down
161 changes: 161 additions & 0 deletions docs/develop/python/activities/basics.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
---
id: basics
title: Activity Basics - Python SDK
sidebar_label: Activity Basics
description: This section explains Activity Basics with the Python SDK
toc_max_heading_level: 4
keywords:
- Python SDK
tags:
- Python SDK
- Temporal SDKs
---

## Develop a basic Activity {#develop-activities}

**How to develop a basic Activity using the Temporal Python SDK.**

One of the primary things that Workflows do is orchestrate the execution of Activities. An Activity is a normal function
or method execution that's intended to execute a single, well-defined action (either short or long-running), such as
querying a database, calling a third-party API, or transcoding a media file. An Activity can interact with world outside
the Temporal Platform or use a Temporal Client to interact with a Temporal Service. For the Workflow to be able to
execute the Activity, we must define the [Activity Definition](/activity-definition).

You can develop an Activity Definition by using the `@activity.defn` decorator. Register the function as an Activity
with a custom name through a decorator argument, for example `@activity.defn(name="your_activity")`.

:::note

The Temporal Python SDK supports multiple ways of implementing an Activity:

- Asynchronously using [`asyncio`](https://docs.python.org/3/library/asyncio.html)
- Synchronously multithreaded using
[`concurrent.futures.ThreadPoolExecutor`](https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor)
- Synchronously multiprocess using
[`concurrent.futures.ProcessPoolExecutor`](https://docs.python.org/3/library/concurrent.futures.html#processpoolexecutor)
and
[`multiprocessing.managers.SyncManager`](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.managers.SyncManager)

Blocking the async event loop in Python would turn your asynchronous program into a synchronous program that executes
serially, defeating the entire purpose of using `asyncio`. This can also lead to potential deadlock, and unpredictable
behavior that causes tasks to be unable to execute. Debugging these issues can be difficult and time consuming, as
locating the source of the blocking call might not always be immediately obvious.

Due to this, consider not make blocking calls from within an asynchronous Activity, or use an async safe library to
perform these actions. If you must use a blocking library, consider using a synchronous Activity instead.

:::

<div className="copycode-notice-container">
<a href="https://github.com/temporalio/documentation/blob/main/sample-apps/python/your_app/your_activities_dacx.py">
View the source code
</a>{' '}
in the context of the rest of the application code.
</div>

```python
from temporalio import activity
# ...
# ...
@activity.defn(name="your_activity")
async def your_activity(input: YourParams) -> str:
return f"{input.greeting}, {input.name}!"
```

### Develop Activity Parameters {#activity-parameters}

**How to develop Activity Parameters using the Temporal Python SDK.**

There is no explicit limit to the total number of parameters that an [Activity Definition](/activity-definition) may
support. However, there is a limit to the total size of the data that ends up encoded into a gRPC message Payload.

A single argument is limited to a maximum size of 2 MB. And the total size of a gRPC message, which includes all the
arguments, is limited to a maximum of 4 MB.

Also, keep in mind that all Payload data is recorded in the
[Workflow Execution Event History](/workflow-execution/event#event-history) and large Event Histories can affect Worker
performance. This is because the entire Event History could be transferred to a Worker Process with a
[Workflow Task](/tasks#workflow-task).

{/* TODO link to gRPC limit section when available */}

Some SDKs require that you pass context objects, others do not. When it comes to your application data—that is, data
that is serialized and encoded into a Payload—we recommend that you use a single object as an argument that wraps the
application data passed to Activities. This is so that you can change what data is passed to the Activity without
breaking a function or method signature.

Activity parameters are the function parameters of the function decorated with `@activity.defn`. These can be any data
type Temporal can convert, including dataclasses when properly type-annotated. Technically this can be multiple
parameters, but Temporal strongly encourages a single dataclass parameter containing all input fields.

<div className="copycode-notice-container">
<a href="https://github.com/temporalio/documentation/blob/main/sample-apps/python/your_app/your_activities_dacx.py">
View the source code
</a>{' '}
in the context of the rest of the application code.
</div>

```python
from temporalio import activity
from your_dataobject_dacx import YourParams

# ...
# ...
@activity.defn(name="your_activity")
async def your_activity(input: YourParams) -> str:
return f"{input.greeting}, {input.name}!"
```

### Define Activity return values {#activity-return-values}

**How to define Activity return values using the Temporal Python SDK.**

All data returned from an Activity must be serializable.

Activity return values are subject to payload size limits in Temporal. The default payload size limit is 2MB, and there
is a hard limit of 4MB for any gRPC message size in the Event History transaction
([see Cloud limits here](https://docs.temporal.io/cloud/limits#per-message-grpc-limit)). Keep in mind that all return
values are recorded in a [Workflow Execution Event History](/workflow-execution/event#event-history).

An Activity Execution can return inputs and other Activity values.

The following example defines an Activity that takes an object as input and returns a string.

<div className="copycode-notice-container">
<a href="https://github.com/temporalio/documentation/blob/main/sample-apps/python/your_app/your_activities_dacx.py">
View the source code
</a>{' '}
in the context of the rest of the application code.
</div>

```python
# ...
@activity.defn(name="your_activity")
async def your_activity(input: YourParams) -> str:
return f"{input.greeting}, {input.name}!"
```

### Customize your Activity Type {#activity-type}

**How to customize your Activity Type**

Activities have a Type that are referred to as the Activity name. The following examples demonstrate how to set a custom
name for your Activity Type.

You can customize the Activity name with a custom name in the decorator argument. For example,
`@activity.defn(name="your-activity")`. If the name parameter is not specified, the Activity name defaults to the
function name.

<div className="copycode-notice-container">
<a href="https://github.com/temporalio/documentation/blob/main/sample-apps/python/your_app/your_activities_dacx.py">
View the source code
</a>{' '}
in the context of the rest of the application code.
</div>

```python
# ...
@activity.defn(name="your_activity")
async def your_activity(input: YourParams) -> str:
return f"{input.greeting}, {input.name}!"
```
Loading