Skip to content

Commit

Permalink
fix(@aws-amplify/analytics)!: do not attempt to delete unused endpoin…
Browse files Browse the repository at this point in the history
…ts (aws-amplify#7245)

BREAKING CHANGE: Analytics will no longer attempt to automatically delete old endpoints on updateEndpoint
  • Loading branch information
iartemiev authored and CryogenicPlanet committed Jan 20, 2021
1 parent c0ecd11 commit 3797bb3
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -749,33 +749,17 @@ describe('AnalyticsProvider test', () => {
// Reject with error the first time we execute updateEndpoint
.mockImplementationOnce(async params => {
throw mockExceededMaxError;
})
// Succeed on the second attempt (i.e. after we go through _retryEndpointUpdate)
.mockImplementationOnce(async params => {
return 'data';
});

jest
.spyOn(Credentials, 'get')
.mockImplementationOnce(() => Promise.resolve(credentials));

jest
.spyOn(AnalyticsProvider.prototype, '_removeUnusedEndpoints')
.mockImplementationOnce(() => ({
promise: jest.fn().mockResolvedValue(true),
}));

const spyonRetryEndpointUpdate = jest.spyOn(
AnalyticsProvider.prototype,
'_retryEndpointUpdate'
);

const params = { event: { name: '_update_endpoint', immediate: true } };

await analytics.record(params, { resolve, reject });

expect(spyonUpdateEndpoint).toHaveBeenCalledTimes(2); // 1 failed + 1 successful call
expect(spyonRetryEndpointUpdate).toHaveBeenCalled();
expect(spyonUpdateEndpoint).toHaveBeenCalledTimes(1);

spyonUpdateEndpoint.mockRestore();
});
Expand Down
104 changes: 3 additions & 101 deletions packages/analytics/src/Providers/AWSPinpointProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import {
ConsoleLogger as Logger,
ClientDevice,
Platform,
Credentials,
Signer,
JS,
Expand All @@ -26,7 +25,6 @@ import {
PutEventsCommand,
PutEventsCommandInput,
UpdateEndpointCommand,
GetUserEndpointsCommand,
} from '@aws-sdk/client-pinpoint';
import { EventsBatch } from '@aws-sdk/client-pinpoint/models';
import Cache from '@aws-amplify/cache';
Expand Down Expand Up @@ -55,7 +53,6 @@ const logger = new Logger('AWSPinpointProvider');
const RETRYABLE_CODES = [429, 500];
const ACCEPTED_CODES = [202];
const FORBIDDEN_CODE = 403;
const BAD_REQUEST_CODE = 400;
const MOBILE_SERVICE_NAME = 'mobiletargeting';
const EXPIRED_TOKEN_CODE = 'ExpiredTokenException';
const UPDATE_ENDPOINT = '_update_endpoint';
Expand Down Expand Up @@ -433,11 +430,9 @@ export class AWSPinpointProvider implements AnalyticsProvider {
const { err, endpointObject } = failureData;
const statusCode = err.$metadata && err.$metadata.httpStatusCode;

logger.debug('updateEndpoint failed', err);
logger.debug('updateEndpoint error', err);

switch (statusCode) {
case BAD_REQUEST_CODE:
return this._handleEndpointUpdateBadRequest(failureData);
case FORBIDDEN_CODE:
return this._handleEndpointUpdateForbidden(failureData);
default:
Expand All @@ -446,41 +441,11 @@ export class AWSPinpointProvider implements AnalyticsProvider {
const exponential = true;
return this._retryEndpointUpdate(endpointObject, exponential);
}
logger.error('updateEndpoint failed', err);
endpointObject.handlers.reject(err);
}
}

private async _handleEndpointUpdateBadRequest(
failureData: EndpointFailureData
) {
const { err, update_params, endpointObject } = failureData;
const { message } = err;
const { ApplicationId, EndpointRequest } = update_params;

if (
!String(message).startsWith('Exceeded maximum endpoint per user count')
) {
return endpointObject.handlers.reject(err);
}

try {
await this._removeUnusedEndpoints(
ApplicationId,
EndpointRequest.User.UserId
);
logger.debug('Removed unused endpoints successfully');
this._retryEndpointUpdate(endpointObject);
} catch (err) {
logger.warn(`Failed to remove unused endpoints with error: ${err}`);
logger.warn(
`Please ensure you have updated your Pinpoint IAM Policy ` +
`with the Action: "mobiletargeting:GetUserEndpoints" ` +
`in order to get endpoints info of the user`
);
return endpointObject.handlers.reject(err);
}
}

private _handleEndpointUpdateForbidden(failureData: EndpointFailureData) {
const { err, endpointObject } = failureData;

Expand Down Expand Up @@ -528,69 +493,6 @@ export class AWSPinpointProvider implements AnalyticsProvider {
}
}

private async _removeUnusedEndpoints(appId, userId) {
try {
// TODO: re-write with Promise (during refactor pt. 2)
const command: GetUserEndpointsCommand = new GetUserEndpointsCommand({
ApplicationId: appId,
UserId: userId,
});
const data = await this.pinpointClient.send(command);
const endpoints = data.EndpointsResponse.Item;
logger.debug(
`get endpoints associated with the userId: ${userId} with data`,
endpoints
);
let endpointToBeDeleted = endpoints[0];
for (let i = 1; i < endpoints.length; i++) {
const timeStamp1 = Date.parse(endpointToBeDeleted['EffectiveDate']);
const timeStamp2 = Date.parse(endpoints[i]['EffectiveDate']);
// delete the one with invalid effective date
if (isNaN(timeStamp1)) break;
if (isNaN(timeStamp2)) {
endpointToBeDeleted = endpoints[i];
break;
}

if (timeStamp2 < timeStamp1) {
endpointToBeDeleted = endpoints[i];
}
}
// update the endpoint's user id with an empty string
const update_params = {
ApplicationId: appId,
EndpointId: endpointToBeDeleted['Id'],
EndpointRequest: {
User: {
UserId: '',
},
},
};

try {
const updateEndPointcommand: UpdateEndpointCommand = new UpdateEndpointCommand(
update_params
);
const updateEndPointData = await this.pinpointClient.send(
updateEndPointcommand
);
logger.debug(
'The old endpoint is updated with an empty string for user id'
);
return updateEndPointData;
} catch (err) {
logger.debug('Failed to update the endpoint', err);
throw err;
}
} catch (err) {
logger.debug(
`Failed to get endpoints associated with the userId: ${userId} with error`,
err
);
throw err;
}
}

/**
* @private
* @param config
Expand Down Expand Up @@ -621,7 +523,7 @@ export class AWSPinpointProvider implements AnalyticsProvider {
credentials,
customUserAgent: getAmplifyUserAgent(),
});

// TODO: remove this middleware once a long term fix is implemented by aws-sdk-js team.
this.pinpointClient.middlewareStack.addRelativeTo(
next => args => {
Expand Down

0 comments on commit 3797bb3

Please sign in to comment.