diff --git a/src/ActivityHeartbeatingCancellation/README.md b/src/ActivityHeartbeatingCancellation/README.md index 53f62c6..240c516 100644 --- a/src/ActivityHeartbeatingCancellation/README.md +++ b/src/ActivityHeartbeatingCancellation/README.md @@ -16,4 +16,25 @@ Then in another terminal, run the workflow from this directory: dotnet run workflow -This will show logs in the worker window of the workflow running. \ No newline at end of file +This will show logs in the worker window of the workflow running. + +# Retry + Heartbeat Activity Example + +This example demonstrates how to combine **Retry Policies** and **Activity Heartbeats** +in Temporal's .NET SDK. + +## What This Sample Shows +- How to configure retry settings for an activity. +- How an activity can send heartbeat progress. +- How Temporal detects stalled activities via `HeartbeatTimeout`. + +This pattern is useful for: +- Batch processing +- Migration jobs +- Long-running operations +- Resumable workflows + +## How to Run + +1. Start Temporal locally (`temporalite start`). +2. Run the worker: diff --git a/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatActivity.cs b/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatActivity.cs new file mode 100644 index 0000000..afeed4e --- /dev/null +++ b/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatActivity.cs @@ -0,0 +1,19 @@ +using Temporalio.Activities; + +namespace RetryAndHeartbeat; + +public class RetryAndHeartbeatActivity +{ + [Activity] + public async Task ProcessAsync(string input) + { + for (int i = 0; i < 5; i++) + { + // Send progress + ActivityExecutionContext.Current.Heartbeat(i); + await Task.Delay(500); + } + + return $"Processed: {input}"; + } +} diff --git a/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatWorkflow.cs b/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatWorkflow.cs new file mode 100644 index 0000000..e5e35dd --- /dev/null +++ b/src/ActivityHeartbeatingCancellation/RetryAndHeartbeatWorkflow.cs @@ -0,0 +1,28 @@ +using Temporalio.Workflows; + +namespace RetryAndHeartbeat; + +[Workflow] +public class RetryAndHeartbeatWorkflow +{ + [WorkflowRun] + public async Task RunAsync(string input) + { + var options = new ActivityOptions + { + StartToCloseTimeout = TimeSpan.FromSeconds(30), + HeartbeatTimeout = TimeSpan.FromSeconds(5), + RetryPolicy = new() + { + MaximumAttempts = 3, + InitialInterval = TimeSpan.FromSeconds(1), + BackoffCoefficient = 2.0, + MaximumInterval = TimeSpan.FromSeconds(10) + } + }; + + return await Workflow.ExecuteActivityAsync( + (RetryAndHeartbeatActivity a) => a.ProcessAsync(input), + options); + } +}