Skip to content

Commit

Permalink
Merge pull request #3080 from GoogleCloudPlatform/kennethrosario/func…
Browse files Browse the repository at this point in the history
…tions-cloudevent-tips-retry

chore(functions/v2/tips/retry): create new cloud event sample from background function sample
  • Loading branch information
kenneth-rosario authored Mar 22, 2023
2 parents 151e593 + 18436eb commit 4ab34d7
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 0 deletions.
66 changes: 66 additions & 0 deletions functions/v2/tips/retry/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2023 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
//
// http://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.

// [START functions_cloudevent_tips_retry]
const functions = require('@google-cloud/functions-framework');

/**
* Register a Cloud Event Function that demonstrates
* how to toggle retries using a promise
*
* @param {object} event The Cloud Event for the function trigger.
*/
functions.cloudEvent('retryPromise', cloudEvent => {
// The Pub/Sub event payload is passed as the CloudEvent's data payload.
// See the documentation for more details:
// https://cloud.google.com/eventarc/docs/cloudevents#pubsub
const base64PubsubMessage = cloudEvent.data.message.data;
const jsonString = Buffer.from(base64PubsubMessage, 'base64').toString();

const tryAgain = JSON.parse(jsonString).retry;

if (tryAgain) {
throw new Error('Retrying...');
} else {
console.error('Not retrying...');
return Promise.resolve();
}
});

/**
* Cloud Event Function that demonstrates
* how to toggle retries using a callback
*
* @param {object} event The Cloud Event for the function trigger.
* @param {function} callback The callback function.
*/
functions.cloudEvent('retryCallback', (cloudEvent, callback) => {
// The Pub/Sub event payload is passed as the CloudEvent's data payload.
// See the documentation for more details:
// https://cloud.google.com/eventarc/docs/cloudevents#pubsub
const base64PubsubMessage = cloudEvent.data.message.data;
const jsonString = Buffer.from(base64PubsubMessage, 'base64').toString();

const tryAgain = JSON.parse(jsonString).retry;
const err = new Error('Error!');

if (tryAgain) {
console.error('Retrying:', err);
callback(err);
} else {
console.error('Not retrying:', err);
callback();
}
});
// [END functions_cloudevent_tips_retry]
25 changes: 25 additions & 0 deletions functions/v2/tips/retry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "nodejs-docs-samples-functions-tips-retry",
"version": "0.0.1",
"private": true,
"license": "Apache-2.0",
"author": "Google Inc.",
"repository": {
"type": "git",
"url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"
},
"engines": {
"node": ">=12.0.0"
},
"scripts": {
"test": "mocha test/*.test.js --timeout=60000 --exit"
},
"devDependencies": {
"mocha": "^9.0.0",
"sinon": "^15.0.0",
"supertest": "^6.3.3"
},
"dependencies": {
"@google-cloud/functions-framework": "^3.1.3"
}
}
65 changes: 65 additions & 0 deletions functions/v2/tips/retry/test/integration.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2023 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
//
// http://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.

const supertest = require('supertest');
const functionsFramework = require('@google-cloud/functions-framework/testing');

require('..');

const jsonRetryObject = JSON.stringify({retry: true});
const encodedRetryMessage = Buffer.from(jsonRetryObject).toString('base64');

const jsonDontRetryObject = JSON.stringify({retry: false});
const encodedDontRetryMessage =
Buffer.from(jsonDontRetryObject).toString('base64');

describe('functions_cloudevent_tips_retry', () => {
it('should raise error to retry', async () => {
const cloudEventData = {data: {message: {}}};
cloudEventData.data.message.data = encodedRetryMessage;

const promiseServer = functionsFramework.getTestServer('retryPromise');
await supertest(promiseServer)
.post('/')
.send(cloudEventData)
.set('Content-Type', 'application/json')
.expect(500);

const callBackServer = functionsFramework.getTestServer('retryCallback');
await supertest(callBackServer)
.post('/')
.send(cloudEventData)
.set('Content-Type', 'application/json')
.expect(500);
});

it('should not raise error to not retry', async () => {
const cloudEventData = {data: {message: {}}};
cloudEventData.data.message.data = encodedDontRetryMessage;

const promiseServer = functionsFramework.getTestServer('retryPromise');
await supertest(promiseServer)
.post('/')
.send(cloudEventData)
.set('Content-Type', 'application/json')
.expect(204);

const callBackServer = functionsFramework.getTestServer('retryCallback');
await supertest(callBackServer)
.post('/')
.send(cloudEventData)
.set('Content-Type', 'application/json')
.expect(204);
});
});
76 changes: 76 additions & 0 deletions functions/v2/tips/retry/test/unit.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2023 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
//
// http://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 {getFunction} = require('@google-cloud/functions-framework/testing');
const sinon = require('sinon');
const assert = require('assert');
require('..');

const jsonRetryObject = JSON.stringify({retry: true});
const encodedRetryMessage = Buffer.from(jsonRetryObject).toString('base64');

const jsonDontRetryObject = JSON.stringify({retry: false});
const encodedDontRetryMessage =
Buffer.from(jsonDontRetryObject).toString('base64');

describe('functions_cloudevent_tips_retry', () => {
it('should demonstrate retry behavior for a promise', async () => {
const retryPromise = getFunction('retryPromise');

// Retry by throwing an error
assert.throws(() => {
retryPromise({
data: {
message: {
data: encodedRetryMessage,
},
},
});
}, new Error('Retrying...'));

// Terminate by returning a rejected promise
try {
await retryPromise({data: {message: {data: encodedDontRetryMessage}}});
} catch (err) {
assert.strictEqual(err.message, 'Not retrying...');
return Promise.resolve();
}
});

it('should demonstrate retry behavior for a callback', done => {
const retryCallback = getFunction('retryCallback');
const cb = sinon.stub();
const err = new Error('Error!');

// Retry by passing an error to the callback
retryCallback(
{
data: {
message: {
data: encodedRetryMessage,
},
},
},
cb
);
assert.deepStrictEqual(cb.firstCall.args, [err]);

// Terminate by passing nothing to the callback
retryCallback({data: {message: {data: encodedDontRetryMessage}}}, cb);
assert.deepStrictEqual(cb.secondCall.args, []);
done();
});
});

0 comments on commit 4ab34d7

Please sign in to comment.