Skip to content

💥 Standalone activity support - #609

Merged
cretz merged 5 commits into
temporalio:mainfrom
cretz:standalone-activities
Feb 19, 2026
Merged

cretz merged 5 commits into
temporalio:mainfrom
cretz:standalone-activities

Conversation

@cretz

@cretz cretz commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

What was changed

  • Added StartActivityOptions, ActivityDescribeOptions, ActivityCancelOptions, ActivityTerminateOptions, ActivityListOptions, ActivityListPaginatedOptions, ActivityCountOptions
  • Added ActivityHandle and ActivityHandle<TResult> with GetResultAsync, DescribeAsync, CancelAsync, TerminateAsync
  • Added ActivityExecution, ActivityExecutionDescription, ActivityExecutionCount, ActivityListPage model classes
  • Added ActivityFailedException and ActivityAlreadyStartedException exceptions
  • Added StartActivityAsync, GetActivityHandle, ListActivitiesAsync, CountActivitiesAsync, ListActivitiesPaginatedAsync on ITemporalClient
  • Added ExecuteActivityAsync extension methods on ITemporalClient (start + get result shortcut, 4 overloads matching workflow pattern)
  • Added interceptor inputs: StartActivityInput, DescribeActivityInput, CancelActivityInput, TerminateActivityInput, ListActivitiesInput, ListActivitiesPaginatedInput, CountActivitiesInput
  • Added activity methods on ClientOutboundInterceptor
  • Added timeout validation requiring ScheduleToCloseTimeout or StartToCloseTimeout on StartActivityOptions
  • Updated ISerializationContext.Activity to support standalone activities: ActivityId added, WorkflowId/WorkflowType now nullable, some fields deprecated
    • 💥 BACKWARDS INCOMPATIBLE CHANGE - changing some items to nullable here, though only nullable in standalone situations. Also deprecated some items.
  • Updated ActivityInfo with Namespace, IsWorkflowActivity, and nullable workflow fields (WorkflowId, WorkflowNamespace, WorkflowRunId, WorkflowType)
    • 💥 BACKWARDS INCOMPATIBLE CHANGE - changing some items to nullable here, though only nullable in standalone situations
  • Fixed NullReferenceException in ActivityWorker.StartActivity when CurrentAttemptScheduledTime is null for standalone activities
  • Added error handling in activity worker poll loop so StartActivity failures complete the task as failed instead of crashing the worker
  • Updated dev server to v1.6.1-server-1.31.0-150.0 with standalone activity dynamic config flags
  • Added 12 integration tests covering start/execute, already-started/reuse-policy errors, get handle, describe, cancel, terminate, list/count/paginate, interceptors, and worker activity info

Checklist

  1. Closes [Feature Request] Support standalone activities #568

@cretz cretz changed the title Standalone activity support 💥 Standalone activity support Feb 13, 2026
Comment thread .github/workflows/ci.yml
dotnet-repo-path: ${{github.event.pull_request.head.repo.full_name}}
version: ${{github.event.pull_request.head.ref}}
version-is-repo-ref: true
features-repo-ref: standalone-activities-dotnet

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note, we will need to merge this branch into features repo right after this PR is merged.

@cretz
cretz marked this pull request as ready for review February 13, 2026 15:28
@cretz
cretz requested a review from a team as a code owner February 13, 2026 15:28
/// are required.
/// </summary>
/// <remarks>WARNING: Standalone activities are experimental.</remarks>
public class StartActivityOptions : ICloneable

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Note, after internal discussions, we chose StartActivityOptions to not clash with existing ActivityOptions which is kinda a uniquely .NET problem of preventing clashes across the entire assembly (instead of just namespace)

["WorkflowId"] = WorkflowId,
["WorkflowRunId"] = WorkflowRunId,
["WorkflowType"] = WorkflowType,
["Namespace"] = Namespace,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we maybe preserve WorkflowNamespace and only fill it if it's workflow activity? That way we don't wholesale break anyone who is scraping logs, especially for those who aren't using this experimental feature yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can, though the question is whether we should also emit a Namespace at that time? Is it worth the redundant scope?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thinking this through...

Previously, WorkflowNamespace was always added as a scope value and always had a value. Log scraping/queries who look for it a likely relying on it being there. With this change as-is, that key will no longer be there at all. So they would have to adjust their code to find the new kew.

With my suggestion, WorkflowNamespace would still be provided under those circumstances IF they don't start using standalone activities. Once they start using standalone activities, some of their log entries won't have WorkflowNamespace (for those that are standalone activities). This would avoid a break until they start using the experimental feature.

So questions are:

  • do we break now while the feature is still experimental and probably not used in environments where log scraping is occurring? Maybe we can defer the break until standalone activities is GA?
  • do we break only for standalone activities?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right, all of that makes sense, and I don't have a strong opinion on whether to break existing log scope keys now, later, or not at all. It makes sense for me to put WorkflowNamespace back for now.

What I was asking was a followup question - do we emit Namespace always or only for standalone activities?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we always emit Namespace and say that we're deprecating WorkflowNamespace.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍 I will add the redundant log tag for the majority of users

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Meaning all workflow logs will have Namespace and WorkflowNamespace, but all new standalone activity logs will have just Namespace, assuming that is what you meant.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm fine with theremoval of WorkflowNamespace now as you have in this PR. If we are ever going to remove it, I think now is better than later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍 Same for other workflow tags. Can you take a look at 287ed97 and confirm it is what you were thinking?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm :shipit:

Comment thread src/Temporalio/Client/ActivityExecution.cs
Comment thread src/Temporalio/Client/ActivityExecution.cs
@cretz
cretz merged commit 39dba9a into temporalio:main Feb 19, 2026
10 checks passed
@cretz
cretz deleted the standalone-activities branch February 19, 2026 15:33
THardy98 added a commit to temporalio/omes that referenced this pull request Mar 23, 2026
## What was changed
SDK PR
temporalio/sdk-dotnet#609 (standalone activity
support) made ActivityInfo.WorkflowId nullable (string?). The omes .NET
worker has `TreatWarningsAsErrors` enabled, so CS8604 (possible null
reference) becomes a hard build error.

This causes omes runs that build .NET worker from source to fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Support standalone activities

2 participants