From 69c83489c85486c9b2aed4a1292bd9f0aae9ca44 Mon Sep 17 00:00:00 2001 From: Gauravudia <60897972+Gauravudia@users.noreply.github.com> Date: Mon, 12 Feb 2024 19:07:26 +0530 Subject: [PATCH 1/2] fix: amplitude batch output metadata (#3077) * fix: amplitude batching * refactor: remove commented code * refactor: remove redundant import --- src/v0/destinations/am/transform.js | 13 +- .../destination/batch/failure_batch.json | 403 +++++++++++++----- .../destinations/am/batch/data.ts | 132 +++--- 3 files changed, 369 insertions(+), 179 deletions(-) diff --git a/src/v0/destinations/am/transform.js b/src/v0/destinations/am/transform.js index 911ec51be08..d78a5f727fa 100644 --- a/src/v0/destinations/am/transform.js +++ b/src/v0/destinations/am/transform.js @@ -22,13 +22,13 @@ const { getFieldValueFromMessage, getValueFromMessage, deleteObjectProperty, - getErrorRespEvents, removeUndefinedAndNullValues, isDefinedAndNotNull, isAppleFamily, isDefinedAndNotNullAndNotEmpty, simpleProcessRouterDest, isValidInteger, + handleRtTfSingleEventError, } = require('../../util'); const { BASE_URL, @@ -40,7 +40,6 @@ const { AMBatchSizeLimit, AMBatchEventLimit, } = require('./config'); -const tags = require('../../util/tags'); const AMUtils = require('./utils'); @@ -904,16 +903,10 @@ const batch = (destEvents) => { // this case shold not happen and should be filtered already // by the first pass of single event transformation if (messageEvent && !userId && !deviceId) { - const errorResponse = getErrorRespEvents( - metadata, - 400, + const MissingUserIdDeviceIdError = new InstrumentationError( 'Both userId and deviceId cannot be undefined', - { - [tags.TAG_NAMES.ERROR_CATEGORY]: tags.ERROR_CATEGORIES.DATA_VALIDATION, - [tags.TAG_NAMES.ERROR_TYPE]: tags.ERROR_TYPES.INSTRUMENTATION, - }, ); - respList.push(errorResponse); + respList.push(handleRtTfSingleEventError(ev, MissingUserIdDeviceIdError, {})); return; } /* check if not a JSON body or (userId length < 5 && batchEventsWithUserIdLengthLowerThanFive is false) or diff --git a/test/apitests/data_scenarios/destination/batch/failure_batch.json b/test/apitests/data_scenarios/destination/batch/failure_batch.json index 8063bc74a12..6352ca1a11f 100644 --- a/test/apitests/data_scenarios/destination/batch/failure_batch.json +++ b/test/apitests/data_scenarios/destination/batch/failure_batch.json @@ -1051,125 +1051,314 @@ }, "output": [ { - "metadata": { - "userId": "<<>>testUser<<>>testUser", - "jobId": 2, - "sourceId": "27O0bmEEx3GgfmEhZHUcPwJQVWC", - "destinationId": "2JK3ACpBjq9AmvUbxR1u2pDPSYR", - "attemptNum": 0, - "receivedAt": "2022-12-24T17:29:00.699+05:30", - "createdAt": "2022-12-24T11:59:03.125Z", - "firstAttemptedAt": "", - "transformAt": "processor", - "workspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg", - "secret": null, - "jobsT": { - "UUID": "aaa8b7c4-2600-478b-b275-01740e1ef50c", - "JobID": 2, - "UserID": "<<>>testUser<<>>testUser", - "CreatedAt": "2022-12-24T11:59:03.125515Z", - "ExpireAt": "2022-12-24T11:59:03.125515Z", - "CustomVal": "AM", - "EventCount": 1, - "EventPayload": { - "body": { - "XML": {}, - "FORM": {}, - "JSON": { - "events": [ - { - "ip": "[::1]", - "time": 1671883143047, - "library": "rudderstack", - "user_id": "testUser", - "device_id": "anon-id", - "insert_id": "14642496-9a12-4db7-b0f2-9a336cf6cea9", - "event_type": "Product Added", - "session_id": -1, - "user_properties": { - "email": "test.c97@gmail.com", - "phone": "+919876543210", - "gender": "Male", - "lastName": "Rudderlabs", - "firstName": "test" - }, - "event_properties": { - "sku": "F15", - "url": "https://www.website.com/product/path", - "name": "Game", - "brand": "Gamepro", - "price": 13.49, - "coupon": "DISC21", - "variant": "111", - "category": "Games", - "position": 1, - "quantity": 11, - "image_url": "https://www.website.com/product/path.png", - "product_id": "123" + "metadata": [ + { + "userId": "<<>>testUser<<>>testUser", + "jobId": 2, + "sourceId": "27O0bmEEx3GgfmEhZHUcPwJQVWC", + "destinationId": "2JK3ACpBjq9AmvUbxR1u2pDPSYR", + "attemptNum": 0, + "receivedAt": "2022-12-24T17:29:00.699+05:30", + "createdAt": "2022-12-24T11:59:03.125Z", + "firstAttemptedAt": "", + "transformAt": "processor", + "workspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "secret": null, + "jobsT": { + "UUID": "aaa8b7c4-2600-478b-b275-01740e1ef50c", + "JobID": 2, + "UserID": "<<>>testUser<<>>testUser", + "CreatedAt": "2022-12-24T11:59:03.125515Z", + "ExpireAt": "2022-12-24T11:59:03.125515Z", + "CustomVal": "AM", + "EventCount": 1, + "EventPayload": { + "body": { + "XML": {}, + "FORM": {}, + "JSON": { + "events": [ + { + "ip": "[::1]", + "time": 1671883143047, + "library": "rudderstack", + "user_id": "testUser", + "device_id": "anon-id", + "insert_id": "14642496-9a12-4db7-b0f2-9a336cf6cea9", + "event_type": "Product Added", + "session_id": -1, + "user_properties": { + "email": "test.c97@gmail.com", + "phone": "+919876543210", + "gender": "Male", + "lastName": "Rudderlabs", + "firstName": "test" + }, + "event_properties": { + "sku": "F15", + "url": "https://www.website.com/product/path", + "name": "Game", + "brand": "Gamepro", + "price": 13.49, + "coupon": "DISC21", + "variant": "111", + "category": "Games", + "position": 1, + "quantity": 11, + "image_url": "https://www.website.com/product/path.png", + "product_id": "123" + } } + ], + "api_key": "dummyApiKey", + "options": { + "min_id_length": 1 } - ], - "api_key": "dummyApiKey", - "options": { - "min_id_length": 1 - } + }, + "JSON_ARRAY": {} }, - "JSON_ARRAY": {} + "type": "REST", + "files": {}, + "method": "POST", + "params": {}, + "userId": "anon-id", + "headers": { + "Content-Type": "application/json" + }, + "version": "1", + "endpoint": "https://api2.amplitude.com/2/httpapi" }, - "type": "REST", - "files": {}, - "method": "POST", - "params": {}, - "userId": "anon-id", - "headers": { - "Content-Type": "application/json" + "PayloadSize": 1133, + "LastJobStatus": { + "JobID": 0, + "JobState": "", + "AttemptNum": 0, + "ExecTime": "0001-01-01T00:00:00Z", + "RetryTime": "0001-01-01T00:00:00Z", + "ErrorCode": "", + "ErrorResponse": null, + "Parameters": null, + "WorkspaceId": "" }, - "version": "1", - "endpoint": "https://api2.amplitude.com/2/httpapi" - }, - "PayloadSize": 1133, - "LastJobStatus": { - "JobID": 0, - "JobState": "", - "AttemptNum": 0, - "ExecTime": "0001-01-01T00:00:00Z", - "RetryTime": "0001-01-01T00:00:00Z", - "ErrorCode": "", - "ErrorResponse": null, - "Parameters": null, - "WorkspaceId": "" - }, - "Parameters": { - "record_id": null, - "source_id": "27O0bmEEx3GgfmEhZHUcPwJQVWC", - "event_name": "Product Added", - "event_type": "track", - "message_id": "14642496-9a12-4db7-b0f2-9a336cf6cea9", - "received_at": "2022-12-24T17:29:00.699+05:30", - "workspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg", - "transform_at": "processor", - "source_job_id": "", - "destination_id": "2JK3ACpBjq9AmvUbxR1u2pDPSYR", - "gateway_job_id": 1, - "source_task_id": "", - "source_batch_id": "", - "source_category": "", - "source_job_run_id": "", - "source_task_run_id": "", - "source_definition_id": "1b6gJdqOPOCadT3cddw8eidV591", - "destination_definition_id": "" + "Parameters": { + "record_id": null, + "source_id": "27O0bmEEx3GgfmEhZHUcPwJQVWC", + "event_name": "Product Added", + "event_type": "track", + "message_id": "14642496-9a12-4db7-b0f2-9a336cf6cea9", + "received_at": "2022-12-24T17:29:00.699+05:30", + "workspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "transform_at": "processor", + "source_job_id": "", + "destination_id": "2JK3ACpBjq9AmvUbxR1u2pDPSYR", + "gateway_job_id": 1, + "source_task_id": "", + "source_batch_id": "", + "source_category": "", + "source_job_run_id": "", + "source_task_run_id": "", + "source_definition_id": "1b6gJdqOPOCadT3cddw8eidV591", + "destination_definition_id": "" + }, + "WorkspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg" }, - "WorkspaceId": "27O0bhB6p5ehfOWeeZlOSsSDTLg" - }, - "workerAssignedTime": "2022-12-24T17:29:04.051596+05:30" - }, + "workerAssignedTime": "2022-12-24T17:29:04.051596+05:30" + } + ], "batched": false, "statusCode": 400, "statTags": { "errorCategory": "dataValidation", "errorType": "instrumentation" }, - "error": "Both userId and deviceId cannot be undefined" + "error": "Both userId and deviceId cannot be undefined", + "destination": { + "ID": "2JK3ACpBjq9AmvUbxR1u2pDPSYR", + "Name": "Amplitude-2", + "DestinationDefinition": { + "ID": "1QGzO4fWSyq3lsyFHf4eQAMDSr9", + "Name": "AM", + "DisplayName": "Amplitude", + "Config": { + "destConfig": { + "android": [ + "eventUploadPeriodMillis", + "eventUploadThreshold", + "useNativeSDK", + "enableLocationListening", + "trackSessionEvents", + "useAdvertisingIdForDeviceId" + ], + "defaultConfig": [ + "apiKey", + "groupTypeTrait", + "groupValueTrait", + "trackAllPages", + "trackCategorizedPages", + "trackNamedPages", + "traitsToIncrement", + "traitsToSetOnce", + "traitsToAppend", + "traitsToPrepend", + "trackProductsOnce", + "trackRevenuePerProduct", + "versionName", + "apiSecret", + "residencyServer", + "blacklistedEvents", + "whitelistedEvents", + "eventFilteringOption", + "mapDeviceBrand" + ], + "flutter": [ + "eventUploadPeriodMillis", + "eventUploadThreshold", + "useNativeSDK", + "enableLocationListening", + "trackSessionEvents", + "useAdvertisingIdForDeviceId", + "useIdfaAsDeviceId" + ], + "ios": [ + "eventUploadPeriodMillis", + "eventUploadThreshold", + "useNativeSDK", + "trackSessionEvents", + "useIdfaAsDeviceId" + ], + "reactnative": [ + "eventUploadPeriodMillis", + "eventUploadThreshold", + "useNativeSDK", + "enableLocationListening", + "trackSessionEvents", + "useAdvertisingIdForDeviceId", + "useIdfaAsDeviceId" + ], + "web": [ + "useNativeSDK", + "preferAnonymousIdForDeviceId", + "deviceIdFromUrlParam", + "forceHttps", + "trackGclid", + "trackReferrer", + "saveParamsReferrerOncePerSession", + "trackUtmProperties", + "unsetParamsReferrerOnNewSession", + "batchEvents", + "eventUploadPeriodMillis", + "eventUploadThreshold", + "oneTrustCookieCategories" + ] + }, + "excludeKeys": [], + "includeKeys": [ + "apiKey", + "groupTypeTrait", + "groupValueTrait", + "trackAllPages", + "trackCategorizedPages", + "trackNamedPages", + "traitsToIncrement", + "traitsToSetOnce", + "traitsToAppend", + "traitsToPrepend", + "trackProductsOnce", + "trackRevenuePerProduct", + "preferAnonymousIdForDeviceId", + "deviceIdFromUrlParam", + "forceHttps", + "trackGclid", + "trackReferrer", + "saveParamsReferrerOncePerSession", + "trackUtmProperties", + "unsetParamsReferrerOnNewSession", + "batchEvents", + "eventUploadPeriodMillis", + "eventUploadThreshold", + "versionName", + "enableLocationListening", + "useAdvertisingIdForDeviceId", + "trackSessionEvents", + "useIdfaAsDeviceId", + "blacklistedEvents", + "whitelistedEvents", + "oneTrustCookieCategories", + "eventFilteringOption", + "mapDeviceBrand" + ], + "saveDestinationResponse": true, + "secretKeys": ["apiKey", "apiSecret"], + "supportedMessageTypes": ["alias", "group", "identify", "page", "screen", "track"], + "supportedSourceTypes": [ + "android", + "ios", + "web", + "unity", + "amp", + "cloud", + "warehouse", + "reactnative", + "flutter", + "cordova" + ], + "supportsVisualMapper": true, + "transformAt": "processor", + "transformAtV1": "processor" + }, + "ResponseRules": null + }, + "Config": { + "apiKey": "dummyApiKey", + "apiSecret": "", + "blacklistedEvents": [ + { + "eventName": "" + } + ], + "eventFilteringOption": "disable", + "groupTypeTrait": "", + "groupValueTrait": "", + "mapDeviceBrand": false, + "residencyServer": "standard", + "trackAllPages": false, + "trackCategorizedPages": true, + "trackNamedPages": true, + "trackProductsOnce": false, + "trackRevenuePerProduct": false, + "traitsToAppend": [ + { + "traits": "" + } + ], + "traitsToIncrement": [ + { + "traits": "" + } + ], + "traitsToPrepend": [ + { + "traits": "" + } + ], + "traitsToSetOnce": [ + { + "traits": "" + } + ], + "versionName": "", + "whitelistedEvents": [ + { + "eventName": "" + } + ] + }, + "Enabled": true, + "WorkspaceID": "27O0bhB6p5ehfOWeeZlOSsSDTLg", + "Transformations": [], + "IsProcessorEnabled": true, + "RevisionID": "2JMKUgZX3b8sbtDSZrkUB7okeOY" + } }, { "batchedRequest": { diff --git a/test/integrations/destinations/am/batch/data.ts b/test/integrations/destinations/am/batch/data.ts index aa67df06c7c..91a17606a90 100644 --- a/test/integrations/destinations/am/batch/data.ts +++ b/test/integrations/destinations/am/batch/data.ts @@ -61,7 +61,7 @@ export const data = [ endpoint: 'https://api.eu.amplitude.com/2/httpapi', }, metadata: { - job_id: 1, + jobId: 1, userId: 'u1', }, destination: { @@ -83,16 +83,24 @@ export const data = [ { batched: false, error: 'Both userId and deviceId cannot be undefined', - //TODO fix this - metadata: { - job_id: 1, - userId: 'u1', - }, + metadata: [ + { + jobId: 1, + userId: 'u1', + }, + ], statTags: { errorCategory: 'dataValidation', errorType: 'instrumentation', }, statusCode: 400, + destination: { + ID: 'a', + url: 'a', + Config: { + residencyServer: 'EU', + }, + }, }, ], }, @@ -163,7 +171,7 @@ export const data = [ endpoint: 'https://api.eu.amplitude.com/2/httpapi', }, metadata: { - job_id: 1, + jobId: 1, userId: 'u1', }, destination: { @@ -218,7 +226,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 2, + jobId: 2, userId: 'u1', }, destination: { @@ -273,7 +281,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 3, + jobId: 3, userId: 'u1', }, destination: { @@ -331,7 +339,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 4, + jobId: 4, userId: 'u1', }, destination: { @@ -389,7 +397,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 5, + jobId: 5, userId: 'u1', }, destination: { @@ -423,7 +431,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/groupidentify', }, metadata: { - job_id: 6, + jobId: 6, userId: 'u1', }, destination: { @@ -455,7 +463,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/usermap', }, metadata: { - job_id: 7, + jobId: 7, userId: 'u1', }, destination: { @@ -529,7 +537,7 @@ export const data = [ }, metadata: [ { - job_id: 1, + jobId: 1, userId: 'u1', }, ], @@ -565,7 +573,7 @@ export const data = [ }, metadata: [ { - job_id: 6, + jobId: 6, userId: 'u1', }, ], @@ -599,7 +607,7 @@ export const data = [ }, metadata: [ { - job_id: 7, + jobId: 7, userId: 'u1', }, ], @@ -710,19 +718,19 @@ export const data = [ }, metadata: [ { - job_id: 2, + jobId: 2, userId: 'u1', }, { - job_id: 3, + jobId: 3, userId: 'u1', }, { - job_id: 4, + jobId: 4, userId: 'u1', }, { - job_id: 5, + jobId: 5, userId: 'u1', }, ], @@ -801,7 +809,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 1, + jobId: 1, userId: 'u1', }, destination: { @@ -854,7 +862,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 2, + jobId: 2, userId: 'u1', }, destination: { @@ -907,7 +915,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 3, + jobId: 3, userId: 'u1', }, destination: { @@ -963,7 +971,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 4, + jobId: 4, userId: 'u1', }, destination: { @@ -1019,7 +1027,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 5, + jobId: 5, userId: 'u1', }, destination: { @@ -1053,7 +1061,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/groupidentify', }, metadata: { - job_id: 6, + jobId: 6, userId: 'u1', }, destination: { @@ -1085,7 +1093,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/usermap', }, metadata: { - job_id: 7, + jobId: 7, userId: 'u1', }, destination: { @@ -1157,7 +1165,7 @@ export const data = [ }, metadata: [ { - job_id: 1, + jobId: 1, userId: 'u1', }, ], @@ -1193,7 +1201,7 @@ export const data = [ }, metadata: [ { - job_id: 6, + jobId: 6, userId: 'u1', }, ], @@ -1227,7 +1235,7 @@ export const data = [ }, metadata: [ { - job_id: 7, + jobId: 7, userId: 'u1', }, ], @@ -1338,19 +1346,19 @@ export const data = [ }, metadata: [ { - job_id: 2, + jobId: 2, userId: 'u1', }, { - job_id: 3, + jobId: 3, userId: 'u1', }, { - job_id: 4, + jobId: 4, userId: 'u1', }, { - job_id: 5, + jobId: 5, userId: 'u1', }, ], @@ -2117,7 +2125,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 1, + jobId: 1, userId: 'u1', }, destination: { @@ -2172,7 +2180,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 2, + jobId: 2, userId: 'u1', }, destination: { @@ -2227,7 +2235,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 3, + jobId: 3, userId: 'u1', }, destination: { @@ -2285,7 +2293,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 4, + jobId: 4, userId: 'u1', }, destination: { @@ -2343,7 +2351,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 5, + jobId: 5, userId: 'u1', }, destination: { @@ -2377,7 +2385,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/groupidentify', }, metadata: { - job_id: 6, + jobId: 6, userId: 'u1', }, destination: { @@ -2409,7 +2417,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/usermap', }, metadata: { - job_id: 7, + jobId: 7, userId: 'u1', }, destination: { @@ -2483,7 +2491,7 @@ export const data = [ }, metadata: [ { - job_id: 1, + jobId: 1, userId: 'u1', }, ], @@ -2519,7 +2527,7 @@ export const data = [ }, metadata: [ { - job_id: 6, + jobId: 6, userId: 'u1', }, ], @@ -2553,7 +2561,7 @@ export const data = [ }, metadata: [ { - job_id: 7, + jobId: 7, userId: 'u1', }, ], @@ -2664,19 +2672,19 @@ export const data = [ }, metadata: [ { - job_id: 2, + jobId: 2, userId: 'u1', }, { - job_id: 3, + jobId: 3, userId: 'u1', }, { - job_id: 4, + jobId: 4, userId: 'u1', }, { - job_id: 5, + jobId: 5, userId: 'u1', }, ], @@ -2756,7 +2764,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 1, + jobId: 1, userId: 'u1', }, destination: { @@ -2811,7 +2819,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 2, + jobId: 2, userId: 'u1', }, destination: { @@ -2866,7 +2874,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 3, + jobId: 3, userId: 'u1', }, destination: { @@ -2924,7 +2932,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 4, + jobId: 4, userId: 'u1', }, destination: { @@ -2982,7 +2990,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/2/httpapi', }, metadata: { - job_id: 5, + jobId: 5, userId: 'u1', }, destination: { @@ -3016,7 +3024,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/groupidentify', }, metadata: { - job_id: 6, + jobId: 6, userId: 'u1', }, destination: { @@ -3048,7 +3056,7 @@ export const data = [ endpoint: 'https://api2.amplitude.com/usermap', }, metadata: { - job_id: 7, + jobId: 7, userId: 'u1', }, destination: { @@ -3121,7 +3129,7 @@ export const data = [ }, metadata: [ { - job_id: 1, + jobId: 1, userId: 'u1', }, ], @@ -3157,7 +3165,7 @@ export const data = [ }, metadata: [ { - job_id: 6, + jobId: 6, userId: 'u1', }, ], @@ -3191,7 +3199,7 @@ export const data = [ }, metadata: [ { - job_id: 7, + jobId: 7, userId: 'u1', }, ], @@ -3302,19 +3310,19 @@ export const data = [ }, metadata: [ { - job_id: 2, + jobId: 2, userId: 'u1', }, { - job_id: 3, + jobId: 3, userId: 'u1', }, { - job_id: 4, + jobId: 4, userId: 'u1', }, { - job_id: 5, + jobId: 5, userId: 'u1', }, ], From a98cabdfe7781ada12baf742df4a3a439fc5fecd Mon Sep 17 00:00:00 2001 From: Gauravudia <60897972+Gauravudia@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:01:41 +0530 Subject: [PATCH 2/2] fix: gaoc batching order (#3064) * fix: gaoc batching order * refactor: apply review suggestions --- .../transform.js | 3 +- src/v0/destinations/mp/transform.js | 2 +- src/v0/destinations/mp/util.js | 91 ------ src/v0/destinations/mp/util.test.js | 230 -------------- src/v0/util/index.js | 85 +++++ src/v0/util/index.test.js | 292 ++++++++++++++++- .../router/data.ts | 294 ++++++++---------- 7 files changed, 502 insertions(+), 495 deletions(-) diff --git a/src/v0/destinations/google_adwords_offline_conversions/transform.js b/src/v0/destinations/google_adwords_offline_conversions/transform.js index 397895c6032..46cde727713 100644 --- a/src/v0/destinations/google_adwords_offline_conversions/transform.js +++ b/src/v0/destinations/google_adwords_offline_conversions/transform.js @@ -10,6 +10,7 @@ const { defaultBatchRequestConfig, getSuccessRespEvents, checkInvalidRtTfEvents, + combineBatchRequestsWithSameJobIds, } = require('../../util'); const { CALL_CONVERSION, @@ -229,7 +230,7 @@ const processRouterDest = async (inputs, reqMetadata) => { .concat(storeSalesEventsBatchedResponseList) .concat(clickCallEvents) .concat(errorRespList); - return batchedResponseList; + return combineBatchRequestsWithSameJobIds(batchedResponseList); }; module.exports = { process, processRouterDest }; diff --git a/src/v0/destinations/mp/transform.js b/src/v0/destinations/mp/transform.js index 41a814683d5..24890c0eb1e 100644 --- a/src/v0/destinations/mp/transform.js +++ b/src/v0/destinations/mp/transform.js @@ -18,6 +18,7 @@ const { handleRtTfSingleEventError, groupEventsByType, parseConfigArray, + combineBatchRequestsWithSameJobIds, } = require('../../util'); const { ConfigCategory, @@ -33,7 +34,6 @@ const { createIdentifyResponse, isImportAuthCredentialsAvailable, buildUtmParams, - combineBatchRequestsWithSameJobIds, groupEventsByEndpoint, batchEvents, trimTraits, diff --git a/src/v0/destinations/mp/util.js b/src/v0/destinations/mp/util.js index c01d2308b75..8e943f41dd0 100644 --- a/src/v0/destinations/mp/util.js +++ b/src/v0/destinations/mp/util.js @@ -139,44 +139,6 @@ const isImportAuthCredentialsAvailable = (destination) => destination.Config.serviceAccountUserName && destination.Config.projectId); -/** - * Finds an existing batch based on metadata JobIds from the provided batch and metadataMap. - * @param {*} batch - * @param {*} metadataMap The map containing metadata items indexed by JobIds. - * @returns - */ -const findExistingBatch = (batch, metadataMap) => { - let existingBatch = null; - - // eslint-disable-next-line no-restricted-syntax - for (const metadataItem of batch.metadata) { - if (metadataMap.has(metadataItem.jobId)) { - existingBatch = metadataMap.get(metadataItem.jobId); - break; - } - } - - return existingBatch; -}; - -/** - * Removes duplicate metadata within each merged batch object. - * @param {*} mergedBatches An array of merged batch objects. - */ -const removeDuplicateMetadata = (mergedBatches) => { - mergedBatches.forEach((batch) => { - const metadataSet = new Set(); - // eslint-disable-next-line no-param-reassign - batch.metadata = batch.metadata.filter((metadataItem) => { - if (!metadataSet.has(metadataItem.jobId)) { - metadataSet.add(metadataItem.jobId); - return true; - } - return false; - }); - }); -}; - /** * Builds UTM parameters from a campaign object. * @@ -273,58 +235,6 @@ const batchEvents = (successRespList, maxBatchSize, reqMetadata) => { }); }; -/** - * Combines batched requests with the same JobIds. - * @param {*} inputBatches The array of batched request objects. - * @returns The combined batched requests with merged JobIds. - * - */ -const combineBatchRequestsWithSameJobIds = (inputBatches) => { - const combineBatches = (batches) => { - const clonedBatches = [...batches]; - const mergedBatches = []; - const metadataMap = new Map(); - - clonedBatches.forEach((batch) => { - const existingBatch = findExistingBatch(batch, metadataMap); - - if (existingBatch) { - // Merge batchedRequests arrays - existingBatch.batchedRequest = [ - ...(Array.isArray(existingBatch.batchedRequest) - ? existingBatch.batchedRequest - : [existingBatch.batchedRequest]), - ...(Array.isArray(batch.batchedRequest) ? batch.batchedRequest : [batch.batchedRequest]), - ]; - - // Merge metadata - batch.metadata.forEach((metadataItem) => { - if (!metadataMap.has(metadataItem.jobId)) { - metadataMap.set(metadataItem.jobId, existingBatch); - } - existingBatch.metadata.push(metadataItem); - }); - } else { - mergedBatches.push(batch); - batch.metadata.forEach((metadataItem) => { - metadataMap.set(metadataItem.jobId, batch); - }); - } - }); - - // Remove duplicate metadata within each merged object - removeDuplicateMetadata(mergedBatches); - - return mergedBatches; - }; - // We need to run this twice because in first pass some batches might not get merged - // and in second pass they might get merged - // Example: [[{jobID:1}, {jobID:2}], [{jobID:3}], [{jobID:1}, {jobID:3}]] - // 1st pass: [[{jobID:1}, {jobID:2}, {jobID:3}], [{jobID:3}]] - // 2nd pass: [[{jobID:1}, {jobID:2}, {jobID:3}]] - return combineBatches(combineBatches(inputBatches)); -}; - /** * Trims the traits and contextTraits objects based on the setOnceProperties array and returns an object containing the modified traits, contextTraits, and setOnce properties. * @@ -398,6 +308,5 @@ module.exports = { groupEventsByEndpoint, generateBatchedPayloadForArray, batchEvents, - combineBatchRequestsWithSameJobIds, trimTraits, }; diff --git a/src/v0/destinations/mp/util.test.js b/src/v0/destinations/mp/util.test.js index ebf140faddd..866119a336c 100644 --- a/src/v0/destinations/mp/util.test.js +++ b/src/v0/destinations/mp/util.test.js @@ -1,5 +1,4 @@ const { - combineBatchRequestsWithSameJobIds, groupEventsByEndpoint, batchEvents, generateBatchedPayloadForArray, @@ -263,235 +262,6 @@ describe('Mixpanel utils test', () => { }); }); - describe('Unit test cases for combineBatchRequestsWithSameJobIds', () => { - it('Combine batch request with same jobIds', async () => { - const input = [ - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/track/', - }, - metadata: [ - { - jobId: 1, - }, - { - jobId: 4, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/import/', - }, - metadata: [ - { - jobId: 3, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/track/', - }, - metadata: [ - { - jobId: 5, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/engage/', - }, - metadata: [ - { - jobId: 1, - }, - { - jobId: 3, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/import/', - }, - metadata: [ - { - jobId: 6, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - ]; - - const expectedOutput = [ - { - batchedRequest: [ - { - endpoint: 'https://api.mixpanel.com/track/', - }, - { - endpoint: 'https://api.mixpanel.com/engage/', - }, - { - endpoint: 'https://api.mixpanel.com/import/', - }, - ], - metadata: [ - { - jobId: 1, - }, - { - jobId: 4, - }, - { - jobId: 3, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/track/', - }, - metadata: [ - { - jobId: 5, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/import/', - }, - metadata: [ - { - jobId: 6, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - ]; - expect(combineBatchRequestsWithSameJobIds(input)).toEqual(expectedOutput); - }); - - it('Each batchRequest contains unique jobIds (no event multiplexing)', async () => { - const input = [ - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/track/', - }, - metadata: [ - { - jobId: 1, - }, - { - jobId: 4, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/engage/', - }, - metadata: [ - { - jobId: 2, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/engage/', - }, - metadata: [ - { - jobId: 5, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - ]; - - const expectedOutput = [ - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/track/', - }, - - metadata: [ - { - jobId: 1, - }, - { - jobId: 4, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/engage/', - }, - metadata: [ - { - jobId: 2, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - { - batchedRequest: { - endpoint: 'https://api.mixpanel.com/engage/', - }, - metadata: [ - { - jobId: 5, - }, - ], - batched: true, - statusCode: 200, - destination: destinationMock, - }, - ]; - expect(combineBatchRequestsWithSameJobIds(input)).toEqual(expectedOutput); - }); - }); - describe('Unit test cases for generateBatchedPayloadForArray', () => { it('should generate a batched payload with GZIP payload for /import endpoint when given an array of events', () => { const events = [ diff --git a/src/v0/util/index.js b/src/v0/util/index.js index 49ef39969ec..0cc66b2d7a5 100644 --- a/src/v0/util/index.js +++ b/src/v0/util/index.js @@ -33,6 +33,7 @@ const { AUTH_STATUS_INACTIVE, } = require('../../adapters/networkhandler/authConstants'); const { FEATURE_FILTER_CODE, FEATURE_GZIP_SUPPORT } = require('./constant'); +const { CommonUtils } = require('../../util/common'); // ======================================================================== // INLINERS @@ -2136,6 +2137,87 @@ const parseConfigArray = (arr, key) => { return arr.map((item) => item[key]); }; +/** + * Finds an existing batch based on metadata JobIds from the provided batch and metadataMap. + * @param {*} batch + * @param {*} metadataMap The map containing metadata items indexed by JobIds. + * @returns + */ +const findExistingBatch = (batch, metadataMap) => { + const existingMetadataItem = batch.metadata.find((metadataItem) => + metadataMap.has(metadataItem.jobId), + ); + return existingMetadataItem ? metadataMap.get(existingMetadataItem.jobId) : null; +}; + +/** + * Removes duplicate metadata within each merged batch object. + * @param {*} mergedBatches An array of merged batch objects. + */ +const removeDuplicateMetadata = (mergedBatches) => { + mergedBatches.forEach((batch) => { + const metadataSet = new Set(); + // eslint-disable-next-line no-param-reassign + batch.metadata = batch.metadata.filter((metadataItem) => { + if (!metadataSet.has(metadataItem.jobId)) { + metadataSet.add(metadataItem.jobId); + return true; + } + return false; + }); + }); +}; + +/** + * Combines batched requests with the same JobIds. + * @param {*} inputBatches The array of batched request objects. + * @returns The combined batched requests with merged JobIds. + * + */ +const combineBatchRequestsWithSameJobIds = (inputBatches) => { + const combineBatches = (batches) => { + const clonedBatches = [...batches]; + const mergedBatches = []; + const metadataMap = new Map(); + + clonedBatches.forEach((batch) => { + const existingBatch = findExistingBatch(batch, metadataMap); + + if (existingBatch) { + // Merge batchedRequests arrays + existingBatch.batchedRequest = [ + ...CommonUtils.toArray(existingBatch.batchedRequest), + ...CommonUtils.toArray(batch.batchedRequest), + ]; + + // Merge metadata + batch.metadata.forEach((metadataItem) => { + if (!metadataMap.has(metadataItem.jobId)) { + metadataMap.set(metadataItem.jobId, existingBatch); + } + existingBatch.metadata.push(metadataItem); + }); + } else { + mergedBatches.push(batch); + batch.metadata.forEach((metadataItem) => { + metadataMap.set(metadataItem.jobId, batch); + }); + } + }); + + // Remove duplicate metadata within each merged object + removeDuplicateMetadata(mergedBatches); + + return mergedBatches; + }; + // We need to run this twice because in first pass some batches might not get merged + // and in second pass they might get merged + // Example: [[{jobID:1}, {jobID:2}], [{jobID:3}], [{jobID:1}, {jobID:3}]] + // 1st pass: [[{jobID:1}, {jobID:2}, {jobID:3}], [{jobID:3}]] + // 2nd pass: [[{jobID:1}, {jobID:2}, {jobID:3}]] + return combineBatches(combineBatches(inputBatches)); +}; + // ======================================================================== // EXPORTS // ======================================================================== @@ -2249,4 +2331,7 @@ module.exports = { isNewStatusCodesAccepted, IsGzipSupported, parseConfigArray, + findExistingBatch, + removeDuplicateMetadata, + combineBatchRequestsWithSameJobIds, }; diff --git a/src/v0/util/index.test.js b/src/v0/util/index.test.js index 1c6b34eca6a..4dc62556911 100644 --- a/src/v0/util/index.test.js +++ b/src/v0/util/index.test.js @@ -2,7 +2,12 @@ const { TAG_NAMES } = require('@rudderstack/integrations-lib'); const utilities = require('.'); const { getFuncTestData } = require('../../../test/testHelper'); const { FilteredEventsError } = require('./errorTypes'); -const { hasCircularReference, flattenJson, generateExclusionList } = require('./index'); +const { + hasCircularReference, + flattenJson, + generateExclusionList, + combineBatchRequestsWithSameJobIds, +} = require('./index'); // Names of the utility functions to test const functionNames = [ @@ -166,3 +171,288 @@ describe('generateExclusionList', () => { expect(result).toEqual(expected); }); }); + +describe('Unit test cases for combineBatchRequestsWithSameJobIds', () => { + it('Combine batch request with same jobIds', async () => { + const input = [ + { + batchedRequest: { + endpoint: 'https://endpoint1', + }, + metadata: [ + { + jobId: 1, + }, + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint2', + }, + metadata: [ + { + jobId: 3, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint1', + }, + metadata: [ + { + jobId: 5, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint3', + }, + metadata: [ + { + jobId: 1, + }, + { + jobId: 3, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint2', + }, + metadata: [ + { + jobId: 6, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + ]; + + const expectedOutput = [ + { + batchedRequest: [ + { + endpoint: 'https://endpoint1', + }, + { + endpoint: 'https://endpoint3', + }, + { + endpoint: 'https://endpoint2', + }, + ], + metadata: [ + { + jobId: 1, + }, + { + jobId: 4, + }, + { + jobId: 3, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint1', + }, + metadata: [ + { + jobId: 5, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint2', + }, + metadata: [ + { + jobId: 6, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + ]; + expect(combineBatchRequestsWithSameJobIds(input)).toEqual(expectedOutput); + }); + + it('Each batchRequest contains unique jobIds (no event multiplexing)', async () => { + const input = [ + { + batchedRequest: { + endpoint: 'https://endpoint1', + }, + metadata: [ + { + jobId: 1, + }, + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint3', + }, + metadata: [ + { + jobId: 2, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint3', + }, + metadata: [ + { + jobId: 5, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + ]; + + const expectedOutput = [ + { + batchedRequest: { + endpoint: 'https://endpoint1', + }, + + metadata: [ + { + jobId: 1, + }, + { + jobId: 4, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint3', + }, + metadata: [ + { + jobId: 2, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + { + batchedRequest: { + endpoint: 'https://endpoint3', + }, + metadata: [ + { + jobId: 5, + }, + ], + batched: true, + statusCode: 200, + destination: { + Config: { + key: 'value', + }, + }, + }, + ]; + expect(combineBatchRequestsWithSameJobIds(input)).toEqual(expectedOutput); + }); +}); diff --git a/test/integrations/destinations/google_adwords_offline_conversions/router/data.ts b/test/integrations/destinations/google_adwords_offline_conversions/router/data.ts index 1536af81876..a38980f0e9f 100644 --- a/test/integrations/destinations/google_adwords_offline_conversions/router/data.ts +++ b/test/integrations/destinations/google_adwords_offline_conversions/router/data.ts @@ -96,6 +96,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, + jobId: 1, userId: 'u1', }, destination: { @@ -211,6 +212,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, + jobId: 2, userId: 'u1', }, destination: { @@ -274,7 +276,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 1, + jobId: 3, userId: 'u1', }, destination: { @@ -350,7 +352,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 2, + jobId: 4, userId: 'u1', }, destination: { @@ -426,7 +428,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 3, + jobId: 5, userId: 'u1', }, destination: { @@ -479,80 +481,130 @@ export const data = [ body: { output: [ { - batchedRequest: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: - 'https://googleads.googleapis.com/v14/customers/7693729833/offlineUserDataJobs', - headers: { - Authorization: 'Bearer abcd1234', - 'Content-Type': 'application/json', - 'developer-token': 'ijkl91011', - }, - params: { event: 'Store sales', customerId: '7693729833' }, - body: { - JSON: { - event: '7693729833', - isStoreConversion: true, - createJobPayload: { - job: { - storeSalesMetadata: { - loyaltyFraction: 1, - transaction_upload_fraction: '1', + batchedRequest: [ + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://googleads.googleapis.com/v14/customers/7693729833/offlineUserDataJobs', + headers: { + Authorization: 'Bearer abcd1234', + 'Content-Type': 'application/json', + 'developer-token': 'ijkl91011', + }, + params: { event: 'Store sales', customerId: '7693729833' }, + body: { + JSON: { + event: '7693729833', + isStoreConversion: true, + createJobPayload: { + job: { + storeSalesMetadata: { + loyaltyFraction: 1, + transaction_upload_fraction: '1', + }, + type: 'STORE_SALES_UPLOAD_FIRST_PARTY', }, - type: 'STORE_SALES_UPLOAD_FIRST_PARTY', }, - }, - addConversionPayload: { - operations: [ - { - create: { - transaction_attribute: { - store_attribute: { store_code: 'store code' }, - transaction_amount_micros: '100000000', - order_id: 'order id', - currency_code: 'INR', - transaction_date_time: '2019-10-14 16:45:18+05:30', - }, - userIdentifiers: [ - { - hashedEmail: - '6db61e6dcbcf2390e4a46af426f26a133a3bee45021422fc7ae86e9136f14110', + addConversionPayload: { + operations: [ + { + create: { + transaction_attribute: { + store_attribute: { store_code: 'store code' }, + transaction_amount_micros: '100000000', + order_id: 'order id', + currency_code: 'INR', + transaction_date_time: '2019-10-14 16:45:18+05:30', }, - ], - }, - }, - { - create: { - transaction_attribute: { - store_attribute: { store_code: 'store code2' }, - transaction_amount_micros: '100000000', - order_id: 'order id', - currency_code: 'INR', - transaction_date_time: '2019-10-14 16:45:18+05:30', + userIdentifiers: [ + { + hashedEmail: + '6db61e6dcbcf2390e4a46af426f26a133a3bee45021422fc7ae86e9136f14110', + }, + ], }, - userIdentifiers: [ - { - hashedEmail: - '6db61e6dcbcf2390e4a46af426f26a133a3bee45021422fc7ae86e9136f14110', + }, + { + create: { + transaction_attribute: { + store_attribute: { store_code: 'store code2' }, + transaction_amount_micros: '100000000', + order_id: 'order id', + currency_code: 'INR', + transaction_date_time: '2019-10-14 16:45:18+05:30', }, - ], + userIdentifiers: [ + { + hashedEmail: + '6db61e6dcbcf2390e4a46af426f26a133a3bee45021422fc7ae86e9136f14110', + }, + ], + }, }, + ], + enable_partial_failure: false, + enable_warnings: false, + validate_only: true, + }, + executeJobPayload: { validate_only: true }, + }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, + }, + files: {}, + }, + { + version: '1', + type: 'REST', + method: 'POST', + endpoint: + 'https://googleads.googleapis.com/v14/customers/7693729833:uploadCallConversions', + headers: { + Authorization: 'Bearer abcd1234', + 'Content-Type': 'application/json', + 'developer-token': 'ijkl91011', + }, + params: { + event: 'Order Completed', + customerId: '7693729833', + customVariables: [{ from: '', to: '' }], + properties: { + loyaltyFraction: 1, + order_id: 'order id', + currency: 'INR', + revenue: '100', + store_code: 'store code2', + email: 'alex@example.com', + gclid: 'gclid', + product_id: '123445', + quantity: 123, + callerId: '1234', + callStartDateTime: '2019-10-14T11:15:18.299Z', + }, + }, + body: { + JSON: { + conversions: [ + { + callerId: '1234', + callStartDateTime: '2019-10-14T11:15:18.299Z', + conversionDateTime: '2019-10-14 16:45:18+05:30', + conversionValue: 100, + currencyCode: 'INR', }, ], - enable_partial_failure: false, - enable_warnings: false, - validate_only: true, + partialFailure: true, }, - executeJobPayload: { validate_only: true }, + JSON_ARRAY: {}, + XML: {}, + FORM: {}, }, - JSON_ARRAY: {}, - XML: {}, - FORM: {}, + files: {}, }, - files: {}, - }, + ], metadata: [ { secret: { @@ -560,7 +612,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 1, + jobId: 3, userId: 'u1', }, { @@ -569,7 +621,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 2, + jobId: 4, userId: 'u1', }, ], @@ -714,6 +766,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, + jobId: 1, userId: 'u1', }, ], @@ -824,6 +877,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, + jobId: 2, userId: 'u1', }, ], @@ -857,108 +911,6 @@ export const data = [ }, }, }, - { - batchedRequest: { - version: '1', - type: 'REST', - method: 'POST', - endpoint: - 'https://googleads.googleapis.com/v14/customers/7693729833:uploadCallConversions', - headers: { - Authorization: 'Bearer abcd1234', - 'Content-Type': 'application/json', - 'developer-token': 'ijkl91011', - }, - params: { - event: 'Order Completed', - customerId: '7693729833', - customVariables: [{ from: '', to: '' }], - properties: { - loyaltyFraction: 1, - order_id: 'order id', - currency: 'INR', - revenue: '100', - store_code: 'store code2', - email: 'alex@example.com', - gclid: 'gclid', - product_id: '123445', - quantity: 123, - callerId: '1234', - callStartDateTime: '2019-10-14T11:15:18.299Z', - }, - }, - body: { - JSON: { - conversions: [ - { - callerId: '1234', - callStartDateTime: '2019-10-14T11:15:18.299Z', - conversionDateTime: '2019-10-14 16:45:18+05:30', - conversionValue: 100, - currencyCode: 'INR', - }, - ], - partialFailure: true, - }, - JSON_ARRAY: {}, - XML: {}, - FORM: {}, - }, - files: {}, - }, - metadata: [ - { - secret: { - access_token: 'abcd1234', - refresh_token: 'efgh5678', - developer_token: 'ijkl91011', - }, - jobId: 2, - userId: 'u1', - }, - ], - batched: false, - statusCode: 200, - destination: { - Config: { - rudderAccountId: '2Hsy2iFyoG5VLDd9wQcggHLMYFA', - customerId: '769-372-9833', - subAccount: false, - UserIdentifierSource: 'FIRST_PARTY', - conversionEnvironment: 'none', - defaultUserIdentifier: 'email', - hashUserIdentifier: true, - validateOnly: true, - eventsToOfflineConversionsTypeMapping: [ - { from: 'Data Reading Guide', to: 'click' }, - { from: 'Order Completed', to: 'store' }, - { from: 'Sign-up - click', to: 'click' }, - { from: 'Outbound click (rudderstack.com)', to: 'click' }, - { from: 'Page view', to: 'click' }, - { from: 'download', to: 'click' }, - { from: 'Product Clicked', to: 'store' }, - { from: 'Order Completed', to: 'call' }, - ], - loginCustomerId: '4219454086', - eventsToConversionsNamesMapping: [ - { from: 'Data Reading Guide', to: 'Data Reading Guide' }, - { from: 'Order Completed', to: 'Order Completed' }, - { from: 'Sign-up - click', to: 'Sign-up - click' }, - { - from: 'Outbound click (rudderstack.com)', - to: 'Outbound click (rudderstack.com)', - }, - { from: 'Page view', to: 'Page view' }, - { from: 'Sign up completed', to: 'Sign-up - click' }, - { from: 'download', to: 'Page view' }, - { from: 'Product Clicked', to: 'Store sales' }, - ], - authStatus: 'active', - oneTrustCookieCategories: [], - customVariables: [{ from: '', to: '' }], - }, - }, - }, { metadata: [ { @@ -967,7 +919,7 @@ export const data = [ refresh_token: 'efgh5678', developer_token: 'ijkl91011', }, - jobId: 3, + jobId: 5, userId: 'u1', }, ],