Skip to content

Commit

Permalink
Add timer sample (#57)
Browse files Browse the repository at this point in the history
Co-authored-by: Chad Retz <[email protected]>
  • Loading branch information
lorensr and cretz authored Apr 2, 2024
1 parent 49c0c06 commit 61133fb
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Prerequisites:
* [Polling](src/Polling) - Recommended implementation of an activity that needs to periodically poll an external resource waiting its successful completion.
* [Saga](src/Saga) - Demonstrates how to implement a saga pattern.
* [Schedules](src/Schedules) - How to schedule workflows to be run at specific times in the future.
* [Timer](src/Timer) - Use a timer to implement a monthly subscription; handle workflow cancellation.
* [WorkerSpecificTaskQueues](src/WorkerSpecificTaskQueues) - Use a unique task queue per Worker to have certain Activities only run on that specific Worker.
* [WorkerVersioning](src/WorkerVersioning) - How to use the Worker Versioning feature to more easily deploy changes to Workflow & other code.
* [WorkflowUpdate](src/WorkflowUpdate) - How to use the Workflow Update feature while blocking in update method for concurrent updates.
Expand Down
9 changes: 9 additions & 0 deletions src/Timer/MyActivities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TemporalioSamples.Timer;

using Temporalio.Activities;

public class MyActivities
{
[Activity]
public static string Charge(string userId) => "charge successful";
}
63 changes: 63 additions & 0 deletions src/Timer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Microsoft.Extensions.Logging;
using Temporalio.Client;
using Temporalio.Worker;
using TemporalioSamples.Timer;

// Create a client to localhost on default namespace
var client = await TemporalClient.ConnectAsync(new("localhost:7233")
{
LoggerFactory = LoggerFactory.Create(builder =>
builder.
AddSimpleConsole(options => options.TimestampFormat = "[HH:mm:ss] ").
SetMinimumLevel(LogLevel.Information)),
});

async Task RunWorkerAsync()
{
// Cancellation token cancelled on ctrl+c
using var tokenSource = new CancellationTokenSource();
Console.CancelKeyPress += (_, eventArgs) =>
{
tokenSource.Cancel();
eventArgs.Cancel = true;
};

// Create an activity instance with some state
var activities = new MyActivities();

// Run worker until cancelled
Console.WriteLine("Running worker");
using var worker = new TemporalWorker(
client,
new TemporalWorkerOptions(taskQueue: "timer-sample").
AddActivity(MyActivities.Charge).
AddWorkflow<Subscription>());
try
{
await worker.ExecuteAsync(tokenSource.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Worker cancelled");
}
}

async Task ExecuteWorkflowAsync()
{
Console.WriteLine("Executing workflow");
await client.ExecuteWorkflowAsync(
(Subscription wf) => wf.RunAsync("user-id-123"),
new(id: "timer-workflow-id", taskQueue: "timer-sample"));
}

switch (args.ElementAtOrDefault(0))
{
case "worker":
await RunWorkerAsync();
break;
case "workflow":
await ExecuteWorkflowAsync();
break;
default:
throw new ArgumentException("Must pass 'worker' or 'workflow' as the single argument");
}
14 changes: 14 additions & 0 deletions src/Timer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Timer

Use a timer (`Workflow.DelayAsync`) to implement a monthly subscription. Also, handle workflow cancellation.

To run, first see [README.md](../../README.md) for prerequisites. Then, run the following from this directory
in a separate terminal to start the worker:

dotnet run worker

Then in another terminal, run the workflow from this directory:

dotnet run workflow

The worker terminal will show logs from running the workflow.
32 changes: 32 additions & 0 deletions src/Timer/Subscription.workflow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace TemporalioSamples.Timer;

using Microsoft.Extensions.Logging;
using Temporalio.Workflows;

[Workflow]
public class Subscription
{
[WorkflowRun]
public async Task RunAsync(string userId)
{
try
{
while (true)
{
await Workflow.DelayAsync(TimeSpan.FromDays(30));

var result = await Workflow.ExecuteActivityAsync(
() => MyActivities.Charge(userId),
new() { StartToCloseTimeout = TimeSpan.FromMinutes(5) });
Workflow.Logger.LogInformation("Activity result: {Result}", result);
}
}
catch (Exception e) when (TemporalException.IsCanceledException(e))
{
Workflow.Logger.LogInformation("Workflow cancelled, cleaning up...");
// Handle any cleanup here
// Re-throw to close the workflow as Cancelled. Otherwise, it will be closed as Completed.
throw;
}
}
}
7 changes: 7 additions & 0 deletions src/Timer/TemporalioSamples.Timer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>

</Project>

0 comments on commit 61133fb

Please sign in to comment.