mirror of https://github.com/dapr/quickstarts.git
				
				
				
			Merge pull request #1166 from alicejgibbons/release-1.15
Dotnet Jobs SDK qs
This commit is contained in:
		
						commit
						e87a963cec
					
				| 
						 | 
				
			
			@ -0,0 +1,185 @@
 | 
			
		|||
# 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 -->
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
#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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
await Task.Delay(50);
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
{
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Information",
 | 
			
		||||
      "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
{
 | 
			
		||||
  "Logging": {
 | 
			
		||||
    "LogLevel": {
 | 
			
		||||
      "Default": "Information",
 | 
			
		||||
      "Microsoft.AspNetCore": "Warning"
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  "AllowedHosts": "*"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
include ../../../docker.mk
 | 
			
		||||
include ../../../validate.mk
 | 
			
		||||
		Loading…
	
		Reference in New Issue