Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"build": "hedy -v --test-bundle",
"deploy": "hedy -v --deploy --aws-deploy-bucket=spacecat-prod-deploy --pkgVersion=latest",
"deploy-stage": "hedy -v --deploy --aws-deploy-bucket=spacecat-stage-deploy --pkgVersion=latest",
"deploy-dev": "hedy -v --deploy --pkgVersion=latest$CI_BUILD_NUM -l latest --aws-deploy-bucket=spacecat-dev-deploy --cleanup-ci=24h --aws-api vldld6qz1d",
"deploy-dev": "hedy -v --deploy --pkgVersion=latest$CI_BUILD_NUM -l mstoyanov --aws-deploy-bucket=spacecat-dev-deploy --cleanup-ci=24h --aws-api vldld6qz1d",
"deploy-secrets": "hedy --aws-update-secrets --params-file=secrets/secrets.env",
"docs": "npm run docs:lint && npm run docs:build",
"docs:build": "npx @redocly/cli build-docs -o ./docs/index.html --config docs/openapi/redocly-config.yaml",
Expand Down
131 changes: 93 additions & 38 deletions src/controllers/suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ import AccessControlUtil from '../support/access-control-util.js';
* @param {object} ctx - Context of the request.
* @param {SQS} sqs - SQS client.
* @param env
* @param log
* @returns {object} Suggestions controller.
* @constructor
*/
function SuggestionsController(ctx, sqs, env) {
function SuggestionsController(ctx, sqs, env, log) {
if (!isNonEmptyObject(ctx)) {
throw new Error('Context required');
}
Expand Down Expand Up @@ -454,6 +455,7 @@ function SuggestionsController(ctx, sqs, env) {
};
return createResponse(fullResponse, 207);
};

const autofixSuggestions = async (context) => {
const siteId = context.params?.siteId;
const opportunityId = context.params?.opportunityId;
Expand Down Expand Up @@ -497,41 +499,87 @@ function SuggestionsController(ctx, sqs, env) {
const validSuggestions = [];
const failedSuggestions = [];
suggestions.forEach((suggestion) => {
if (suggestionIds.includes(suggestion.getId())) {
if (suggestion.getStatus() === SuggestionModel.STATUSES.NEW) {
const suggestionId = suggestion.getId();
if (suggestionIds.includes(suggestionId)) {
const isValidId = isValidUUID(suggestionId);
const hasStatusNew = suggestion.getStatus() === SuggestionModel.STATUSES.NEW;
const data = suggestion.getData();
const hasUrlTo = data?.url_to;

if (isValidId && hasStatusNew && opportunity.getType() !== 'broken-backlinks') {
validSuggestions.push(suggestion);
} else if (isValidId && hasStatusNew && opportunity.getType() === 'broken-backlinks' && hasUrlTo) {
validSuggestions.push(suggestion);
} else {
let message;
switch (true) {
case !isValidId:
message = 'Invalid suggestion ID format';
break;
case opportunity.getType() === 'broken-backlinks' && !hasUrlTo:
message = 'Missing mandatory field: url_to';
break;
default:
message = 'Suggestion is not in NEW status';
}

failedSuggestions.push({
uuid: suggestion.getId(),
index: suggestionIds.indexOf(suggestion.getId()),
message: 'Suggestion is not in NEW status',
uuid: suggestionId,
index: suggestionIds.indexOf(suggestionId),
message,
statusCode: 400,
});
}
}
});

let suggestionGroups;
if (opportunity.getType() !== 'broken-backlinks') {
const suggestionsByUrl = validSuggestions.reduce((acc, suggestion) => {
const data = suggestion.getData();
const suggestionsByUrl = validSuggestions.reduce((acc, suggestion) => {
const data = suggestion.getData();
let groupKey;

if (opportunity.getType() === 'broken-backlinks') {
groupKey = 'broken-backlinks';
const urlTo = data?.url_to;

if (!acc[groupKey]) {
acc[groupKey] = {};
}

if (!acc[groupKey][urlTo]) {
acc[groupKey][urlTo] = [];
}
acc[groupKey][urlTo].push(suggestion);
} else {
const url = data?.url || data?.recommendations?.[0]?.pageUrl
|| data?.url_from
|| data?.urlFrom;
|| data?.url_from
|| data?.urlFrom;
if (!url) return acc;

if (!acc[url]) {
acc[url] = [];
acc[url] = {
suggestions: [],
};
}
acc[url].push(suggestion);
return acc;
}, {});

suggestionGroups = Object.entries(suggestionsByUrl).map(([url, groupedSuggestions]) => ({
groupedSuggestions,
url,
}));
}
acc[url].suggestions.push(suggestion);
}
return acc;
}, {});

const suggestionGroups = Object.entries(suggestionsByUrl).flatMap(([key, value]) => {
if (key === 'broken-backlinks') {
// eslint-disable-next-line no-shadow
return Object.entries(value).map(([urlTo, suggestions]) => ({
url: urlTo,
suggestions,
}));
} else {
return {
url: key,
suggestions: value.suggestions,
};
}
});
log.info(`suggestionGroups: ${JSON.stringify(suggestionGroups)}`);

suggestionIds.forEach((suggestionId, index) => {
if (!suggestions.find((s) => s.getId() === suggestionId)) {
Expand Down Expand Up @@ -582,27 +630,34 @@ function SuggestionsController(ctx, sqs, env) {
response.suggestions.sort((a, b) => a.index - b.index);
const { AUTOFIX_JOBS_QUEUE: queueUrl } = env;

if (opportunity.getType() !== 'broken-backlinks') {
await Promise.all(
suggestionGroups.map(({ groupedSuggestions, url }) => sendAutofixMessage(
if (isNonEmptyArray(suggestionGroups)) {
if (opportunity.getType() === 'broken-backlinks') {
const mappedSuggestions = {};
suggestionGroups.forEach((group) => {
mappedSuggestions[group.url] = group.suggestions.map((s) => s.getId());
});

await sendAutofixMessage(
sqs,
queueUrl,
siteId,
opportunityId,
groupedSuggestions.map((s) => s.getId()),
mappedSuggestions,
promiseTokenResponse,
{ url },
)),
);
} else {
await sendAutofixMessage(
sqs,
queueUrl,
siteId,
opportunityId,
succeededSuggestions.map((s) => s.getId()),
promiseTokenResponse,
);
);
} else {
await Promise.all(
suggestionGroups.map(({ suggestions: groupSuggestions, url }) => sendAutofixMessage(
sqs,
queueUrl,
siteId,
opportunityId,
groupSuggestions.map((s) => s.getId()),
promiseTokenResponse,
{ url },
)),
);
}
}

return createResponse(response, 207);
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ async function run(request, context) {
const apiKeyController = ApiKeyController(context);
const sitesAuditsToggleController = SitesAuditsToggleController(context);
const opportunitiesController = OpportunitiesController(context);
const suggestionsController = SuggestionsController(context, context.sqs, context.env);
const suggestionsController = SuggestionsController(context, context.sqs, context.env, log);
const brandsController = BrandsController(context, log, context.env);
const paidController = PaidController(context);
const trafficController = TrafficController(context, log, context.env);
Expand Down
4 changes: 2 additions & 2 deletions src/support/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ export const sendAutofixMessage = async (
queueUrl,
siteId,
opportunityId,
suggestionIds,
suggestionsData,
promiseToken,
{ url } = {},
) => sqs.sendMessage(queueUrl, {
opportunityId,
siteId,
suggestionIds,
suggestionsData,
promiseToken,
url,
});
Expand Down
Loading