diff --git a/packages/serverless/src/gcpfunction/cloud_events.ts b/packages/serverless/src/gcpfunction/cloud_events.ts index 533c74bb7653..a31158156990 100644 --- a/packages/serverless/src/gcpfunction/cloud_events.ts +++ b/packages/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); + } }); }); diff --git a/packages/serverless/test/gcpfunction.test.ts b/packages/serverless/test/gcpfunction.test.ts index cde69e6b22d2..085835752cc5 100644 --- a/packages/serverless/test/gcpfunction.test.ts +++ b/packages/serverless/test/gcpfunction.test.ts @@ -472,6 +472,59 @@ describe('GCPFunction', () => { 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 => {