From 3fb09c9b9e570aa2ef9ce0fc6b8ac6e9135af601 Mon Sep 17 00:00:00 2001 From: tcoyze Date: Fri, 19 Apr 2024 11:36:10 -0700 Subject: [PATCH 1/3] fix(serverless): Check if cloud event callback is a function (#9044) --- .../google-cloud-serverless/src/gcpfunction/cloud_events.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/google-cloud-serverless/src/gcpfunction/cloud_events.ts b/packages/google-cloud-serverless/src/gcpfunction/cloud_events.ts index c2d1aa307cda..3ea4858d829c 100644 --- a/packages/google-cloud-serverless/src/gcpfunction/cloud_events.ts +++ b/packages/google-cloud-serverless/src/gcpfunction/cloud_events.ts @@ -56,7 +56,9 @@ function _wrapCloudEventFunction( DEBUG_BUILD && logger.error(e); }) .then(() => { - callback(...args); + if (typeof callback === 'function') { + callback(...args); + } }); }); From 579c8b3eb2cfbc1e6cfafc39630159f2cc155780 Mon Sep 17 00:00:00 2001 From: tcoyze Date: Mon, 22 Apr 2024 08:48:55 -0700 Subject: [PATCH 2/3] feat(serverless): Add tests for google cloud event promise based handlers --- .../test/gcpfunction/cloud_event.test.ts | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts index 5c1824077b8d..c34e1dbc9b89 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts @@ -84,6 +84,59 @@ describe('wrapCloudEventFunction', () => { expect(mockFlush).toBeCalledWith(2000); }); + describe('wrapEventFunction() as Promise', () => { + test('successful execution', async () => { + const func: CloudEventFunction = (_context) => + new Promise(resolve => { + setTimeout(() => { + resolve(42); + }, 10); + }); + const wrappedHandler = wrapCloudEventFunction(func); + await expect(handleCloudEvent(wrappedHandler)).resolves.toBe(42); + + const fakeTransactionContext = { + name: 'event.type', + op: 'function.gcp.cloud_event', + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.serverless.gcp_cloud_event', + }, + }; + + expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function)); + expect(mockSpan.end).toBeCalled(); + expect(mockFlush).toBeCalledWith(2000); + }); + + test('capture error', async () => { + const error = new Error('wat'); + const handler: CloudEventFunction = (_context) => + new Promise((_, reject) => { + setTimeout(() => { + reject(error); + }, 10); + }); + + const wrappedHandler = wrapCloudEventFunction(handler); + await expect(handleCloudEvent(wrappedHandler)).rejects.toThrowError(error); + + const fakeTransactionContext = { + name: 'event.type', + op: 'function.gcp.cloud_event', + attributes: { + [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component', + [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.serverless.gcp_cloud_event', + }, + }; + + expect(mockStartSpanManual).toBeCalledWith(fakeTransactionContext, expect.any(Function)); + expect(mockCaptureException).toBeCalledWith(error, expect.any(Function)); + expect(mockSpan.end).toBeCalled(); + expect(mockFlush).toBeCalled(); + }); + }); + test('capture error', async () => { const error = new Error('wat'); const handler: CloudEventFunction = _context => { From f3d3c161422322ba13c65d3784a1edb56ebae2c2 Mon Sep 17 00:00:00 2001 From: tcoyze Date: Mon, 22 Apr 2024 09:29:25 -0700 Subject: [PATCH 3/3] style(serverless): Address biome errors --- .../test/gcpfunction/cloud_event.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts index c34e1dbc9b89..941d4d259930 100644 --- a/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts +++ b/packages/google-cloud-serverless/test/gcpfunction/cloud_event.test.ts @@ -86,7 +86,7 @@ describe('wrapCloudEventFunction', () => { describe('wrapEventFunction() as Promise', () => { test('successful execution', async () => { - const func: CloudEventFunction = (_context) => + const func: CloudEventFunction = _context => new Promise(resolve => { setTimeout(() => { resolve(42); @@ -111,7 +111,7 @@ describe('wrapCloudEventFunction', () => { test('capture error', async () => { const error = new Error('wat'); - const handler: CloudEventFunction = (_context) => + const handler: CloudEventFunction = _context => new Promise((_, reject) => { setTimeout(() => { reject(error);