tus: don't allow 'notify' to be sent again (#1778)

## Ticket
725

## Issue
Upload a video. When `notify` is sent at the end of the tus upload, refresh immediately. The GUI allowed the user to resume the upload, but the ID is no longer present in the server.

## Approach
Until the polling API for `notify` is available, we can only assume the best and let the user know how to handle it.
- Store the "notify was sent" state.
- Show a dialog explaining the situation.

Thought of trying to make `claim_list` calls behind the scenes to clear itself, but it doesn't handle the case of `notify` actually failing. The best is to just let the user handle it for now.

Note that for the case of `onerror` actually received, we still retry since a network error could be the culprit (`notify` wasn't sent).
This commit is contained in:
infinite-persistence 2022-07-01 07:30:08 +08:00 committed by GitHub
parent 90346599b0
commit 640237c630
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 2 deletions

View file

@ -1147,6 +1147,13 @@
"Stopped. Duplicate session detected.": "Stopped. Duplicate session detected.", "Stopped. Duplicate session detected.": "Stopped. Duplicate session detected.",
"File being uploaded in another tab or window.": "File being uploaded in another tab or window.", "File being uploaded in another tab or window.": "File being uploaded in another tab or window.",
"There are pending uploads.": "There are pending uploads.", "There are pending uploads.": "There are pending uploads.",
"Processing file. Please wait...": "Processing file. Please wait...",
"File uploaded to server.": "File uploaded to server.",
"Remove entry?": "Remove entry?",
"The file was successfully uploaded, but we could not retrieve the confirmation status.": "The file was successfully uploaded, but we could not retrieve the confirmation status.",
"Wait 5-10 minutes, then refresh and check the Uploads list and Wallet transactions before attempting to re-upload.": "Wait 5-10 minutes, then refresh and check the Uploads list and Wallet transactions before attempting to re-upload.",
"This entry can be safely removed if the transaction is visible in those pages.": "This entry can be safely removed if the transaction is visible in those pages.",
"Press OK to clear this entry from the \"Currently Uploading\" list.": "Press OK to clear this entry from the \"Currently Uploading\" list.",
"Use a URL": "Use a URL", "Use a URL": "Use a URL",
"Edit Cover Image": "Edit Cover Image", "Edit Cover Image": "Edit Cover Image",
"Cover Image": "Cover Image", "Cover Image": "Cover Image",

View file

@ -75,7 +75,11 @@ export default function WebUploadItem(props: Props) {
} }
if (!uploader) { if (!uploader) {
return __('Stopped.'); if (status === 'notify') {
return __('File uploaded to server.');
} else {
return __('Stopped.');
}
} }
if (resumable) { if (resumable) {
@ -87,6 +91,8 @@ export default function WebUploadItem(props: Props) {
return __('Failed.'); return __('Failed.');
case 'conflict': case 'conflict':
return __('Stopped. Duplicate session detected.'); return __('Stopped. Duplicate session detected.');
case 'notify':
return __('Processing file. Please wait...');
default: default:
return status; return status;
} }
@ -108,7 +114,14 @@ export default function WebUploadItem(props: Props) {
// Should still be uploading. Don't show. // Should still be uploading. Don't show.
return null; return null;
} else { } else {
// Refreshed or connection broken. // Refreshed or connection broken ...
if (status === 'notify') {
// ... but 'notify' sent, so we have to assume it is processed.
// Can't do much until the polling API is available.
return null;
}
const isFileActive = file instanceof File; const isFileActive = file instanceof File;
return ( return (
<Button <Button
@ -129,6 +142,42 @@ export default function WebUploadItem(props: Props) {
function getCancelButton() { function getCancelButton() {
if (!locked) { if (!locked) {
if (status === 'notify') {
return (
<Button
button="link"
label={__('Remove')}
onClick={() => {
doOpenModal(MODALS.CONFIRM, {
title: __('Remove entry?'),
body: (
<>
<p>
{__('The file was successfully uploaded, but we could not retrieve the confirmation status.')}
</p>
<p>
{__(
'Wait 5-10 minutes, then refresh and check the Uploads list and Wallet transactions before attempting to re-upload.'
)}
</p>
<p className="section__subtitle">
{__('This entry can be safely removed if the transaction is visible in those pages.')}
</p>
<div className="help--warning">
<p>{__('Press OK to clear this entry from the "Currently Uploading" list.')}</p>
</div>
</>
),
onConfirm: (closeModal) => {
doUpdateUploadRemove(params.guid);
closeModal();
},
});
}}
/>
);
}
return <Button label={__('Cancel')} button="link" onClick={handleCancel} />; return <Button label={__('Cancel')} button="link" onClick={handleCancel} />;
} }
} }

View file

@ -239,8 +239,14 @@ export const publishReducer = handleActions(
uploadKeys.forEach((key) => { uploadKeys.forEach((key) => {
const params = newPublish.currentUploads[key].params; const params = newPublish.currentUploads[key].params;
if (!params || Object.keys(params).length === 0) { if (!params || Object.keys(params).length === 0) {
// The intended payload for the API is corrupted, so no point
// retaining. Remove from the pending-uploads list.
delete newPublish.currentUploads[key]; delete newPublish.currentUploads[key];
} else { } else {
// The data is still good, so we can resume upload. We just need
// to delete the previous reference of the tus-uploader (no
// longer functional, will be re-created). An empty 'uploader'
// also tells the GUI that we just rebooted.
delete newPublish.currentUploads[key].uploader; delete newPublish.currentUploads[key].uploader;
} }
}); });

View file

@ -123,6 +123,9 @@ export function makeResumableUploadRequest(
xhr.setRequestHeader('Tus-Resumable', '1.0.0'); xhr.setRequestHeader('Tus-Resumable', '1.0.0');
xhr.setRequestHeader(X_LBRY_AUTH_TOKEN, token); xhr.setRequestHeader(X_LBRY_AUTH_TOKEN, token);
xhr.responseType = 'json'; xhr.responseType = 'json';
xhr.onloadstart = () => {
window.store.dispatch(doUpdateUploadProgress({ guid, status: 'notify' }));
};
xhr.onload = () => { xhr.onload = () => {
window.store.dispatch(doUpdateUploadRemove(guid)); window.store.dispatch(doUpdateUploadRemove(guid));
resolve(xhr); resolve(xhr);