Skip to content

Commit

Permalink
Added Quickstart for Javascript Jobs HTTP api
Browse files Browse the repository at this point in the history
Signed-off-by: Constantin Chirila <constantin@diagrid.io>
  • Loading branch information
Constantin Chirila authored and ConstantinChirila committed Jan 16, 2025
1 parent c32f421 commit 4d31a4e
Show file tree
Hide file tree
Showing 9 changed files with 1,872 additions and 0 deletions.
166 changes: 166 additions & 0 deletions jobs/javascript/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Dapr Jobs

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://v1-14.docs.dapr.io/developing-applications/building-blocks/jobs/) link for more information about Dapr and the Jobs API.

> **Note:** This example leverages HTTP `requests` only. If you are looking for the example using the Dapr Client SDK (recommended) [click here](../sdk/).
This quickstart includes two apps:

- `job-scheduler`, responsible for scheduling, retrieving and deleting jobs.
- `job-service`, responsible for handling the triggered jobs.

## Run the app with the 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. Install dependencies:

<!-- STEP
name: Install Node dependencies
-->

```bash
cd ./job-service
npm install
cd ..
cd ./job-scheduler
npm install
```

<!-- END_STEP -->

2. Open a new terminal window and run the multi app run template:

<!-- STEP
name: Run multi app run template
expected_stdout_lines:
- '== APP - job-scheduler == Job Scheduled: R2-D2'
- '== APP - job-scheduler == Job Scheduled: C-3PO'
- '== APP - job-service == Received job request...'
- '== APP - job-service == Starting droid: R2-D2'
- '== APP - job-service == Executing maintenance job: Oil Change'
- '== APP - job-service == Received job request...'
- '== APP - job-service == Starting droid: C-3PO'
- '== APP - job-service == Executing maintenance job: Limb Calibration'
expected_stderr_lines:
output_match_mode: substring
match_order: none
background: false
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 == Job Scheduled: R2-D2
== APP - job-scheduler == Job details: {"name":"R2-D2", "dueTime":"15s", "data":{"value":{"value":"R2-D2:Oil Change"}}}
== APP - job-scheduler == Job Scheduled: C-3PO
== APP - job-scheduler == Job details: {"name":"C-3PO", "dueTime":"20s", "data":{"value":{"value":"C-3PO:Limb Calibration"}}}
== APP - job-service == Received job request...
== APP - job-service == Starting droid: R2-D2
== APP - job-service == Executing maintenance job: Oil Change
```

After 20 seconds, the terminal output should present the `C-3PO` job being processed:

```text
== APP - job-service == Received job request...
== APP - job-service == Starting droid: C-3PO
== APP - job-service == Executing maintenance job: Limb Calibration
```

<!-- END_STEP -->

## Run the Jobs APIs individually

### Schedule Jobs

1. Open a terminal and run the `job-service` app:

```bash
dapr run --app-id job-service --app-port 6200 --dapr-http-port 6280 -- go run .
```

2. On a new terminal window, schedule the `R2-D2` Job using the Jobs API.

```bash
curl -X POST \
http://localhost:6280/v1.0-alpha1/jobs/R2D2 \
-H "Content-Type: application/json" \
-d '{
"data": {
"value": "R2-D2:Oil Change"
},
"dueTime": "2s"
}'
```

Back at the `job-service` app 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:6280/v1.0-alpha1/jobs/c-3po \
-H "Content-Type: application/json" \
-d '{
"data": {
"value": "C-3PO:Limb Calibration"
},
"dueTime": "30s"
}'
```

### 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:6280/v1.0-alpha1/jobs/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.StringValue", "expression":"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:6280/v1.0-alpha1/jobs/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:6280/v1.0-alpha1/jobs/c-3po -H "Content-Type: application/json"
```

Back at the `job-service` app terminal window, the output should be:

```text
ERRO[0249] Error getting job c-3po due to: rpc error: code = Unknown desc = job not found: app||default||job-service||c-3po instance=diagrid.local scope=dapr.api type=log ver=1.14.0-rc.2
```
13 changes: 13 additions & 0 deletions jobs/javascript/http/dapr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: 1
apps:
- appDirPath: ./job-service/
appID: job-service
appPort: 6200
daprHTTPPort: 6280
schedulerHostAddress: localhost
command: ["npm", "run", "start"]
- appDirPath: ./job-scheduler/
appID: job-scheduler
appPort: 6300
daprHTTPPort: 6380
command: ["npm", "run", "start"]
78 changes: 78 additions & 0 deletions jobs/javascript/http/job-scheduler/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Job request bodies
const c3poJobBody = {
data: {
value: "C-3PO:Limb Calibration",
},
dueTime: "20s",
};

const r2d2JobBody = {
data: {
value: "R2-D2:Oil Change",
},
dueTime: "15s",
};
const daprHost = process.env.DAPR_HOST || "http://localhost";
const schedulerDaprHttpPort = "6280";

async function main() {
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Wait for job-service to start
await sleep(5000);

try {
// Schedule R2-D2 job
await scheduleJob("R2-D2", r2d2JobBody);
await sleep(5000);
// Get R2-D2 job details
await getJobDetails("R2-D2");

// Schedule C-3PO job
await scheduleJob("C-3PO", c3poJobBody);
await sleep(5000);
// Get C-3PO job details
await getJobDetails("C-3PO");

await sleep(30000);
} catch (error) {
if (error.name === "AbortError") {
console.error("Request timed out");
} else {
console.error("Error:", error.message);
}
process.exit(1);
}
}

async function scheduleJob(jobName, jobBody) {
const reqURL = `${daprHost}:${schedulerDaprHttpPort}/v1.0-alpha1/jobs/${jobName}`;
const response = await fetch(reqURL, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(jobBody),
});

if (response.status !== 204) {
throw new Error(
`Failed to register job event handler. Status code: ${response.status}`
);
}

console.log("Job Scheduled:", jobName);
}

async function getJobDetails(jobName) {
const reqURL = `${daprHost}:${schedulerDaprHttpPort}/v1.0-alpha1/jobs/${jobName}`;
const response = await fetch(reqURL, {
method: "GET",
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const jobDetails = await response.text();
console.log("Job details:", jobDetails);
}

main().catch(console.error);
Loading

0 comments on commit 4d31a4e

Please sign in to comment.