diff --git a/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/__snapshots__/tablemaintutilities.test.ts.snap b/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/__snapshots__/tablemaintutilities.test.ts.snap deleted file mode 100644 index 0554247d23..0000000000 --- a/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/__snapshots__/tablemaintutilities.test.ts.snap +++ /dev/null @@ -1,7 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`checkRTExist checkRTExist should return expected output 1`] = `[Function]`; - -exports[`createSegmentEventsTable createSegmentEventsTable should return expected output 1`] = `[Function]`; - -exports[`preChecksAndMaint preChecksAndMaint should return expected output 1`] = `[Function]`; diff --git a/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/tablemaintutilities.test.ts b/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/tablemaintutilities.test.ts index a1e2f30744..356e365b39 100644 --- a/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/tablemaintutilities.test.ts +++ b/packages/destination-actions/src/destinations/acoustic/Utility/__tests__/tablemaintutilities.test.ts @@ -3,8 +3,7 @@ // import get from 'lodash/get' // import { Settings } from '../../generated-types' import nock from 'nock' -import { preChecksAndMaint, createSegmentEventsTable, checkRTExist } from '../tablemaintutilities' -import { getAuthCreds, getEventTableListId, getAccessToken, doPOST } from '../tablemaintutilities' +import { getAuthCreds, getAccessToken, doPOST } from '../tablemaintutilities' //import { IntegrationError, OAuth2ClientCredentials, RefreshAccessTokenResult, RetryableError } from '@segment/actions-core' //import { RequestClient } from '@segment/actions-core' @@ -21,77 +20,8 @@ jest.mock('../../generated-types') const accessPoint = nock('https://api-campaign-us-2.goacoustic.com').post('/XMLAPI').reply(200) accessPoint.isDone -describe('preChecksAndMaint', () => { - it('should be present', () => { - expect(preChecksAndMaint).toBeDefined() - }) - - it('preChecksAndMaint should return expected output', async () => { - // const retValue = await preChecksAndMaint(request,settings); - expect(preChecksAndMaint).toMatchSnapshot() - }) -}) - -describe('createSegmentEventsTable', () => { - it('should expose a function', () => { - expect(createSegmentEventsTable).toBeDefined() - }) - - it('createSegmentEventsTable should return expected output', async () => { - // const retValue = await createSegmentEventsTable(request,settings,auth); - expect(createSegmentEventsTable).toMatchSnapshot() - }) -}) - -describe('checkRTExist', () => { - afterAll(nock.restore) - afterEach(nock.cleanAll) - - it('should expose a function', () => { - expect(checkRTExist).toBeDefined() - }) - - it('checkRTExist should return expected output', async () => { - const settings = { - a_pod: '2', - a_region: 'US' - } - - const accessToken = '' - - // nock.recorder.rec() - nock.back.setMode('record') - - const checkResult = nock(`https://api-campaign-${settings.a_region}-${settings.a_pod}.goacoustic.com`, { - reqheaders: { - Authorization: `Bearer ${accessToken}`, - 'Content-Type': 'text/xml', - 'user-agent': 'Segment (checkforRT)', - Connection: 'keep-alive', - 'Accept-Encoding': 'gzip, deflate, br', - Accept: '*/*' - } - }) - .persist() - .post( - '/XMLAPI', - ` - - - 1 - 15 - True - - - ` - ) //, body => body.username && body.password - .reply(200, {}) - - checkResult.isDone - - expect(checkRTExist).toMatchSnapshot() - }) -}) +// nock.recorder.rec() +nock.back.setMode('record') describe('getAuthCreds', () => { it('should expose a function', () => { @@ -103,16 +33,7 @@ describe('getAuthCreds', () => { expect(false) //.toBeTruthy(); }) }) -describe('getEventTableListId', () => { - it('should expose a function', () => { - expect(getEventTableListId).toBeDefined() - }) - it('getEventTableListId should return expected output', () => { - // const retValue = getEventTableListId(); - expect(false) //.toBeTruthy(); - }) -}) describe('getAccessToken', () => { it('should expose a function', () => { expect(getAccessToken).toBeDefined() diff --git a/packages/destination-actions/src/destinations/acoustic/Utility/eventprocessing.ts b/packages/destination-actions/src/destinations/acoustic/Utility/eventprocessing.ts index 45de9351a9..9914c9fc17 100644 --- a/packages/destination-actions/src/destinations/acoustic/Utility/eventprocessing.ts +++ b/packages/destination-actions/src/destinations/acoustic/Utility/eventprocessing.ts @@ -78,14 +78,6 @@ export function addUpdateEvents(payload: Payload, email: string, limit: number) ...propertiesTraitsKV, ...parseSections(payload.context as { [key: string]: string }, 0) } - - if (Object.keys(propertiesTraitsKV).length > limit) { - throw new IntegrationError( - 'Properties Exceed Max. Use Mapping to limit the number of Attributes (Properties, Traits) present and thereby reduce the Campaign Relational Table Rows consumed.', - 'EXCEEDS_MAX_PROPERTIES_MAX', - 400 - ) - } } catch (e) { throw new IntegrationError( 'Unexpected Exception processing payload \n ${e}', @@ -94,6 +86,17 @@ export function addUpdateEvents(payload: Payload, email: string, limit: number) ) } + //Check Size - Number of Attributes + const l = Object.keys(propertiesTraitsKV).length + if (l > limit) { + throw new IntegrationError( + `There are ${l} Attributes in this Event. This exceeds the max of ${limit}. Use Mapping to limit the number of Attributes and thereby reduce the Campaign Relational Table Rows consumed.`, + 'EXCEEDS_MAX_PROPERTIES_MAX', + 400 + ) + } + + //Audience // Identify events generated by an audience have the audience key set to true or false based on whether the user is entering or exiting the audience: // { // "type": "identify", @@ -115,7 +118,7 @@ export function addUpdateEvents(payload: Payload, email: string, limit: number) let ak = '' let av = '' - //Audience + const getValue = (o: object, part: string) => Object.entries(o).find(([k, _v]) => k.includes(part))?.[1] if (getValue(propertiesTraitsKV, 'computation_class')) { diff --git a/packages/destination-actions/src/destinations/acoustic/Utility/tablemaintutilities.ts b/packages/destination-actions/src/destinations/acoustic/Utility/tablemaintutilities.ts index 3cca7210da..0c3fc4bf07 100644 --- a/packages/destination-actions/src/destinations/acoustic/Utility/tablemaintutilities.ts +++ b/packages/destination-actions/src/destinations/acoustic/Utility/tablemaintutilities.ts @@ -8,7 +8,7 @@ import { RequestClient } from '@segment/actions-core' import { Settings } from '../generated-types' import { AuthTokens } from '@segment/actions-core/src/destination-kit/parse-settings' -export let eventTableListId = '' +// export let eventTableListId = '' export interface accessResp { access_token: string token_type: string @@ -48,10 +48,6 @@ export function getAuthCreds() { return authCreds } -export function getEventTableListId() { - return eventTableListId -} - export async function getAccessToken( request: RequestClient, settings: Settings @@ -65,7 +61,6 @@ export async function getAccessToken( authCreds.refreshTokenUrl = `https://api-campaign-${settings.region}-${settings.pod}.goacoustic.com/oauth/token` const requestAToken = await request(authCreds.refreshTokenUrl, { - //return await request(authCreds.refreshTokenUrl, { method: 'POST', body: new URLSearchParams({ refresh_token: authCreds.refreshToken, @@ -105,6 +100,8 @@ export async function doPOST( } let resultTxt = '' + let res = '' + try { const postResults = await request(`https://api-campaign-${settings.region}-${settings.pod}.goacoustic.com/XMLAPI`, { method: 'POST', @@ -118,150 +115,23 @@ export async function doPOST( }, body: `${body}` }) - const res = await postResults.data - - //check for success, hard fails throw error, soft fails throw retryable error - resultTxt = res as string - if (resultTxt.indexOf('FALSE') > -1 || resultTxt.indexOf('false') > -1) { - const rx = /(.*)<\/FaultString>/gm - const r = rx.exec(resultTxt) as RegExpExecArray - if (r.indexOf('max number of concurrent') > -1) - throw new RetryableError( - 'Currently exceeding Max number of concurrent authenticated requests via API, retrying', - 429 - ) - resultTxt = '' - } + res = (await postResults.data) as string } catch (e) { throw new IntegrationError(`Unexpected Request Exception \n${e}`, 'UNEXPECTED_REQUEST_EXCEPTION', 400) } - return resultTxt -} - -export async function preChecksAndMaint(request: RequestClient, settings: Settings, auth: AuthTokens) { - //check for Segment Events table, if not exist create it - eventTableListId = await checkRTExist(request, settings, auth) - - if (eventTableListId === '') { - const crt = await createSegmentEventsTable(request, settings, auth) - if (!crt) { - throw new IntegrationError( - 'Error attempting to create the Acoustic Segment Events Table', - 'CANNOT_CREATE_EVENTS_TABLE', - 400 - ) - } - } - return eventTableListId -} - -export async function checkRTExist(request: RequestClient, settings: Settings, auth: AuthTokens) { - if (settings.tableListId != '') { - const checkDefinedTableId = ` - - ${settings.tableListId} - - ` - const respText = (await doPOST(request, settings, auth, checkDefinedTableId, 'CheckDefinedTable')) ?? '' - - const rx = /TRUE<\/SUCCESS>(?:\s)*(.*)<\/ID/gm - if (respText != null) { - const r = rx.exec(respText) - if (r) eventTableListId = r[1] - else - throw new IntegrationError( - 'Defined Events Table List Id is invalid, please refer to documentation to configure the Segment Events Table in Acoustic', - 'INVALID_LIST_ID', - 400 - ) - } - } else { - const getTableList = ` - - - 1 - 15 - True - - - ` - - const respText = (await doPOST(request, settings, auth, getTableList, 'GetTableList')) ?? '' - - const lists = respText - - if (lists.indexOf('Segment Events Table') > 0) { - const simplify = lists.substring( - lists.indexOf('Segment Events Table') - 40, - lists.indexOf('Segment Events Table') + 40 - ) - const rx = /(.*)<\/ID>/gm - const setListId = rx.exec(simplify) ?? '999999999' - - eventTableListId = setListId[1] - } else { - eventTableListId = '999999999' //Make it obvious - should not be 999999999 - - throw new IntegrationError( - `Cannot determine the Segment Events Table in the defined Acoustic environment. Please check the documentation and confirm the configuration`, - 'CANNOT_DETERMINE_EVENTS_TABLE', - 400 + //check for success, hard fails throw error, soft fails throw retryable error + resultTxt = res + if (resultTxt.indexOf('FALSE') > -1 || resultTxt.indexOf('false') > -1) { + const rx = /(.*)<\/FaultString>/gm + const r = rx.exec(resultTxt) as RegExpExecArray + if (r[1].indexOf('max number of concurrent') > -1) + throw new RetryableError( + 'Currently exceeding Max number of concurrent authenticated requests via API, retrying', + 429 ) - } + resultTxt = '' } - return eventTableListId -} - -export async function createSegmentEventsTable(request: RequestClient, settings: Settings, auth: AuthTokens) { - const createSET = ` - - - ${settings.tableName} - - - EmailId - EMAIL - true - TRUE - - - EventSource - TEXT - TRUE - FALSE - - - EventName - TEXT - TRUE - TRUE - - - EventValue - TEXT - TRUE - FALSE - - - EventTimestamp - DATE_TIME - TRUE - FALSE - - - - - ` - const cset = (await doPOST(request, settings, auth, createSET, 'CreateSegmentEventsTable')) ?? '' - - const rx = /TRUE<\/SUCCESS>(?:\s)*(.*)<\/TABLE_ID/gm - let tid = '' - if (cset != null) { - const r = rx.exec(cset) - if (r) tid = r[1] - } - eventTableListId = tid - return eventTableListId + return resultTxt } diff --git a/packages/destination-actions/src/destinations/acoustic/__tests__/__snapshots__/snapshot.test.ts.snap b/packages/destination-actions/src/destinations/acoustic/__tests__/__snapshots__/snapshot.test.ts.snap index d99e7c21bf..4db1b167bd 100644 --- a/packages/destination-actions/src/destinations/acoustic/__tests__/__snapshots__/snapshot.test.ts.snap +++ b/packages/destination-actions/src/destinations/acoustic/__tests__/__snapshots__/snapshot.test.ts.snap @@ -1,18 +1,38 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Testing snapshot for actions-acoustic-campaign destination: receiveEvents action - all fields 1`] = ` -" - - lLhce#$[oZh - +" + + + lLhce#$[oZh + + + + + + + + + + + + + + + + + " `; exports[`Testing snapshot for actions-acoustic-campaign destination: receiveEvents action - required fields 1`] = ` -" - - lLhce#$[oZh - +" + + + lLhce#$[oZh + + + " `; @@ -35,7 +55,7 @@ Headers { "text/xml", ], "user-agent": Array [ - "Segment Action (Acoustic Destination) CheckDefinedTable", + "Segment Action (Acoustic Destination) POST_Updates", ], }, } diff --git a/packages/destination-actions/src/destinations/acoustic/receiveEvents/index.ts b/packages/destination-actions/src/destinations/acoustic/receiveEvents/index.ts index e56f728c43..3fe3400614 100644 --- a/packages/destination-actions/src/destinations/acoustic/receiveEvents/index.ts +++ b/packages/destination-actions/src/destinations/acoustic/receiveEvents/index.ts @@ -1,7 +1,7 @@ import { ActionDefinition } from '@segment/actions-core' import { Settings } from '../generated-types' import { Payload } from './generated-types' -import { doPOST, preChecksAndMaint, getAuthCreds } from '../Utility/tablemaintutilities' +import { doPOST, getAuthCreds } from '../Utility/tablemaintutilities' import get from 'lodash/get' import { addUpdateEvents } from '../Utility/eventprocessing' import { AuthTokens } from '@segment/actions-core/src/destination-kit/parse-settings' @@ -76,19 +76,16 @@ const action: ActionDefinition = { perform: async (request, { settings, payload, auth }) => { const email = get(payload, 'email', '') - - const tableId = await preChecksAndMaint(request, settings, auth as AuthTokens) - - //Ok, prechecks and Maint are all accomplished, let's see what needs to be processed, + //Parse Event-Payload into an Update const rows = addUpdateEvents(payload, email, settings.attributesMax as number) let a_Auth = {} - if (!auth) a_Auth = getAuthCreds() + if (!auth?.accessToken) a_Auth = getAuthCreds() const POSTUpdates = ` - ${tableId} + ${settings.tableListId} ${rows}