Merge pull request #1176 from alicejgibbons/release-1.15

Re-merge 1.15 release branch into master
This commit is contained in:
Alice Gibbons 2025-03-04 15:32:46 -06:00 committed by GitHub
commit 55d7dc2a37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 599 additions and 24 deletions

View File

@ -1,5 +1,5 @@
DAPR_CLI_VERSION: 1.15.0
DAPR_RUNTIME_VERSION: 1.15.0
DAPR_RUNTIME_VERSION: 1.15.2
DAPR_INSTALL_URL: https://raw.githubusercontent.com/dapr/cli/v${DAPR_CLI_VERSION}/install/
DAPR_DEFAULT_IMAGE_REGISTRY: ghcr

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages HTTP `requests` only. If you are looking for the example using the Dapr Client SDK (recommended) [click here](../sdk/).
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template file](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) and Dapr CLI with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Integrate with popular LLM models by using one of the other [supported conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Integrate with popular LLM models by using one of the other [supported conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
Open a new terminal window and run the multi app run template:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages the Dapr SDK. If you are looking for the example using the HTTP API [click here](../http/).
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template file](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) and Dapr CLI with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Integrate with popular LLM models by using one of the other [supported conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Integrate with popular LLM models by using one of the other [supported conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
Open a new terminal window and run the multi app run template:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages HTTP `requests` only. If you are looking for the example using the Dapr Client SDK (recommended) [click here](../sdk/).
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
Open a new terminal window and run the multi app run template:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages the Dapr SDK. If you are looking for the example using the HTTP API [click here](../http/).
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
Open a new terminal window and run the multi app run template:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages HTTP `requests` only.
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
1. Install dependencies:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
> **Note:** This example leverages HTTP `requests` only.
@ -14,7 +14,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
1. Install dependencies:

View File

@ -2,7 +2,7 @@
In this quickstart, you'll send an input to a mock Large Language Model (LLM) using Dapr's Conversation API. This API is responsible for providing one consistent API entry point to talk to underlying LLM providers.
Visit [this](https://v1-15.docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/conversation/conversation-overview/) link for more information about Dapr and the Conversation API.
This quickstart includes one app:
@ -12,7 +12,7 @@ This quickstart includes one app:
This section shows how to run the application using the [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`.
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://v1-15.docs.dapr.io/reference/components-reference/supported-conversation/).
This example uses the default LLM Component provided by Dapr which simply echoes the input provided, for testing purposes. Here are other [supported Conversation components](https://docs.dapr.io/reference/components-reference/supported-conversation/).
1. Install dependencies:

View File

@ -57,7 +57,7 @@ expected_stdout_lines:
expected_stderr_lines:
output_match_mode: substring
match_order: none
background: false
background: true
sleep: 60
timeout_seconds: 120
-->
@ -95,6 +95,18 @@ After 20 seconds, the terminal output should present the `C-3PO` job being proce
<!-- END_STEP -->
3. Stop and clean up application processes.
<!-- STEP
name: Stop multi-app run
-->
```bash
dapr stop -f .
```
<!-- END_STEP -->
## Run apps individually
### Schedule Jobs

View File

@ -19,7 +19,6 @@ var r2d2JobBody = new
var daprHost = Environment.GetEnvironmentVariable("DAPR_HOST") ?? "http://localhost";
var jobServiceDaprHttpPort = "6280";
var httpClient = new HttpClient();
await Task.Delay(5000); // Wait for job-service to start
@ -65,7 +64,6 @@ async Task ScheduleJob(string jobName, object jobBody)
async Task GetJobDetails(string jobName)
{
var reqURL = $"{daprHost}:{jobServiceDaprHttpPort}/v1.0-alpha1/jobs/{jobName}";
var response = await httpClient.GetAsync(reqURL);
if (!response.IsSuccessStatusCode)

197
jobs/csharp/sdk/README.md Normal file
View File

@ -0,0 +1,197 @@
# Dapr Jobs API (SDK)
In this quickstart, you'll schedule, get, and delete a job using Dapr's Job API. This API is responsible for scheduling and running jobs at a specific time or interval.
Visit [this](https://docs.dapr.io/developing-applications/building-blocks/jobs/) link for more information about Dapr and the Jobs API.
> **Note:** This example leverages the Dotnet SDK. If you are looking for the example using only HTTP requests, [click here](../http/).
This quickstart includes two apps:
- Jobs Scheduler, responsible for scheduling, retrieving and deleting jobs.
- Jobs Service, responsible for handling the triggered jobs.
## Run all apps with multi-app run template file
This section shows how to run both applications at once using [multi-app run template files](https://docs.dapr.io/developing-applications/local-development/multi-app-dapr-run/multi-app-overview/) with `dapr run -f .`. This enables to you test the interactions between multiple applications and will `schedule`, `run`, `get`, and `delete` jobs within a single process.
1. Build the apps:
<!-- STEP
name: Build dependencies for job-service
sleep: 1
-->
```bash
cd ./job-service
dotnet build
```
<!-- END_STEP -->
<!-- STEP
name: Build dependencies for job-scheduler
sleep: 1
-->
```bash
cd ./job-scheduler
dotnet build
```
<!-- END_STEP -->
2. Run the multi app run template:
<!-- STEP
name: Run multi app run template
expected_stdout_lines:
- '== APP - job-service-sdk == Job Scheduled: R2-D2'
- '== APP - job-service-sdk == Job Scheduled: C-3PO'
- '== APP - job-service-sdk == Starting droid: R2-D2'
- '== APP - job-service-sdk == Executing maintenance job: Oil Change'
- '== APP - job-service-sdk == Starting droid: C-3PO'
- '== APP - job-service-sdk == Executing maintenance job: Limb Calibration'
expected_stderr_lines:
output_match_mode: substring
match_order: none
background: true
sleep: 60
timeout_seconds: 120
-->
```bash
dapr run -f .
```
The terminal console output should look similar to this, where:
- The `R2-D2` job is being scheduled.
- The `R2-D2` job is being retrieved.
- The `C-3PO` job is being scheduled.
- The `C-3PO` job is being retrieved.
- The `R2-D2` job is being executed after 15 seconds.
- The `C-3PO` job is being executed after 20 seconds.
```text
== APP - job-scheduler-sdk == Scheduling job...
== APP - job-service-sdk == Job Scheduled: R2-D2
== APP - job-scheduler-sdk == Job scheduled: {"name":"R2-D2","job":"Oil Change","dueTime":15}
== APP - job-scheduler-sdk == Getting job: R2-D2
== APP - job-service-sdk == Getting job...
== APP - job-scheduler-sdk == Job details: {"schedule":"@every 15s","repeatCount":1,"dueTime":null,"ttl":null,"payload":"ChtkYXByLmlvL3NjaGVkdWxlL2pvYnBheWxvYWQSJXsiZHJvaWQiOiJSMi1EMiIsInRhc2siOiJPaWwgQ2hhbmdlIn0="}
== APP - job-scheduler-sdk == Scheduling job...
== APP - job-service-sdk == Job Scheduled: C-3PO
== APP - job-scheduler-sdk == Job scheduled: {"name":"C-3PO","job":"Limb Calibration","dueTime":20}
== APP - job-scheduler-sdk == Getting job: C-3PO
== APP - job-service-sdk == Getting job...
== APP - job-scheduler-sdk == Job details: {"schedule":"@every 20s","repeatCount":1,"dueTime":null,"ttl":null,"payload":"ChtkYXByLmlvL3NjaGVkdWxlL2pvYnBheWxvYWQSK3siZHJvaWQiOiJDLTNQTyIsInRhc2siOiJMaW1iIENhbGlicmF0aW9uIn0="}
== APP - job-service-sdk == Handling job...
== APP - job-service-sdk == Starting droid: R2-D2
== APP - job-service-sdk == Executing maintenance job: Oil Change
```
After 20 seconds, the terminal output should present the `C-3PO` job being processed:
```text
== APP - job-service-sdk == Handling job...
== APP - job-service-sdk == Starting droid: C-3PO
== APP - job-service-sdk == Executing maintenance job: Limb Calibration
```
<!-- END_STEP -->
3. Stop and clean up application processes.
<!-- STEP
name: Stop multi-app run
-->
```bash
dapr stop -f .
```
<!-- END_STEP -->
## Run apps individually
### Schedule Jobs
1. Open a terminal and run the `job-service` app. Build the dependencies if you haven't already.
```bash
cd ./job-service
dotnet build
```
```bash
dapr run --app-id job-service-sdk --app-port 6200 --dapr-http-port 6280 -- dotnet run
```
2. In a new terminal window, schedule the `R2-D2` Job using the Jobs API.
```bash
curl -X POST \
http://localhost:6200/scheduleJob \
-H "Content-Type: application/json" \
-d '{
"name": "R2-D2",
"job": "Oil Change",
"dueTime": 2
}'
```
In the `job-service` terminal window, the output should be:
```text
== APP - job-app == Received job request...
== APP - job-app == Starting droid: R2-D2
== APP - job-app == Executing maintenance job: Oil Change
```
3. On the same terminal window, schedule the `C-3PO` Job using the Jobs API.
```bash
curl -X POST \
http://localhost:6200/scheduleJob \
-H "Content-Type: application/json" \
-d '{
"name": "C-3PO",
"job": "Limb Calibration",
"dueTime": 30
}'
```
### Get a scheduled job
1. On the same terminal window, run the command below to get the recently scheduled `C-3PO` job.
```bash
curl -X GET http://localhost:6200/getJob/C-3PO -H "Content-Type: application/json"
```
You should see the following:
```text
{"name":"c-3po", "dueTime":"30s", "data":{"@type":"type.googleapis.com/google.protobuf.Value", "value":{"Value":"C-3PO:Limb Calibration"}}}
```
### Delete a scheduled job
1. On the same terminal window, run the command below to deleted the recently scheduled `C-3PO` job.
```bash
curl -X DELETE http://localhost:6200/deleteJob/C-3PO -H "Content-Type: application/json"
```
2. Run the command below to attempt to retrieve the deleted job:
```bash
curl -X GET http://localhost:6200/getJob/C-3PO -H "Content-Type: application/json"
```
In the `job-service` terminal window, the output should be similar to the following:
```text
ERRO[0157] Error getting job C-3PO due to: rpc error: code = NotFound desc = job not found: C-3PO instance=local scope=dapr.api type=log ver=1.15.0
```

16
jobs/csharp/sdk/dapr.yaml Normal file
View File

@ -0,0 +1,16 @@
version: 1
apps:
- appDirPath: ./job-service/
appID: job-service-sdk
appPort: 6200
daprHTTPPort: 6280
command: ["dotnet", "run"]
appLogDestination: console
daprdLogDestination: console
- appDirPath: ./job-scheduler/
appID: job-scheduler-sdk
appPort: 6300
daprHTTPPort: 6380
command: ["dotnet", "run"]
appLogDestination: console
daprdLogDestination: console

View File

@ -0,0 +1,101 @@
#pragma warning disable CS0618 // Type or member is obsolete
using System.Text.Json.Serialization;
using Dapr.Client;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
await Task.Delay(5000); // Allow time for the job-service-sdk to start
// Instantiate an HTTP client for invoking the job-service-sdk application
var httpClient = DaprClient.CreateInvokeHttpClient(appId: "job-service-sdk");
// Job details
var r2d2Job = new DroidJob
{
Name = "R2-D2",
Job = "Oil Change",
DueTime = 15
};
var c3poJob = new DroidJob
{
Name = "C-3PO",
Job = "Limb Calibration",
DueTime = 20
};
try
{
// Schedule R2-D2 job
await ScheduleJob(r2d2Job);
await Task.Delay(5000);
// Get R2-D2 job details
await GetJobDetails(r2d2Job);
// Schedule C-3PO job
await ScheduleJob(c3poJob);
await Task.Delay(5000);
// Get C-3PO job details
await GetJobDetails(c3poJob);
await Task.Delay(30000); // Allow time for jobs to complete
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error: {ex.Message}");
Environment.Exit(1);
}
async Task ScheduleJob(DroidJob job)
{
Console.WriteLine($"Scheduling job...");
try
{
var response = await httpClient.PostAsJsonAsync("/scheduleJob", job);
var result = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine($"Job scheduled: {result}");
}
catch (Exception e)
{
Console.WriteLine($"Error scheduling job: " + e);
}
}
async Task GetJobDetails(DroidJob job)
{
Console.WriteLine($"Getting job: " + job.Name);
try
{
var response = await httpClient.GetAsync($"/getJob/{job.Name}");
var jobDetails = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine($"Job details: {jobDetails}");
}
catch (Exception e)
{
Console.WriteLine($"Error getting job: " + e);
}
}
await app.RunAsync();
public class DroidJob
{
[JsonPropertyName("name")]
public string? Name { get; set; }
[JsonPropertyName("job")]
public string? Job { get; set; }
[JsonPropertyName("dueTime")]
public int DueTime { get; set; }
}
#pragma warning restore CS0618 // Type or member is obsolete

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>jobs_scheduler</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapr.Client" Version="1.15.0-rc07" />
<PackageReference Include="Dapr.Jobs" Version="1.15.0-rc07" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,163 @@
#pragma warning disable CS0618 // Type or member is obsolete
using Dapr.Jobs;
using Dapr.Jobs.Extensions;
using Dapr.Jobs.Models;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
// The jobs host is a background service that connects to the sidecar over gRPC
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDaprJobsClient();
var app = builder.Build();
var appPort = Environment.GetEnvironmentVariable("APP_PORT") ?? "6200";
var jobsClient = app.Services.GetRequiredService<DaprJobsClient>();
app.MapPost("/scheduleJob", async (HttpContext context) =>
{
var droidJob = await JsonSerializer.DeserializeAsync<DroidJob>(context.Request.Body);
if (droidJob?.Name is null || droidJob?.Job is null)
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Job must contain a name and a task " + context.Request.Body);
return;
}
try
{
var jobData = new JobData
{
Droid = droidJob.Name,
Task = droidJob.Job
};
await jobsClient.ScheduleJobWithPayloadAsync(droidJob.Name, DaprJobSchedule.FromDuration(TimeSpan.FromSeconds(droidJob.DueTime)), payload: jobData, repeats: 1); //Schedule cron job that repeats once
Console.WriteLine($"Job Scheduled: {droidJob.Name}");
context.Response.StatusCode = 200;
await context.Response.WriteAsJsonAsync(droidJob);
}
catch (Exception e)
{
Console.WriteLine($"Error scheduling job: " + e);
}
return;
});
app.MapGet("/getJob/{name}", async (HttpContext context) =>
{
var jobName = context.Request.RouteValues["name"]?.ToString();
Console.WriteLine($"Getting job...");
if (string.IsNullOrEmpty(jobName))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Job name required");
return;
}
try
{
var jobDetails = await jobsClient.GetJobAsync(jobName);
context.Response.StatusCode = 200;
await context.Response.WriteAsJsonAsync(jobDetails);
}
catch (Exception e)
{
Console.WriteLine($"Error getting job: " + e);
context.Response.StatusCode = 400;
await context.Response.WriteAsync($"Error getting job");
}
return;
});
app.MapDelete("/deleteJob/{name}", async (HttpContext context) =>
{
var jobName = context.Request.RouteValues["name"]?.ToString();
Console.WriteLine($"Deleting job: " + jobName);
if (string.IsNullOrEmpty(jobName))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Job name required");
return;
}
try
{
await jobsClient.DeleteJobAsync(jobName);
Console.WriteLine($"Job deleted: {jobName}");
context.Response.StatusCode = 200;
await context.Response.WriteAsync("Job deleted");
}
catch (Exception e)
{
Console.WriteLine($"Error deleting job: " + e);
context.Response.StatusCode = 400;
await context.Response.WriteAsync($"Error deleting job");
}
return;
});
// Job handler route to capture incoming jobs
app.MapDaprScheduledJobHandler((string jobName, ReadOnlyMemory<byte> jobPayload) =>
{
Console.WriteLine("Handling job...");
var deserializedPayload = Encoding.UTF8.GetString(jobPayload.Span);
try
{
if (deserializedPayload is null)
{
throw new Exception("Payload is null");
}
var jobData = JsonSerializer.Deserialize<JobData>(deserializedPayload);
if (jobData?.Droid is null || jobData?.Task is null)
{
throw new Exception("Invalid format of job data.");
}
// Handling Droid Job from decoded value
Console.WriteLine($"Starting droid: {jobData.Droid}");
Console.WriteLine($"Executing maintenance job: {jobData.Task}");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to handle job {jobName}");
Console.Error.WriteLine($"Error handling job: {ex.Message}");
}
return Task.CompletedTask;
});
app.UseRouting();
app.Run($"http://*:{appPort}");
// Classes for request and response models
public class JobData
{
[JsonPropertyName("droid")]
public string? Droid { get; set; }
[JsonPropertyName("task")]
public string? Task { get; set; }
}
public class DroidJob
{
[JsonPropertyName("name")]
public string? Name { get; set; }
[JsonPropertyName("job")]
public string? Job { get; set; }
[JsonPropertyName("dueTime")]
public int DueTime { get; set; }
}
#pragma warning restore CS0618 // Type or member is obsolete

View File

@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5305",
"sslPort": 44346
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5023",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7073;http://localhost:5023",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapr.Jobs" Version="1.15.0-rc07" />
</ItemGroup>
</Project>

2
jobs/csharp/sdk/makefile Normal file
View File

@ -0,0 +1,2 @@
include ../../../docker.mk
include ../../../validate.mk

View File

@ -240,4 +240,4 @@ When you ran `dapr run -f .`:
8. The `NotifyActivity` workflow activity sends a notification saying that order `571a6e25` has completed.
9. The workflow terminates as completed and the OrderResult is set to processed.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://v1-15.docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.

View File

@ -95,4 +95,4 @@ When you ran the above comands:
8. The `NotifyActivity` workflow activity sends a notification saying that order `b4cb2687-1af0-4f8d-9659-eb6389c07ade` has completed.
9. The workflow terminates as completed and the OrderResult is set to processed.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://v1-15.docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.

View File

@ -122,4 +122,5 @@ When you ran `dapr run -f .`:
8. The `NotifyActivity` workflow activity sends a notification saying that order `d1bf548b-c854-44af-978e-90c61ed88e3c` has completed.
9. The workflow terminates as completed and the orderResult is set to processed.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://v1-15.docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `RequestApprovalActivity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.

View File

@ -174,4 +174,4 @@ When you ran `dapr run -f .`
8. The `notifyActivity` workflow activity sends a notification saying that order `f5087775-779c-4e73-ac77-08edfcb375f4` has completed and processed.
9. The workflow terminates as completed and processed.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `requestApprovalActivity` activity nor wait for an approval event. The dapr.yaml multi-app run file starts a console application and can't accept incoming events easily. The dapr-AppWithDaprServer.yaml and dapr-AppWithExpressServer.yaml files start a service that can accept incoming events. Use the [raise event API](https://v1-15.docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client in the server apps to send an event to the workflow.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `requestApprovalActivity` activity nor wait for an approval event. The dapr.yaml multi-app run file starts a console application and can't accept incoming events easily. The dapr-AppWithDaprServer.yaml and dapr-AppWithExpressServer.yaml files start a service that can accept incoming events. Use the [raise event API](https://docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client in the server apps to send an event to the workflow.

View File

@ -124,4 +124,4 @@ When you ran `dapr run -f .`
8. The `notify_activity` workflow activity sends a notification saying that order `fc8a507e4a2246d2917d3ad4e3111240` has completed.
9. The workflow terminates as completed and the OrderResult is set to processed.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `request_approval_activity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://v1-15.docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.
> **Note:** This quickstart uses an OrderPayload of one car with a total cost of $5000. Since the total order cost is not over 5000, the workflow will not call the `request_approval_activity` activity nor wait for an approval event. Since the quickstart is a console application, it can't accept incoming events easily. If you want to test this scenario, convert the console app to a service and use the [raise event API](https://docs.dapr.io/reference/api/workflow_api/#raise-event-request) via HTTP/gRPC or via the Dapr Workflow client to send an event to the workflow instance.

View File

@ -1,2 +1,2 @@
dapr-ext-workflow>=1.15.0
dapr>=1.15.0
dapr>=1.15.0