Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: changes for supporting record event in FB audience #3351

Merged
merged 17 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 22 additions & 37 deletions src/v0/destinations/fb_custom_audience/transform.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
const lodash = require('lodash');
const get = require('get-value');
const { InstrumentationError, ConfigurationError } = require('@rudderstack/integrations-lib');
const {
InstrumentationError,
TransformationError,
ConfigurationError,
} = require('@rudderstack/integrations-lib');
const {
defaultRequestConfig,
defaultPostRequestConfig,
defaultDeleteRequestConfig,
checkSubsetOfArray,
isDefinedAndNotNullAndNotEmpty,
returnArrayOfSubarrays,
Expand All @@ -21,36 +14,10 @@
getSchemaForEventMappedToDest,
batchingWithPayloadSize,
} = require('./util');
const {
getEndPoint,
schemaFields,
USER_ADD,
USER_DELETE,
typeFields,
subTypeFields,
} = require('./config');
const { schemaFields, USER_ADD, USER_DELETE, typeFields, subTypeFields } = require('./config');

const { MappedToDestinationKey } = require('../../../constants');

const responseBuilderSimple = (payload, audienceId) => {
if (payload) {
const responseParams = payload.responseField;
const response = defaultRequestConfig();
response.endpoint = getEndPoint(audienceId);

if (payload.operationCategory === 'add') {
response.method = defaultPostRequestConfig.requestMethod;
}
if (payload.operationCategory === 'remove') {
response.method = defaultDeleteRequestConfig.requestMethod;
}

response.params = responseParams;
return response;
}
// fail-safety for developer error
throw new TransformationError(`Payload could not be constructed`);
};
const { processRecordInputs, responseBuilderSimple } = require('./transformV2');

// Function responsible prepare the payload field of every event parameter

Expand Down Expand Up @@ -243,6 +210,7 @@
),
);
}

toSendEvents.forEach((sendEvent) => {
respList.push(responseBuilderSimple(sendEvent, operationAudienceId));
});
Expand All @@ -258,7 +226,24 @@
const process = (event) => processEvent(event.message, event.destination);

const processRouterDest = async (inputs, reqMetadata) => {
const respList = await simpleProcessRouterDest(inputs, process, reqMetadata);
const respList = [];
const groupedInputs = lodash.groupBy(inputs, (input) => input.message.type?.toLowerCase());
let transformedRecordEvent = [];
let transformedAudienceEvent = [];

if (groupedInputs.record) {
transformedRecordEvent = await processRecordInputs(groupedInputs.record, reqMetadata);

Check warning on line 235 in src/v0/destinations/fb_custom_audience/transform.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transform.js#L235

Added line #L235 was not covered by tests
}

if (groupedInputs.audiencelist) {
transformedAudienceEvent = await simpleProcessRouterDest(
groupedInputs.audiencelist,
process,
reqMetadata,
);
}

ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
respList.push(...transformedRecordEvent, ...transformedAudienceEvent);
return flattenMap(respList);
};

Expand Down
249 changes: 249 additions & 0 deletions src/v0/destinations/fb_custom_audience/transformV2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
/* eslint-disable no-const-assign */
const lodash = require('lodash');
const get = require('get-value');
const {
InstrumentationError,
ConfigurationError,
TransformationError,
} = require('@rudderstack/integrations-lib');
const { schemaFields, typeFields, subTypeFields, getEndPoint } = require('./config');
const { MappedToDestinationKey } = require('../../../constants');
const stats = require('../../../util/stats');
const {
getDestinationExternalIDInfoForRetl,
isDefinedAndNotNullAndNotEmpty,
checkSubsetOfArray,
defaultRequestConfig,
returnArrayOfSubarrays,
defaultPostRequestConfig,
defaultDeleteRequestConfig,
} = require('../../util');
const {
ensureApplicableFormat,
getUpdatedDataElement,
getSchemaForEventMappedToDest,
batchingWithPayloadSize,
} = require('./util');

const responseBuilderSimple = (payload, audienceId) => {
if (payload) {
const responseParams = payload.responseField;
const response = defaultRequestConfig();
response.endpoint = getEndPoint(audienceId);

if (payload.operationCategory === 'add') {
response.method = defaultPostRequestConfig.requestMethod;
}
if (payload.operationCategory === 'remove') {
response.method = defaultDeleteRequestConfig.requestMethod;
}

response.params = responseParams;
return response;
}
// fail-safety for developer error
throw new TransformationError(`Payload could not be constructed`);

Check warning on line 45 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L45

Added line #L45 was not covered by tests
};

const processRecordEventArray = (
recordChunksArray,
userSchema,
isHashRequired,
disableFormat,
paramsPayload,
prepareParams,
destination,
operation,
) => {
const toSendEvents = [];
recordChunksArray.forEach((recordArray) => {
const data = [];
recordArray.forEach((input) => {
const { fields } = input.message;
let dataElement = [];
let nullUserData = true;

Check warning on line 64 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L57-L64

Added lines #L57 - L64 were not covered by tests

userSchema.forEach((eachProperty) => {
const userProperty = fields[eachProperty];
let updatedProperty = userProperty;

Check warning on line 68 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L66-L68

Added lines #L66 - L68 were not covered by tests

if (isHashRequired && !disableFormat) {
updatedProperty = ensureApplicableFormat(eachProperty, userProperty);

Check warning on line 71 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L71

Added line #L71 was not covered by tests
}

dataElement = getUpdatedDataElement(

Check warning on line 74 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L74

Added line #L74 was not covered by tests
dataElement,
isHashRequired,
eachProperty,
updatedProperty,
);

if (dataElement[dataElement.length - 1]) {
nullUserData = false;

Check warning on line 82 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L82

Added line #L82 was not covered by tests
}
});

if (nullUserData) {
stats.increment('fb_custom_audience_event_having_all_null_field_values_for_a_user', {

Check warning on line 87 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L87

Added line #L87 was not covered by tests
destinationId: destination.ID,
nullFields: userSchema,
});
}

data.push(dataElement);

Check warning on line 93 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L93

Added line #L93 was not covered by tests
});

const prepareFinalPayload = lodash.cloneDeep(paramsPayload);
prepareFinalPayload.schema = userSchema;
prepareFinalPayload.data = data;
const payloadBatches = batchingWithPayloadSize(prepareFinalPayload);

Check warning on line 99 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L96-L99

Added lines #L96 - L99 were not covered by tests

payloadBatches.forEach((payloadBatch) => {
const response = {

Check warning on line 102 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L101-L102

Added lines #L101 - L102 were not covered by tests
...prepareParams,
payload: payloadBatch,
};
const wrappedResponse = {

Check warning on line 106 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L106

Added line #L106 was not covered by tests
responseField: response,
operationCategory: operation,
};
toSendEvents.push(wrappedResponse);

Check warning on line 110 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L110

Added line #L110 was not covered by tests
});
});

return toSendEvents;

Check warning on line 114 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L114

Added line #L114 was not covered by tests
};

async function processRecordInputs(groupedRecordInputs) {
const { destination } = groupedRecordInputs[0];
const { message } = groupedRecordInputs[0];

Check warning on line 119 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L117-L119

Added lines #L117 - L119 were not covered by tests
const { isHashRequired, accessToken, disableFormat, type, subType, isRaw, maxUserCount } =
destination.Config;
const prepareParams = {

Check warning on line 122 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L121-L122

Added lines #L121 - L122 were not covered by tests
access_token: accessToken,
};

// maxUserCount validation
const maxUserCountNumber = parseInt(maxUserCount, 10);

Check warning on line 127 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L127

Added line #L127 was not covered by tests
if (Number.isNaN(maxUserCountNumber)) {
throw new ConfigurationError('Batch size must be an Integer.');

Check warning on line 129 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L129

Added line #L129 was not covered by tests
}

// audience id validation
const { audienceId } = destination.Config;
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
let operationAudienceId = audienceId;
const mappedToDestination = get(message, MappedToDestinationKey);

Check warning on line 135 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L133-L135

Added lines #L133 - L135 were not covered by tests
if (!operationAudienceId && mappedToDestination) {
const { objectType } = getDestinationExternalIDInfoForRetl(message, 'FB_CUSTOM_AUDIENCE');
operationAudienceId = objectType;

Check warning on line 138 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L137-L138

Added lines #L137 - L138 were not covered by tests
}
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved
if (!isDefinedAndNotNullAndNotEmpty(operationAudienceId)) {
throw new ConfigurationError('Audience ID is a mandatory field');

Check warning on line 141 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L141

Added line #L141 was not covered by tests
}

// user schema validation
let { userSchema } = destination.Config;

Check warning on line 145 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L145

Added line #L145 was not covered by tests
if (mappedToDestination) {
userSchema = getSchemaForEventMappedToDest(message);

Check warning on line 147 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L147

Added line #L147 was not covered by tests
}
if (!Array.isArray(userSchema)) {
userSchema = [userSchema];

Check warning on line 150 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L150

Added line #L150 was not covered by tests
}
if (!checkSubsetOfArray(schemaFields, userSchema)) {
throw new ConfigurationError('One or more of the schema fields are not supported');

Check warning on line 153 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L153

Added line #L153 was not covered by tests
}

const paramsPayload = {};
const dataSource = {};

Check warning on line 157 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L156-L157

Added lines #L156 - L157 were not covered by tests
if (isRaw) {
paramsPayload.is_raw = isRaw;

Check warning on line 159 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L159

Added line #L159 was not covered by tests
}
if (type && type !== 'NA' && typeFields.includes(type)) {
dataSource.type = type;

Check warning on line 162 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L162

Added line #L162 was not covered by tests
}
if (subType && subType !== 'NA' && subTypeFields.includes(subType)) {
dataSource.sub_type = subType;

Check warning on line 165 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L165

Added line #L165 was not covered by tests
}
if (Object.keys(dataSource).length > 0) {
paramsPayload.data_source = dataSource;

Check warning on line 168 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L168

Added line #L168 was not covered by tests
}
ItsSudip marked this conversation as resolved.
Show resolved Hide resolved

const groupedRecordsByAction = lodash.groupBy(groupedRecordInputs, (record) =>
record.message.action?.toLowerCase(),

Check warning on line 172 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L171-L172

Added lines #L171 - L172 were not covered by tests
);

const toSendEvents = [];

Check warning on line 175 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L175

Added line #L175 was not covered by tests

if (groupedRecordsByAction.delete) {
const deleteRecordChunksArray = returnArrayOfSubarrays(

Check warning on line 178 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L178

Added line #L178 was not covered by tests
groupedRecordsByAction.delete,
maxUserCountNumber,
);
toSendEvents.push(

Check warning on line 182 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L182

Added line #L182 was not covered by tests
...processRecordEventArray(
deleteRecordChunksArray,
userSchema,
isHashRequired,
disableFormat,
paramsPayload,
prepareParams,
destination,
'remove',
),
);
}

if (groupedRecordsByAction.insert) {
const insertRecordChunksArray = returnArrayOfSubarrays(

Check warning on line 197 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L197

Added line #L197 was not covered by tests
groupedRecordsByAction.insert,
maxUserCountNumber,
);
toSendEvents.push(

Check warning on line 201 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L201

Added line #L201 was not covered by tests
...processRecordEventArray(
insertRecordChunksArray,
userSchema,
isHashRequired,
disableFormat,
paramsPayload,
prepareParams,
destination,
'add',
),
);
}

if (groupedRecordsByAction.update) {
const updateRecordChunksArray = returnArrayOfSubarrays(

Check warning on line 216 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L216

Added line #L216 was not covered by tests
groupedRecordsByAction.update,
maxUserCountNumber,
);
toSendEvents.push(

Check warning on line 220 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L220

Added line #L220 was not covered by tests
...processRecordEventArray(
updateRecordChunksArray,
userSchema,
isHashRequired,
disableFormat,
paramsPayload,
prepareParams,
destination,
'add',
),
);
}

const respList = [];
toSendEvents.forEach((sendEvent) => {
respList.push(responseBuilderSimple(sendEvent, operationAudienceId));

Check warning on line 236 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L234-L236

Added lines #L234 - L236 were not covered by tests
});
if (respList.length === 0) {
throw new InstrumentationError(

Check warning on line 239 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L239

Added line #L239 was not covered by tests
'Missing valid parameters, unable to generate transformed payload',
);
}
return respList;

Check warning on line 243 in src/v0/destinations/fb_custom_audience/transformV2.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/fb_custom_audience/transformV2.js#L243

Added line #L243 was not covered by tests
}

module.exports = {
processRecordInputs,
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
responseBuilderSimple,
};
8 changes: 7 additions & 1 deletion src/v0/destinations/fb_custom_audience/util.js
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,10 @@ const prepareDataField = (
return data;
};

module.exports = { prepareDataField, getSchemaForEventMappedToDest, batchingWithPayloadSize };
module.exports = {
prepareDataField,
getSchemaForEventMappedToDest,
batchingWithPayloadSize,
krishna2020 marked this conversation as resolved.
Show resolved Hide resolved
ensureApplicableFormat,
getUpdatedDataElement,
};
Loading