Skip to content

Releases: temporalio/sdk-dotnet

1.1.2

05 Jun 12:43
7b61747
Compare
Choose a tag to compare

Get from NuGet and read the README

Highlights

This is mostly a bug fix release.

💥 Fix Workflow.WaitConditionAsync issue introduced in 1.1.1

There is a bug introduced 1.1.1 where WaitConditionAsync could never be properly resolved. This release fixes that bug by (mostly) reverting to behavior in 1.1.0. There is technically a situation where, if your workflow has run in 1.1.1 and encountered this bug, this fix could lead to non-determinism.

💥 Breaking change on experimental workflow update

Updates, still experimental, now require the WaitForStage option to be set when using StartUpdateAsync. Also the UpdateID property in the options is just Id now.

Specific Changes

2024-05-21 - 618e878 - Required wait update stage and polling improvements (#251)
2024-05-22 - 1645178 - Improved docs for RetryPolicy.NonRetryableErrorTypes (#252)
2024-05-28 - ef70705 - Support ApplicationFailureException.NextRetryDelay (#254)
2024-05-29 - 1f6676b - Extended reporting of failed workflow with OTel (#255)
2024-06-04 - 0e24a43 - feat: add workflow client updater for updating workflow client (#258)
2024-06-04 - 43d0f86 - Update generated rpc requests to not omit ConfigureAwait(false) (#260)
2024-06-04 - 83670a0 - Fix wait condition evaluation issue (#259)

1.1.1

10 May 13:34
48fac0c
Compare
Choose a tag to compare

Get from NuGet and read the README

Highlights

This is just a bug-fix release, no significant highlights of note.

Specific Changes

2024-05-08 - 5cd6f59 - Run wait-condition callbacks in workflow context (#242)
2024-05-08 - f40e78e - Fix issue enumerating services in newer .NET DI library (#241)

1.1.0

07 May 19:43
ee378c1
Compare
Choose a tag to compare

Get from NuGet and read the README

Highlights

Experimental Workflow Failure Type Customization

When a workflow raises an exception that wasn't ApplicationFailureException or bubbled from a Temporal call (e.g. activity failure), it would be a "task failure" which puts the workflow in a suspended state retrying the task until a code fix is deployed. An experimental feature is now available that lets users set which exception types should instead fail the workflow instead of suspending it. Users can now set the per-workflow FailureExceptionTypes on the [Workflow] attribute or set the worker-level WorkflowFailureExceptionTypes option when creating the TemporalWorker. If an exception extends from one of these when raised, it will fail the workflow when raised.

Worker Client Replacement

Workers can now have the client they use replaced without shutting down the worker. The Client property on the TemporalWorker can be set to a different connected client. This is useful for users that need to change options like mTLS client certificate without worker downtime. The worker will not interrupt any polling calls but will start using the new client for subsequent calls.

API Key Client Option

If you use API keys in your Temporal server (i.e. Bearer tokens on Authorization headers), you can now set ApiKey option when connecting a TemporalClient/TemporalConnection or set the ApiKey property on an existing connection to update it.

Floats and Durations in Metrics

Users using MetricMeter directly to create metrics (off of runtime, activity, or workflow) can now create float-based histograms and gauges, and duration-based histograms. Similarly users using ICustomMetricMeter to retrieve metrics can say how they want to retrieve durations (float seconds, int milliseconds, or TimeSpan). A UseSecondsForDuration option was added to telemetry options for users that prefer seconds as float-based durations to OpenTelemetry and Prometheus instead of the default of integer milliseconds.

💥 This has a minor compatibility break. For users that implemented ICustomMetricMeter, calls on that interface can now start passing in double and TimeSpan where it didn't before, but only if users start using those types of metrics.

Counting Workflows

A new CountWorkflowsAsync call has been added to the ITemporalClient that takes the same query as ListWorkflowsAsync but is optimized just to perform counts.

Specific Changes

2024-01-05 - 0e592ee - Fix issue with DI-based static async activities (#172)
2024-01-10 - 53a8a3d - Properly ignore unknown fields when parsing history JSON (#175)
2024-01-12 - 7127437 - Add build id to workflow context (#174)
2024-01-19 - ba4763b - Fix issue with Rust cache using newer node version (#177)
2024-02-01 - 79104b6 - Prefix some errors with rule identifiers (#180)
2024-02-12 - bfe4b3a - Doc/README updates (#188)
2024-02-27 - 66abe70 - Update core (#192)
2024-02-28 - c703da9 - Add type-safe SignalWithStart (#193)
2024-03-01 - e99bcb0 - Eager workflow start (#195)
2024-03-07 - 666ab45 - Fix issue with unconfigured metric meter (#202)
2024-03-07 - ce3f195 - Worker poller and ratio options (#200)
2024-03-08 - 070fba5 - Use Debugger.IsAttached to affect default for debug mode (#201)
2024-03-12 - 3faaf2b - Client API key (#203)
2024-03-21 - 67a52ff - Ability for certain task failure types to fail workflow (#205)
2024-03-21 - d2be959 - Add Client.CountWorkflowsAsync (#206)
2024-03-26 - c6b7aca - Alternative CreateTemporalActivityDefinition (#207)
2024-03-29 - 7d37b9d - Fix README snippet (#213)
2024-04-02 - 070faac - Remove experimental flag from StartDelay (#208)
2024-04-16 - 740dfa2 - Use build ID in the unique DI identifier for workers (#216)
2024-04-19 - 1573d3a - Support duration and float metrics (#223)
2024-04-21 - e11dfd5 - Correct xmldoc spelling error on WorkflowAttribute (#227)
2024-04-22 - 899672c - Make ctor for DefaultPayloadConverter public to expose JsonSerializerOptions (#226)
2024-04-24 - 2bd9ed3 - Readme updates (#230)
2024-04-25 - 9c1c127 - Use macos-12 GHA runners instead of macos-latest (#232)
2024-04-26 - f1b8dde - Support macOS ARM + macOS Intel and update proto generation (#233)
2024-05-06 - e771d5b - Worker client replacement (#236)

1.0.0

05 Dec 14:46
b64dd6d
Compare
Choose a tag to compare

Get from NuGet and read the README

Highlights

Temporal .NET SDK Generally Available

With this 1.0.0 release, the .NET SDK is now considered stable. This means it has been thoroughly used and tested to ensure it meets Temporal quality standards. Throughout the prerelease period, we have received ample feedback and have adjusted the SDK as needed to address feedback and address any issues encountered. We strive to not make any backwards incompatible changes.

Log Forwarding

The Core logic powering the SDK is written in Rust and emits its own logs to console in many situations. Until now, users could only control the level of this log but not adjust where it was emitted or how. Now, with #153, users can set Temporalio.Runtime.LoggingOptions.Forwarding.Logger to an ILogger which will forward all logs from Rust to the .NET logger in a reasonably performant manner.

Specific Changes

2023-11-08 - abab4b2 - Update README.md to remove note about DI issue (#152)
2023-11-14 - 67a2572 - Log forwarding (#153)
2023-11-16 - 32411c7 - Demonstrate OpenTelemetry + dependency injection (#154)
2023-11-17 - 8626167 - Delete .github/workflows/semgrep.yml (#159)
2023-12-04 - 7c07aa7 - Handle new .NET 8 analyzer suggestions (#164)

0.1.0-beta2

30 Oct 16:53
5b10051
Compare
Choose a tag to compare

Get from NuGet and read the README

⚠️ This is a beta release.

Highlights

Advanced Metrics Support

The Rust core that the .NET SDK uses has always provided metrics and a way to export via OpenTelemetry or Prometheus. This release improves the exposure of these metrics in few ways:

First, a MetricMeter property has been added to TemporalRuntime, ActivityExecutionContext, and Workflow for those wanting to record their own metrics using the core-based metrics (but it is often still more desirable to use one's own metrics implementation). The Workflow.MetricMeter has logic to ignore metrics recorded inside workflows.

Second, a Temporal runtime is the overall object created to power Temporal features (if not using the default) and its MetricOptions now have a CustomMetricMeter which accepts a ICustomMetricMeter implementation. If set, this interface will be used for all core-based metrics.

Finally a new extension project, Temporalio.Extensions.DiagnosticSource, has been created which contains an ICustomMetricMeter implementation that sends core metrics to an underlying System.Diagnostics.Metrics.Meter implementation. So with this extension, users can have all internal SDK metrics flow through traditional .NET metrics utilities, even though they originate in Temporal's Rust core.

Several Minor Additions

  • Added Workflow.CurrentHistoryLength, Workflow.CurrentHistorySize, and Workflow.ContinueAsNewSuggested to help developers understand history sizes and when to continue as new
  • Added WorkflowInfo.LastFailure and WorkflowInfo.LastResult for use by workflow retrying and schedules
  • Added TemporalConnectionOptions.KeepAlive to support client keep alive, and defaulted it to 30s interval with 15s timeout
  • Added WorkflowOptions.StartDelay to add a delay to the start of a workflow
  • Added experimental support for workflow update which is only available in bleeding edge open source server environments

💥 BREAKING CHANGES

Only a couple of barely visible, rarely used things were changed this release:

  • Static methods on for creating activity definitions Temporalio.Activities.ActivityDefinition removed cache boolean parameter since caching of activity definitions is no longer that valuable (#118)
  • Removed Temporalio.Runtime.TelemetryOptions.Tracing property and associated class since this was only for advanced internal support for core tracing (i.e. not related to actual Temporal/workflow tracing)

Specific Changes

2023-07-25 - 0cded9b - Remove activity definition cache (#118)
2023-07-25 - 54e61f1 - Clarify in README clients can use the extension project (#120)
2023-07-25 - 612d4ca - Use DI logger factory in worker service and DI clients (#119)
2023-08-07 - 9b92709 - Add history info for workflow (#123)
2023-08-21 - 5b559d5 - Update core and tonic (#127)
2023-08-25 - 9d56fe8 - Improved .NET metrics support (#129)
2023-09-22 - 5cf7a4a - Expose LastFailure and LastResult from WorkflowInfo (#136)
2023-10-06 - 516c72b - Advanced .NET metrics support (#137)
2023-10-09 - ab4ded4 - Client keep alive support (#138)
2023-10-20 - 1cde5c9 - Add missing gRPC calls (#144)
2023-10-24 - bd986d7 - Workflow start delay (#146)
2023-10-25 - ef02df3 - Workflow update (#142)

0.1.0-beta1

24 Jul 13:45
54ff8c5
Compare
Choose a tag to compare

Get from NuGet and read the README

⚠️ This is a beta release and compatibility may not be maintained.

Highlights

This release contains minor improvements over the last alpha release and some breaking changes.

Beta Release

This is the first beta release! This means that the .NET SDK, after months of hard work and feedback, is beta quality. The SDK has been well tested and most major API changes have been settled. Technically breaking changes may still occur until the SDK is marked GA, but we will make clear in these release notes if that occurs.

Experimental Worker Versioning

Support has been added for the brand new Worker Versioning feature. This feature is currently experimental and can only be enabled when running the open source server and setting some special options. Samples for the versioning feature will be present soon.

Better Client Dependency Injection and Lazy Client Support

The Temporalio.Extensions.Hosting extension has a new IServiceCollection.AddTemporalClient extension method which registers a client as a singleton and only connects lazily upon first call. This is made possible by the new TemporalClient.CreateLazy static helper. The client can also be used via dependency injection in worker services.

💥 BREAKING CHANGES

The following refactors occurred:

  • Changed identifiers containing Cancelled to Canceled
  • Changed identifiers containing ID to Id

Specific Changes

2023-07-17 - 945f058 - .NET framework copy targets and smoke test (#102)
2023-07-17 - 9cb71af - Worker Versioning (#103)
2023-07-18 - 0dc06cd - Versioning enum updates, rename "Cancelled" identifiers to "Canceled", and README updates (#112)
2023-07-18 - 32ef77e - Minor README and API doc updates (#96)
2023-07-18 - 370d479 - Rename ID to Id (#111)
2023-07-18 - 52d6868 - Lazy clients, client DI, and health check (#98)
2023-07-20 - 1c14789 - Log and drop signals when we can't decode the arguments (#114)
2023-07-24 - dee4538 - Support for experimental workflow task events (#113)

0.1.0-alpha6

17 Jul 21:49
fd3e104
Compare
Choose a tag to compare

⚠️ THIS IS AN ALPHA RELEASE AND COMPATIBILITY WILL NOT BE MAINTAINED

Get from NuGet and read the README

Highlights

This release introduced two extensions and multiple other helpful features.

Activity dependency injection and generic host support for workers

A new NuGet extension at Temporalio.Extensions.Hosting is now available that adds helpers for adding activities on a service collection that support constructor dependency injection, and adds helpers for running workers as .NET generic hosts. Here's a simple example of creating a .NET host with DI-supported activities:

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Temporalio.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);
// Add a hosted Temporal worker which returns a builder to add activities and workflows
builder.Services.
    AddHostedTemporalWorker("my-temporal-host:7233", "my-namespace", "my-task-queue").
    AddScopedActivities<MyActivityClass>().
    AddWorkflow<MyWorkflow>();

// Run
var host = builder.Build();
host.Run();

See the README on that project for more details.

OpenTelemetry support

A new NuGet extension at Temporalio.Extensions.OpenTelemetry is now available that supports tracing clients, activities, and workflows via OpenTelemetry. This is implemented similar to how we do in our other SDKs and even compatible with them in cross-language scenarios. OpenTelemetry support is built as an interceptor leveraging .NET diagnostic activities and takes care to serialize/deserialize spans across the server boundary so even separate. There are some caveats to be aware of with regards to how OpenTelemetry spans and .NET diagnostic activities behave on workflow replay since spans/activities cannot be resumed. See the README on that project for more details.

Reenable thread pool task checker - 💥 BREAKING CHANGE

In previous versions of the .NET SDK, a tool was on by default to make sure users didn't accidentally schedule tasks from a workflow onto the .NET thread pool. This is needed because it is very easy to accidentally do. This tool was inadvertently disabled by default in the past couple of versions, but has been properly reenabled. This is therefore technically a backwards incompatible behavior change because workflows written within the past couple of versions may now break if they were written improperly.

Dynamic activities, workflows, signals, and queries

Users can now register dynamic activities, workflows, signals, and queries to be invoked as catch-all implementations with raw input payloads when there is not a named item already registered when called. The [Activity], [Workflow], [WorkflowSignal], and [WorkflowQuery] attributes now all support a Dynamic = true property. When an activity or workflow is invoked on a worker with no matching name, the dynamic form will be invoked with IRawValue[] arguments. When a signal or query is called on a workflow with no matching name, the dynamic form will be invoked with a string name and IRawValue[] arguments. Workers can only have one dynamic activity and one dynamic workflow since it is the fall through. Similarly, workflows can only have one dynamic signal and one dynamic query.

Queries can be properties

The getter of a property can now be used as a query. For example, in this workflow:

[Workflow]
public class MyWorkflow
{
    [WorkflowRun]
    public Task RunAsync()
    {
        await Workflow.DelayAsync(5000);
        TimerDone = true;
    }

    [WorkflowQuery]
    public bool TimerDone { get; set; }
}

Can be invoked on a client like:

var myClient = await TemporalClient.ConnectAsync("localhost:7233");

// Start workflow
var myHandle = await myClient.StartWorkflowAsync(
    (MyWorkflow wf) => wf.RunAsync(),
    new(id: "my-workflow-id", taskQueue: "my-task-queue"));

// Query, wait, query again
Console.WriteLine("Done? {0}", await myHandle.QueryAsync(wf => wf.TimerDone));
await Task.Delay(7000);
Console.WriteLine("Done? {0}", await myHandle.QueryAsync(wf => wf.TimerDone));

Designs were considered and rejected for making signals be property setters (but lambda expression trees disallow assignment operators) and activities be property getters (but it is rare/discouraged to make an entire activity a property).

Update test workflow environment local server

The server backing Temporalio.Testing.WorkflowEnvironment.StartLocalAsync() has been upgraded from Temporalite with server version 1.18.1, to the latest Temporal CLI dev server with just-released server version 1.21.0.

Return collections instead of enumerables - 💥BREAKING CHANGE

IPayloadCodec methods now require Task<IReadOnlyCollection<Payload>> instead of enumerables as before. People were getting confused on when mutation would occur when creating lazy linq-based enumerables. Also affects a couple of enumerable properties.

Workflow.WhenAnyAsync added

Due to this issue, Task.WhenAny cannot be trusted to use the current task scheduler in all cases (only most of the time). Therefore a Workflow.WhenAnyAsync helper has been created that is guaranteed to use the current deterministic task scheduler.

Deterministic random with 64-bit seed

A stable, portable, deterministic implementation of System.Random that is initialized with a 64-bit seed is now returned from Workflow.Random. Before, that would return the basic System.Random constructed with a 32-bit seed which is also not technically portable across .NET Framework versions.

Specific Changes

2023-06-06 - 4a99c2f - Add Semgrep scanning (#81)
2023-06-07 - 746d81a - OpenTelemetry Support (#83)
2023-06-13 - 12ae2b3 - Return collection instead of enumerable and fix/re-enable task scheduler check (💥 BREAKING CHANGES) (#87)
2023-06-14 - 1134b91 - Support query properties and disallow static signals/queries (#88)
2023-06-16 - b9edda0 - Dynamic workflows, activities, signals, and queries (#89)
2023-06-26 - 97e1b08 - Remove unused log that includes injection vulnerability. (#91)
2023-06-28 - 01946ba - Dependency injection hosting extension (#92)
2023-06-28 - 98ab973 - Switch from Temporalite to Temporal CLI for local server and other changes related to server update (#94)
2023-06-28 - ebaf1af - Random with 64-bit seed (#93)

0.1.0-alpha5

26 May 13:14
fd41c34
Compare
Choose a tag to compare

⚠️ THIS IS AN ALPHA RELEASE AND COMPATIBILITY WILL NOT BE MAINTAINED

Get from NuGet and read the README

Highlights

This release significantly altered the way workflows, activities, signals, queries, etc are invoked. See breaking changes below.

Expression trees - 💥 BREAKING CHANGE

By popular demand, changed from "Ref" pattern to invoke workflows/activities/signals/queries to expression trees.

For example, if you used to:

await myClient.ExecuteWorkflowAsync(MyWorkflowClass.Ref.RunAsync, "my-arg", myOptions);

You will get a compile error. You have to change to:

await myClient.ExecuteWorkflowAsync((MyWorkflowClass wf) => wf.RunAsync("my-arg"), myOptions);

This breaking change applies to the following calls:

  • Temporalio.Client.ITemporalClient.ExecuteWorkflowAsync (extension)
  • Temporalio.Client.ITemporalClient.StartWorkflowAsync
  • Temporalio.Client.Schedules.ScheduleActionStartWorkflow.Create
  • Temporalio.Client.WorkflowHandle.QueryAsync
  • Temporalio.Client.WorkflowHandle.SignalAsync
  • Temporalio.Workflows.ChildWorkflowHandle.SignalAsync
  • Temporalio.Workflows.ExternalWorkflowHandle.SignalAsync
  • Temporalio.Workflows.Workflow.CreateContinueAsNewException
  • Temporalio.Workflows.Workflow.ExecuteActivityAsync
  • Temporalio.Workflows.Workflow.ExecuteChildWorkflowAsync
  • Temporalio.Workflows.Workflow.ExecuteLocalActivityAsync
  • Temporalio.Workflows.Workflow.StartChildWorkflowAsync

Also, all uses of Refs, ActivityRefs, and WorkflowRefs will fail compilation now because those classes no longer exist. See PR #75 for more details.

Clearer workflow/activity worker options - 💥 BREAKING CHANGE

In order to support more advanced definitions and better practices, we have changed the TemporalWorkerOptions.Activities from List<Delegate> to List<ActivityDefinition> and TemporalWorkerOptions.Workflows from List<Type> to List<WorkflowDefinition>. Users should now use AddActivity and AddWorkflow methods to add activities and workflows to worker options

For example, if you used to do this to build your worker options:

var options = new TemporalWorkerOptions("my-task-queue")
{
    Activities = { MyActivityClass.Method1, MyActivityClass.Method2 },
    Workflows = { MyWorkflowClass1, MyWorkflowClass2 },
};

You will get a compile error. You have to change to:

var options = new TemporalWorkerOptions("my-task-queue").
    AddActivity(MyActivityClass.Method1).
    AddActivity(MyActivityClass.Method2).
    AddWorkflow<MyWorkflowClass1>().
    AddWorkflow<MyWorkflowClass2>();

There are also some changes in manual definition building if those were in use. See PR #67 for more details.

DataConverter just takes direct payload/failure converter instances instead of types - 💥 BREAKING CHANGE

Previously we required that when creating a custom PayloadConverter or FailureConverter, you had to provide a type since we planned on sandboxing them. But since it's become obvious in-runtime sandboxing is unreasonable, we made this easier so now you only have to provide instances to those converters. Still, make sure all conversions are deterministic.

Classes in Temporalio moved to Temporalio.Common - 💥 BREAKING CHANGE

The following classes were moved from Temporalio to Temporalio.Common:

  • RetryPolicy
  • SearchAttributeCollection
  • SearchAttributeKey
  • WorkflowHistory

See PR #80 for more details.

Specific Changes

2023-05-17 - 2efd6f4 - Update docfx (#68)
2023-05-17 - 523bdfe - Remove sandbox strictness and make more hackable (💥 BREAKING CHANGES) (#67)
2023-05-17 - c879008 - Simple benchmarker (#69)
2023-05-23 - b40efff - Support setting metadata (i.e. headers) on connection (#73)
2023-05-23 - e85959a - Add cloud test and vercel.json (#74)
2023-05-25 - 3000d51 - Fix event unset issue on time-skipping server (#78)
2023-05-25 - bbb10ab - Use expression trees for all type-safe remote calls (💥 BREAKING CHANGES) (#75)
2023-05-25 - c8c628d - Replace Go kitchen sink worker with .NET one (#72)
2023-05-26 - fd41c34 - Move Temporalio classes to Temporalio.Common (💥 BREAKING CHANGES) (#80)

0.1.0-alpha4

01 May 16:20
53e3862
Compare
Choose a tag to compare

⚠️ THIS IS AN ALPHA RELEASE AND COMPATIBILITY WILL NOT BE MAINTAINED

Get from NuGet and read the README

Highlights

Schedules

The full schedule API is now present. If you are running the latest open source server you can use the new scheduling feature to make advanced workflow execution schedules. Temporal cloud coming soon.

💥 Breaking Changes

None

Specific Changes

2023-04-25 - bb1671e - Schedule API (#53)
2023-05-01 - 3abee68 - Add banner to README (#58)
2023-05-01 - f4b1fd1 - Update core and release version (#57)

0.1.0-alpha3

20 Apr 14:48
5d8a1a7
Compare
Choose a tag to compare

⚠️ THIS IS AN ALPHA RELEASE AND COMPATIBILITY WILL NOT BE MAINTAINED

Get from NuGet and read the README

Highlights

🎉Full Workflow Support!

With full workflow support of all Temporal workflow features, this SDK is now a full-featured SDK on par with all other
SDKs. The SDK is alpha due to immaturity, not incompleteness.

See the README for how to write workflows.

💥 Breaking Changes

  • Temporalio.Activity namespace is now Temporalio.Activities
    • This was done to align with Temporalio.Workflows plural since we need the Workflow class name not to clash with
      the namespace name
  • Temporalio.Activity.ActivityContext class is now Temporalio.Activities.ActivityExecutionContext
    • This was done to avoid clashing with System.Diagnostics.ActivityContext
  • Temporalio.Refs class is now Temporalio.Activities.ActivityRefs or Temporalio.Activities.WorkflowRefs
    • This was done so people don't have to import Temporalio just for making a Ref
  • Default constructor for Temporalio.Converters.DataConverter removed
    • It was simply the default, which is now available as Default and can be used via with to make changes since it's
      a record
  • Search attributes and memos are now in a more type safe form
  • Maybe some other minor pieces

Specific Changes

2023-02-13 - 60b2ecc - Exclude static-class check on smoke test (#21)
2023-03-01 - 43dfe89 - Renaming Activity and Workflow packages to Activities and Workflows (#26)
2023-03-07 - 2043879 - Initial workflow runtime (#29)
2023-03-10 - 838ca06 - Workflow signals, queries, and more (#31)
2023-03-20 - bed227e - Search attributes, memos, and other updates (#34)
2023-03-24 - a116fda - Workflow support for activities, children, and continue as new (#39)
2023-04-04 - cc74443 - Fixed small typo in README (#43)
2023-04-13 - b8919a4 - Misc workflow features (#40)
2023-04-19 - 3408d01 - Workflow replayer, docs, time-skipping test server, rename ActivityContext, core update, and more (#48)