Skip to main content
Temporal .NET SDK

About this example

Free previewTemporal 101.NET
  1. About this example
  2. Code walkthrough

During the previous exercise, you executed a Workflow that included two Activities, both of which made a call to a microservice that provided a customized message in Spanish. That exercise demonstrates many of the key concepts you've learned during this course. Although you now have first-hand experience with developing and running applications on the Temporal Platform, you'll gain a deeper understanding of how Temporal works by looking at what happens during Workflow Execution.

Actors in the scenario

Let's begin by identifying the actors in this scenario, which will help to reiterate some important concepts.

First, the example includes a Worker, which executes the Workflow and Activity code, and uses a Client to communicate with the Temporal Service.

Next, the Temporal Service orchestrates the execution of that code by coordinating with the Worker, using a shared task queue.

Finally, the program that starts the Workflow, which will be referred to as a Client application because it requests Workflow Execution as well as the result from the Temporal Service, uses a Client to do this.

Diagram showing actors in Workflow execution scenario

Workers and tasks

The assignment of work is indirect. The Temporal Service does not assign tasks to a Worker (in fact, the Temporal Service does not maintain a list of Workers).

Instead, the Workers continually poll the Temporal Service's Task Queue and accept tasks when they have spare capacity to process them. There are several benefits to this approach, but one of them is that tasks will just sit in the queue if there aren't enough Workers, which means that you can increase throughput and scalability by adding more Workers.

Diagram showing Workers polling tasks from the Task Queue

As you learned earlier, Temporal applications in production will typically have multiple Workers; however, this example uses a single Worker for the sake of simplicity.

Commands

Another thing that will help you understand Temporal is the role of Commands. When the Worker encounters certain API calls during a Workflow Execution, such as a call to the Workflow's ExecuteActivityAsync function, it sends a Command to the Temporal Service. The Service acts on these Commands, for example, by creating an Activity Task, but also stores them in case of failure.

For example, if the Worker crashes, the Temporal Service uses this information to recreate the state of the Workflow to what it was immediately before the crash and then resumes progress from that point. This allows you, as a developer, to code as if this type of failure wasn't even a possibility.

Diagram showing Worker sending Commands to the Temporal Service

Activity Definitions

The application defines two Activities: GetSpanishGreeting and GetSpanishFarewell.

TranslateActivities.cs
namespace TemporalioFarewell.Workflow;

using Temporalio.Activities;

public class TranslateActivities
{
private readonly HttpClient client;

public TranslateActivities(HttpClient client) => this.client = client;

[Activity]
public async Task<string> GetSpanishGreetingAsync(string name)
{
var encodedName = Uri.EscapeDataString(name);
var response = await client.GetAsync($"http://localhost:5125/get-spanish-greeting?name={encodedName}");
return await response.Content.ReadAsStringAsync();
}

[Activity]
public async Task<string> GetSpanishFarewellAsync(string name)
{
var encodedName = Uri.EscapeDataString(name);
var response = await client.GetAsync($"http://localhost:5125/get-spanish-farewell?name={encodedName}");
return await response.Content.ReadAsStringAsync();
}
}

Workflow Definition

The Workflow Definition executes those two Activities and returns a string created from their output.

GreetingWorkflow.cs
namespace TemporalioFarewell.Workflow;

using Temporalio.Workflows;

[Workflow]
public class GreetingWorkflow
{
[WorkflowRun]
public async Task<string> RunAsync(string name)
{
// Spanish greeting
var greeting = await Workflow.ExecuteActivityAsync(
(TranslateActivities act) => act.GetSpanishGreetingAsync(name),
new() { ScheduleToCloseTimeout = TimeSpan.FromMinutes(3) });
// Spanish farewell
var farewell = await Workflow.ExecuteActivityAsync(
(TranslateActivities act) => act.GetSpanishFarewellAsync(name),
new() { ScheduleToCloseTimeout = TimeSpan.FromMinutes(3) });
// Greeting and farewell
return $"{greeting}\n{farewell}";
}
}

Worker initialization

Here's the Worker initialization code, which registers the Workflow and Activity Definitions.

Program.cs
// This file is designated to run the Worker
using Temporalio.Client;
using Temporalio.Worker;
using TemporalioFarewell.Workflow;

// Create a client to localhost on "default" namespace
var client = await TemporalClient.ConnectAsync(new("localhost:7233"));

// Cancellation token to shutdown worker on ctrl+c
using var tokenSource = new CancellationTokenSource();
Console.CancelKeyPress += (_, eventArgs) =>
{
tokenSource.Cancel();
eventArgs.Cancel = true;
};

using var httpClient = new HttpClient();
var activities = new TranslateActivities(httpClient);

// Create worker
using var worker = new TemporalWorker(
client,
new TemporalWorkerOptions("farewell-workflow").
AddAllActivities(activities).
AddWorkflow<GreetingWorkflow>());

// Run worker until cancelled
Console.WriteLine("Running worker");
try
{
await worker.ExecuteAsync(tokenSource.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Worker cancelled");
}

Summary

In this course, you saw how the parts of a Temporal Application - a Worker, the Temporal Service, and the Client Application - work together during a Workflow Execution.

In the next video, you will see how all the parts work together through a code walkthrough.

Get notified when we launch new educational content

New courses, tutorials, and learning resources - straight to your inbox.

Subscribe
Feedback