Skip to content
Draft
2,328 changes: 2,328 additions & 0 deletions cross-sdk-design.md

Large diffs are not rendered by default.

48 changes: 38 additions & 10 deletions temporalio/activity.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should go ahead and put here the expected changes to activity runtime. Specifically I assume all workflow_-prefixed fields of Info will become optional. I would also recommend either a "kind" enumerate for activities, or add an is_standalone akin to is_local so users can know it's not the traditional activity.

Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@
from typing import (
TYPE_CHECKING,
Any,
List,
NoReturn,
Optional,
Tuple,
Type,
Union,
overload,
)

Expand Down Expand Up @@ -109,16 +105,26 @@ class Info:
heartbeat_details: Sequence[Any]
heartbeat_timeout: timedelta | None
is_local: bool
namespace: str
"""Namespace the activity is running in."""
schedule_to_close_timeout: timedelta | None
scheduled_time: datetime
start_to_close_timeout: timedelta | None
started_time: datetime
task_queue: str
task_token: bytes
workflow_id: str
workflow_namespace: str
workflow_run_id: str
workflow_type: str
workflow_id: str | None
"""ID of the workflow that started this activity. None for standalone activities."""
workflow_namespace: str | None
"""Namespace of the workflow that started this activity. None for standalone activities.

.. deprecated::
Use :py:attr:`namespace` instead.
"""
workflow_run_id: str | None
"""Run ID of the workflow that started this activity. None for standalone activities."""
workflow_type: str | None
"""Type of the workflow that started this activity. None for standalone activities."""
priority: temporalio.common.Priority
retry_policy: temporalio.common.RetryPolicy | None
"""The retry policy of this activity.
Expand All @@ -127,14 +133,22 @@ class Info:
If the value is None, it means the server didn't send information about retry policy (e.g. due to old server
version), but it may still be defined server-side."""

activity_run_id: str | None = None
"""Run ID of this standalone activity. None for workflow activities."""

@property
def in_workflow(self) -> bool:
"""Whether this activity was started by a workflow (vs. standalone)."""
return self.workflow_id is not None

# TODO(cretz): Consider putting identity on here for "worker_id" for logger?

def _logger_details(self) -> Mapping[str, Any]:
return {
"activity_id": self.activity_id,
"activity_type": self.activity_type,
"attempt": self.attempt,
"namespace": self.workflow_namespace,
"namespace": self.namespace,
"task_queue": self.task_queue,
"workflow_id": self.workflow_id,
"workflow_run_id": self.workflow_run_id,
Expand Down Expand Up @@ -243,7 +257,7 @@ def metric_meter(self) -> temporalio.common.MetricMeter:
info = self.info()
self._metric_meter = self.runtime_metric_meter.with_additional_attributes(
{
"namespace": info.workflow_namespace,
"namespace": info.namespace,
"task_queue": info.task_queue,
"activity_type": info.activity_type,
}
Expand Down Expand Up @@ -582,6 +596,20 @@ def must_from_callable(fn: Callable) -> _Definition:
f"Activity {fn_name} missing attributes, was it decorated with @activity.defn?"
)

@classmethod
def get_name_and_result_type(
Copy link
Member

@cretz cretz Oct 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're extracting this common logic out of workflow_instance.py, can we update workflow_instance.py use this too? Also, then can we get rid of must_from_callable and inline it into this method since it won't be called anywhere anymore?

cls, name_or_run_fn: str | Callable[..., Any]
) -> tuple[str, Type | None]:
if isinstance(name_or_run_fn, str):
return name_or_run_fn, None
elif callable(name_or_run_fn):
defn = cls.must_from_callable(name_or_run_fn)
if not defn.name:
raise ValueError(f"Activity {name_or_run_fn} definition has no name")
return defn.name, defn.ret_type
else:
raise TypeError("Activity must be a string or callable")

@staticmethod
def _apply_to_callable(
fn: Callable,
Expand Down
10 changes: 9 additions & 1 deletion temporalio/api/activity/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
from .message_pb2 import ActivityOptions
from .message_pb2 import (
ActivityExecutionInfo,
ActivityExecutionListInfo,
ActivityExecutionOutcome,
ActivityOptions,
)

__all__ = [
"ActivityExecutionInfo",
"ActivityExecutionListInfo",
"ActivityExecutionOutcome",
"ActivityOptions",
]
66 changes: 63 additions & 3 deletions temporalio/api/activity/v1/message_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading