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

More useful errors and logging when sync fails. #3133

Merged
merged 2 commits into from
Nov 22, 2022
Merged
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
103 changes: 95 additions & 8 deletions assets/js/sync/hooks.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* WordPress dependencies.
*/
import apiFetch from '@wordpress/api-fetch';
import { useCallback, useRef } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies.
Expand All @@ -23,6 +23,98 @@ export const useIndex = () => {
const abort = useRef(new AbortController());
const request = useRef(null);

const onResponse = useCallback(
/**
* Handle the response to the request.
*
* @param {Response} response Request response.
* @throws {Error} An error for unexpected responses.
* @returns {void}
*/
async (response) => {
const responseBody = await response.text();

const errorMessage = `${__(
'ElasticPress: Unexpected response.',
'elasticpress',
)}\n${responseBody}`;

/**
* Throw an error for non-20X responses.
*/
if (!response.ok) {
if (response.status === 403) {
/**
* A 403 response will occur if the nonce has expired or
* if the user's session has expired. Reloading the page
* will reset the nonce or prompt the user to log in again.
*/
throw new Error(
__(
'Permission denied. Reload the sync page and try again.',
'elasticpress',
),
);
} else {
/**
* Log the raw response to the console to assist with
* debugging.
*/
console.error(errorMessage); // eslint-disable-line no-console

/**
* Any other response is unexpected, and the user will
* need to troubleshoot.
*/
throw new Error(
__(
'Something went wrong. Find troubleshooting steps at https://elasticpress.zendesk.com/hc/en-us/sections/360010868652-Troubleshooting.',
'elasticpress',
),
);
}
}

/**
* Parse the response and throw an error if it fails.
*/
try {
return JSON.parse(responseBody);
} catch (e) {
/**
* Log the raw response to the console to assist with
* debugging.
*/
console.error(e.message); // eslint-disable-line no-console
console.error(errorMessage); // eslint-disable-line no-console

/**
* Invalid JSON is unexpected at this stage, and the user will
* need to troubleshoot.
*/
throw new Error(
__(
'Unable to parse response. Find troubleshooting steps at https://elasticpress.zendesk.com/hc/en-us/sections/360010868652-Troubleshooting.',
'elasticpress',
),
);
}
},
[],
);

const onComplete = useCallback(
/**
* Handle completion of the request, whether successful or not.
*
* @returns {void}
*/
() => {
request.current = null;
},
[],
);

const sendRequest = useCallback(
/**
* Send AJAX request.
Expand All @@ -35,13 +127,11 @@ export const useIndex = () => {
* @returns {Promise} Current request promise.
*/
(options) => {
request.current = apiFetch(options).finally(() => {
request.current = null;
});
request.current = fetch(ajaxUrl, options).then(onResponse).finally(onComplete);

return request.current;
},
[],
[onComplete, onResponse],
);

const cancelIndex = useCallback(
Expand All @@ -60,7 +150,6 @@ export const useIndex = () => {
body.append('nonce', nonce);

const options = {
url: ajaxUrl,
method: 'POST',
body,
signal: abort.current.signal,
Expand Down Expand Up @@ -89,7 +178,6 @@ export const useIndex = () => {
body.append('nonce', nonce);

const options = {
url: ajaxUrl,
method: 'POST',
body,
signal: abort.current.signal,
Expand All @@ -116,7 +204,6 @@ export const useIndex = () => {
body.append('nonce', nonce);

const options = {
url: ajaxUrl,
method: 'POST',
body,
signal: abort.current.signal,
Expand Down