Skip to content

Commit 42d1733

Browse files
authored
feat: Batch notifications (#3772)
* feat: add batch_notification sample * refactor: update package.json and add .test.js postfix to test files
1 parent 197bfa7 commit 42d1733

File tree

6 files changed

+196
-2
lines changed

6 files changed

+196
-2
lines changed

.github/workflows/batch.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ jobs:
4949
id-token: 'write'
5050
if: github.event_name == 'schedule' && always() # always() submits logs even if tests fail
5151
uses: ./.github/workflows/flakybot.yaml
52-
needs: [test]
52+
needs: [test]
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Copyright 2021 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
'use strict';
18+
19+
async function main() {
20+
// [START batch_notifications]
21+
// Imports the Batch library
22+
const batchLib = require('@google-cloud/batch');
23+
const batch = batchLib.protos.google.cloud.batch.v1;
24+
25+
// Instantiates a client
26+
const batchClient = new batchLib.v1.BatchServiceClient();
27+
28+
/**
29+
* TODO(developer): Update these variables before running the sample.
30+
*/
31+
const PROJECT_ID = await batchClient.getProjectId();
32+
// Name of the region you want to use to run the job. Regions that are
33+
// available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
34+
const REGION = 'europe-central2';
35+
// The name of the job that will be created.
36+
// It needs to be unique for each project and region pair.
37+
const JOB_NAME = 'job-name-batch-notifications';
38+
// The Pub/Sub topic ID to send the notifications to.
39+
const TOPIC_ID = 'topic-id';
40+
41+
// Define what will be done as part of the job.
42+
const task = new batch.TaskSpec();
43+
const runnable = new batch.Runnable();
44+
runnable.script = new batch.Runnable.Script();
45+
runnable.script.commands = [
46+
'-c',
47+
'echo Hello world! This is task ${BATCH_TASK_INDEX}.',
48+
];
49+
task.runnables = [runnable];
50+
task.maxRetryCount = 2;
51+
task.maxRunDuration = {seconds: 3600};
52+
53+
// Tasks are grouped inside a job using TaskGroups.
54+
const group = new batch.TaskGroup();
55+
group.taskCount = 3;
56+
group.taskSpec = task;
57+
58+
const job = new batch.Job();
59+
job.name = JOB_NAME;
60+
job.taskGroups = [group];
61+
job.labels = {env: 'testing', type: 'script'};
62+
// We use Cloud Logging as it's an option available out of the box
63+
job.logsPolicy = new batch.LogsPolicy();
64+
job.logsPolicy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING;
65+
66+
// Create batch notification when job state changed
67+
const notification1 = new batch.JobNotification();
68+
notification1.pubsubTopic = `projects/${PROJECT_ID}/topics/${TOPIC_ID}`;
69+
notification1.message = {
70+
type: 'JOB_STATE_CHANGED',
71+
};
72+
73+
// Create batch notification when task state changed
74+
const notification2 = new batch.JobNotification();
75+
notification2.pubsubTopic = `projects/${PROJECT_ID}/topics/${TOPIC_ID}`;
76+
notification2.message = {
77+
type: 'TASK_STATE_CHANGED',
78+
newTaskState: 'FAILED',
79+
};
80+
81+
job.name = JOB_NAME;
82+
job.taskGroups = [group];
83+
job.notifications = [notification1, notification2];
84+
job.labels = {env: 'testing', type: 'script'};
85+
// We use Cloud Logging as it's an option available out of the box
86+
job.logsPolicy = new batch.LogsPolicy();
87+
job.logsPolicy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING;
88+
// The job's parent is the project and region in which the job will run
89+
const parent = `projects/${PROJECT_ID}/locations/${REGION}`;
90+
91+
async function callCreateBatchNotifications() {
92+
// Construct request
93+
const request = {
94+
parent,
95+
jobId: JOB_NAME,
96+
job,
97+
};
98+
99+
// Run request
100+
const [response] = await batchClient.createJob(request);
101+
console.log(JSON.stringify(response));
102+
}
103+
104+
callCreateBatchNotifications();
105+
// [END batch_notifications]
106+
}
107+
108+
process.on('unhandledRejection', err => {
109+
console.error(err.message);
110+
process.exitCode = 1;
111+
});
112+
113+
main();

batch/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"*.js"
1111
],
1212
"scripts": {
13-
"test": "c8 mocha -p -j 2 --timeout 600000 test/*.js",
13+
"test": "c8 mocha -p -j 2 --timeout 600000 test/*.test.js",
1414
"publish": "echo 'sample test; do not publish'"
1515
},
1616
"dependencies": {
File renamed without changes.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
'use strict';
18+
19+
const path = require('path');
20+
const assert = require('assert');
21+
const {describe, it} = require('mocha');
22+
const cp = require('child_process');
23+
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
24+
const cwd = path.join(__dirname, '..');
25+
const {BatchServiceClient} = require('@google-cloud/batch').v1;
26+
const batchClient = new BatchServiceClient();
27+
28+
async function deleteJob(projectId, region, jobId) {
29+
const request = {
30+
name: `projects/${projectId}/locations/${region}/jobs/${jobId}`,
31+
};
32+
try {
33+
await batchClient.deleteJob(request);
34+
} catch (err) {
35+
console.error('Error deleting job:', err);
36+
}
37+
}
38+
39+
describe('Create batch notifications', async () => {
40+
const jobName = 'job-name-batch-notifications';
41+
const region = 'europe-central2';
42+
const topicId = 'topic-id';
43+
44+
let projectId;
45+
46+
before(async () => {
47+
projectId = await batchClient.getProjectId();
48+
});
49+
50+
after(async () => {
51+
await deleteJob(projectId, region, jobName);
52+
});
53+
54+
it('should create a new job with batch notifications', async () => {
55+
const pubsubTopic = `projects/${projectId}/topics/${topicId}`;
56+
const expectedNotifications = [
57+
{
58+
pubsubTopic,
59+
message: {
60+
newJobState: 'STATE_UNSPECIFIED',
61+
newTaskState: 'STATE_UNSPECIFIED',
62+
type: 'JOB_STATE_CHANGED',
63+
},
64+
},
65+
{
66+
pubsubTopic,
67+
message: {
68+
type: 'TASK_STATE_CHANGED',
69+
newTaskState: 'FAILED',
70+
newJobState: 'STATE_UNSPECIFIED',
71+
},
72+
},
73+
];
74+
75+
const response = execSync('node ./create/create_batch_notifications.js', {
76+
cwd,
77+
});
78+
79+
assert.deepEqual(JSON.parse(response).notifications, expectedNotifications);
80+
});
81+
});

0 commit comments

Comments
 (0)