Skip to content

Commit

Permalink
feat: Batch notifications (#3772)
Browse files Browse the repository at this point in the history
* feat: add batch_notification sample

* refactor: update package.json and add .test.js postfix to test files
  • Loading branch information
gryczj authored Aug 1, 2024
1 parent 197bfa7 commit 42d1733
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/batch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ jobs:
id-token: 'write'
if: github.event_name == 'schedule' && always() # always() submits logs even if tests fail
uses: ./.github/workflows/flakybot.yaml
needs: [test]
needs: [test]
113 changes: 113 additions & 0 deletions batch/create/create_batch_notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

async function main() {
// [START batch_notifications]
// Imports the Batch library
const batchLib = require('@google-cloud/batch');
const batch = batchLib.protos.google.cloud.batch.v1;

// Instantiates a client
const batchClient = new batchLib.v1.BatchServiceClient();

/**
* TODO(developer): Update these variables before running the sample.
*/
const PROJECT_ID = await batchClient.getProjectId();
// Name of the region you want to use to run the job. Regions that are
// available for Batch are listed on: https://cloud.google.com/batch/docs/get-started#locations
const REGION = 'europe-central2';
// The name of the job that will be created.
// It needs to be unique for each project and region pair.
const JOB_NAME = 'job-name-batch-notifications';
// The Pub/Sub topic ID to send the notifications to.
const TOPIC_ID = 'topic-id';

// Define what will be done as part of the job.
const task = new batch.TaskSpec();
const runnable = new batch.Runnable();
runnable.script = new batch.Runnable.Script();
runnable.script.commands = [
'-c',
'echo Hello world! This is task ${BATCH_TASK_INDEX}.',
];
task.runnables = [runnable];
task.maxRetryCount = 2;
task.maxRunDuration = {seconds: 3600};

// Tasks are grouped inside a job using TaskGroups.
const group = new batch.TaskGroup();
group.taskCount = 3;
group.taskSpec = task;

const job = new batch.Job();
job.name = JOB_NAME;
job.taskGroups = [group];
job.labels = {env: 'testing', type: 'script'};
// We use Cloud Logging as it's an option available out of the box
job.logsPolicy = new batch.LogsPolicy();
job.logsPolicy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING;

// Create batch notification when job state changed
const notification1 = new batch.JobNotification();
notification1.pubsubTopic = `projects/${PROJECT_ID}/topics/${TOPIC_ID}`;
notification1.message = {
type: 'JOB_STATE_CHANGED',
};

// Create batch notification when task state changed
const notification2 = new batch.JobNotification();
notification2.pubsubTopic = `projects/${PROJECT_ID}/topics/${TOPIC_ID}`;
notification2.message = {
type: 'TASK_STATE_CHANGED',
newTaskState: 'FAILED',
};

job.name = JOB_NAME;
job.taskGroups = [group];
job.notifications = [notification1, notification2];
job.labels = {env: 'testing', type: 'script'};
// We use Cloud Logging as it's an option available out of the box
job.logsPolicy = new batch.LogsPolicy();
job.logsPolicy.destination = batch.LogsPolicy.Destination.CLOUD_LOGGING;
// The job's parent is the project and region in which the job will run
const parent = `projects/${PROJECT_ID}/locations/${REGION}`;

async function callCreateBatchNotifications() {
// Construct request
const request = {
parent,
jobId: JOB_NAME,
job,
};

// Run request
const [response] = await batchClient.createJob(request);
console.log(JSON.stringify(response));
}

callCreateBatchNotifications();
// [END batch_notifications]
}

process.on('unhandledRejection', err => {
console.error(err.message);
process.exitCode = 1;
});

main();
2 changes: 1 addition & 1 deletion batch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"*.js"
],
"scripts": {
"test": "c8 mocha -p -j 2 --timeout 600000 test/*.js",
"test": "c8 mocha -p -j 2 --timeout 600000 test/*.test.js",
"publish": "echo 'sample test; do not publish'"
},
"dependencies": {
Expand Down
File renamed without changes.
File renamed without changes.
81 changes: 81 additions & 0 deletions batch/test/create_batch_notifications.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

const path = require('path');
const assert = require('assert');
const {describe, it} = require('mocha');
const cp = require('child_process');
const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
const cwd = path.join(__dirname, '..');
const {BatchServiceClient} = require('@google-cloud/batch').v1;
const batchClient = new BatchServiceClient();

async function deleteJob(projectId, region, jobId) {
const request = {
name: `projects/${projectId}/locations/${region}/jobs/${jobId}`,
};
try {
await batchClient.deleteJob(request);
} catch (err) {
console.error('Error deleting job:', err);
}
}

describe('Create batch notifications', async () => {
const jobName = 'job-name-batch-notifications';
const region = 'europe-central2';
const topicId = 'topic-id';

let projectId;

before(async () => {
projectId = await batchClient.getProjectId();
});

after(async () => {
await deleteJob(projectId, region, jobName);
});

it('should create a new job with batch notifications', async () => {
const pubsubTopic = `projects/${projectId}/topics/${topicId}`;
const expectedNotifications = [
{
pubsubTopic,
message: {
newJobState: 'STATE_UNSPECIFIED',
newTaskState: 'STATE_UNSPECIFIED',
type: 'JOB_STATE_CHANGED',
},
},
{
pubsubTopic,
message: {
type: 'TASK_STATE_CHANGED',
newTaskState: 'FAILED',
newJobState: 'STATE_UNSPECIFIED',
},
},
];

const response = execSync('node ./create/create_batch_notifications.js', {
cwd,
});

assert.deepEqual(JSON.parse(response).notifications, expectedNotifications);
});
});

0 comments on commit 42d1733

Please sign in to comment.