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

chore(release): pull hotfix-release/v1.85.1 into main #3898

Merged
merged 5 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [1.85.1](https://github.com/rudderlabs/rudder-transformer/compare/v1.85.0...v1.85.1) (2024-11-21)


### Bug Fixes

* braze subscription batch size ([#3897](https://github.com/rudderlabs/rudder-transformer/issues/3897)) ([ca71a31](https://github.com/rudderlabs/rudder-transformer/commit/ca71a318e4d8d098116fe539964b699254f58617))
* stringifying session ID for airship ([#3896](https://github.com/rudderlabs/rudder-transformer/issues/3896)) ([bb0b9dc](https://github.com/rudderlabs/rudder-transformer/commit/bb0b9dc1e5a56e8141c6cb56e89835ba61ee7761))

## [1.85.0](https://github.com/rudderlabs/rudder-transformer/compare/v1.84.0...v1.85.0) (2024-11-18)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rudder-transformer",
"version": "1.85.0",
"version": "1.85.1",
"description": "",
"homepage": "https://github.com/rudderlabs/rudder-transformer#readme",
"bugs": {
Expand Down
5 changes: 4 additions & 1 deletion src/v0/destinations/airship/data/airshipTrackConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
{
"destKey": "session_id",
"sourceKeys": ["properties.sessionId", "context.sessionId"],
"required": false
"required": false,
"metadata": {
"type": "toString"
}
},
{
"destKey": "transaction",
Expand Down
12 changes: 11 additions & 1 deletion src/v0/destinations/airship/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,20 @@
extractCustomFields,
isEmptyObject,
simpleProcessRouterDest,
convertToUuid,
} = require('../../util');
const { JSON_MIME_TYPE } = require('../../util/constant');
const { transformSessionId } = require('./utils');

const DEFAULT_ACCEPT_HEADER = 'application/vnd.urbanairship+json; version=3';

const transformSessionId = (rawSessionId) => {
try {
return convertToUuid(rawSessionId);
} catch (error) {
throw new InstrumentationError(`Failed to transform session ID: ${error.message}`);

Check warning on line 35 in src/v0/destinations/airship/transform.js

View check run for this annotation

Codecov / codecov/patch

src/v0/destinations/airship/transform.js#L35

Added line #L35 was not covered by tests
}
};

const identifyResponseBuilder = (message, { Config }) => {
const tagPayload = constructPayload(message, identifyMapping);
const { apiKey, dataCenter } = Config;
Expand Down Expand Up @@ -129,6 +137,8 @@

name = name.toLowerCase();
const payload = constructPayload(message, trackMapping);

// ref : https://docs.airship.com/api/ua/#operation-api-custom-events-post
if (isDefinedAndNotNullAndNotEmpty(payload.session_id)) {
payload.session_id = transformSessionId(payload.session_id);
}
Expand Down
12 changes: 0 additions & 12 deletions src/v0/destinations/airship/utils.js

This file was deleted.

21 changes: 12 additions & 9 deletions src/v0/destinations/braze/braze.util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ describe('processBatch', () => {

// Assert that the response is as expected
expect(result.length).toBe(1); // One successful batched request and one failure response
expect(result[0].batchedRequest.length).toBe(6); // Two batched requests
expect(result[0].batchedRequest.length).toBe(8); // Two batched requests
expect(result[0].batchedRequest[0].body.JSON.partner).toBe('RudderStack'); // Verify partner name
expect(result[0].batchedRequest[0].body.JSON.attributes.length).toBe(75); // First batch contains 75 attributes
expect(result[0].batchedRequest[0].body.JSON.events.length).toBe(75); // First batch contains 75 events
Expand All @@ -981,10 +981,12 @@ describe('processBatch', () => {
expect(result[0].batchedRequest[1].body.JSON.attributes.length).toBe(25); // Second batch contains remaining 25 attributes
expect(result[0].batchedRequest[1].body.JSON.events.length).toBe(25); // Second batch contains remaining 25 events
expect(result[0].batchedRequest[1].body.JSON.purchases.length).toBe(25); // Second batch contains remaining 25 purchases
expect(result[0].batchedRequest[2].body.JSON.subscription_groups.length).toBe(50); // First batch contains 50 subscription group
expect(result[0].batchedRequest[3].body.JSON.subscription_groups.length).toBe(50); // First batch contains 25 subscription group
expect(result[0].batchedRequest[4].body.JSON.merge_updates.length).toBe(50); // First batch contains 50 merge_updates
expect(result[0].batchedRequest[5].body.JSON.merge_updates.length).toBe(50); // First batch contains 25 merge_updates
expect(result[0].batchedRequest[2].body.JSON.subscription_groups.length).toBe(25); // First batch contains 50 subscription group
expect(result[0].batchedRequest[3].body.JSON.subscription_groups.length).toBe(25);
expect(result[0].batchedRequest[4].body.JSON.subscription_groups.length).toBe(25); // First batch contains 50 subscription group
expect(result[0].batchedRequest[5].body.JSON.subscription_groups.length).toBe(25); // First batch contains 25 subscription group
expect(result[0].batchedRequest[6].body.JSON.merge_updates.length).toBe(50); // First batch contains 50 merge_updates
expect(result[0].batchedRequest[7].body.JSON.merge_updates.length).toBe(50); // First batch contains 25 merge_updates
});

test('processBatch handles more than 75 attributes, events, and purchases with non uniform distribution', () => {
Expand Down Expand Up @@ -1093,7 +1095,7 @@ describe('processBatch', () => {
// Assert that the response is as expected
expect(result.length).toBe(1); // One successful batched request and one failure response
expect(result[0].metadata.length).toBe(490); // Check the total length is same as input jobs (120 + 160 + 100 + 70 +40)
expect(result[0].batchedRequest.length).toBe(6); // Two batched requests
expect(result[0].batchedRequest.length).toBe(7); // Two batched requests
expect(result[0].batchedRequest[0].body.JSON.partner).toBe('RudderStack'); // Verify partner name
expect(result[0].batchedRequest[0].body.JSON.attributes.length).toBe(75); // First batch contains 75 attributes
expect(result[0].batchedRequest[0].body.JSON.events.length).toBe(75); // First batch contains 75 events
Expand All @@ -1103,9 +1105,10 @@ describe('processBatch', () => {
expect(result[0].batchedRequest[1].body.JSON.events.length).toBe(45); // Second batch contains remaining 45 events
expect(result[0].batchedRequest[1].body.JSON.purchases.length).toBe(75); // Second batch contains remaining 75 purchases
expect(result[0].batchedRequest[2].body.JSON.purchases.length).toBe(10); // Third batch contains remaining 10 purchases
expect(result[0].batchedRequest[3].body.JSON.subscription_groups.length).toBe(50); // First batch contains 50 subscription group
expect(result[0].batchedRequest[4].body.JSON.subscription_groups.length).toBe(20); // First batch contains 20 subscription group
expect(result[0].batchedRequest[5].body.JSON.merge_updates.length).toBe(40); // First batch contains 50 merge_updates
expect(result[0].batchedRequest[3].body.JSON.subscription_groups.length).toBe(25); // First batch contains 25 subscription group
expect(result[0].batchedRequest[4].body.JSON.subscription_groups.length).toBe(25); // Second batch contains 25 subscription group
expect(result[0].batchedRequest[5].body.JSON.subscription_groups.length).toBe(20); // Third batch contains 20 subscription group
expect(result[0].batchedRequest[6].body.JSON.merge_updates.length).toBe(40); // First batch contains 50 merge_updates
});

test('check success and failure scenarios both for processBatch', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/v0/destinations/braze/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const IDENTIFY_BRAZE_MAX_REQ_COUNT = 50;
// https://www.braze.com/docs/api/endpoints/user_data/post_user_delete/

const ALIAS_BRAZE_MAX_REQ_COUNT = 50;
const SUBSCRIPTION_BRAZE_MAX_REQ_COUNT = 50;
const SUBSCRIPTION_BRAZE_MAX_REQ_COUNT = 25;

const DEL_MAX_BATCH_SIZE = 50;
const DESTINATION = 'braze';
Expand Down
25 changes: 25 additions & 0 deletions src/v0/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const uaParser = require('ua-parser-js');
const moment = require('moment-timezone');
const sha256 = require('sha256');
const crypto = require('crypto');
const { v5 } = require('uuid');
const {
InstrumentationError,
BaseError,
Expand Down Expand Up @@ -2330,6 +2331,29 @@ const isEventSentByVDMV1Flow = (event) => event?.message?.context?.mappedToDesti

const isEventSentByVDMV2Flow = (event) =>
event?.connection?.config?.destination?.schemaVersion === VDM_V2_SCHEMA_VERSION;

const convertToUuid = (input) => {
const NAMESPACE = v5.DNS;

if (!isDefinedAndNotNull(input)) {
throw new InstrumentationError('Input is undefined or null.');
}

try {
// Stringify and trim the input
const trimmedInput = String(input).trim();

// Check for empty input after trimming
if (!trimmedInput) {
throw new InstrumentationError('Input is empty or invalid.');
}
// Generate and return UUID
return v5(trimmedInput, NAMESPACE);
} catch (error) {
const errorMessage = `Failed to transform input to uuid: ${error.message}`;
throw new InstrumentationError(errorMessage);
}
};
// ========================================================================
// EXPORTS
// ========================================================================
Expand Down Expand Up @@ -2456,4 +2480,5 @@ module.exports = {
getRelativePathFromURL,
removeEmptyKey,
isAxiosError,
convertToUuid,
};
64 changes: 64 additions & 0 deletions src/v0/util/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { InstrumentationError } = require('@rudderstack/integrations-lib');
const utilities = require('.');
const { getFuncTestData } = require('../../../test/testHelper');
const { FilteredEventsError } = require('./errorTypes');
const { v5 } = require('uuid');
const {
hasCircularReference,
flattenJson,
Expand All @@ -11,6 +12,7 @@ const {
groupRouterTransformEvents,
isAxiosError,
removeHyphens,
convertToUuid,
} = require('./index');
const exp = require('constants');

Expand Down Expand Up @@ -985,3 +987,65 @@ describe('removeHyphens', () => {
});
});
});

describe('convertToUuid', () => {
const NAMESPACE = v5.DNS;

test('should generate UUID for valid string input', () => {
const input = 'testInput';
const expectedUuid = '7ba1e88f-acf9-5528-9c1c-0c897ed80e1e';
const result = convertToUuid(input);
expect(result).toBe(expectedUuid);
});

test('should generate UUID for valid numeric input', () => {
const input = 123456;
const expectedUuid = 'a52b2702-9bcf-5701-852a-2f4edc640fe1';
const result = convertToUuid(input);
expect(result).toBe(expectedUuid);
});

test('should trim spaces and generate UUID', () => {
const input = ' testInput ';
const expectedUuid = '7ba1e88f-acf9-5528-9c1c-0c897ed80e1e';
const result = convertToUuid(input);
expect(result).toBe(expectedUuid);
});

test('should throw an error for empty input', () => {
const input = '';
expect(() => convertToUuid(input)).toThrow(InstrumentationError);
expect(() => convertToUuid(input)).toThrow('Input is empty or invalid.');
});

test('to throw an error for null input', () => {
const input = null;
expect(() => convertToUuid(input)).toThrow(InstrumentationError);
expect(() => convertToUuid(input)).toThrow('Input is undefined or null');
});

test('to throw an error for undefined input', () => {
const input = undefined;
expect(() => convertToUuid(input)).toThrow(InstrumentationError);
expect(() => convertToUuid(input)).toThrow('Input is undefined or null');
});

test('should throw an error for input that is whitespace only', () => {
const input = ' ';
expect(() => convertToUuid(input)).toThrow(InstrumentationError);
expect(() => convertToUuid(input)).toThrow('Input is empty or invalid.');
});

test('should handle long string input gracefully', () => {
const input = 'a'.repeat(1000);
const expectedUuid = v5(input, NAMESPACE);
const result = convertToUuid(input);
expect(result).toBe(expectedUuid);
});

test('any invalid input if stringified does not throw error', () => {
const input = {};
const result = convertToUuid(input);
expect(result).toBe('672ca00c-37f4-5d71-b8c3-6ae0848080ec');
});
});
Loading
Loading