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

Adds archive uploading to add missing attachments #1506

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

Spoffy
Copy link
Contributor

@Spoffy Spoffy commented Mar 11, 2025

Context

When a document using external attachments is downloaded then uploaded, none of the attachments will work. This is due to external attachments being stored on a per-document basis.

Proposed solution

This PR allows any missing files to be populated in the external store, by uploading a .tar archive containing the missing attachments.

It only supports .tar archives downloaded from Grist, as it uses the file's name to check if the file is missing.

Related issues

#1021

Has this been tested?

  • 👍 yes, I added tests to the test suite
  • 💭 no, because this PR is a draft and still needs work
  • 🙅 no, because this is not relevant here
  • 🙋 no, because I need help

@Spoffy Spoffy marked this pull request as draft March 11, 2025 00:44
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was renamed to streams.ts

if (err instanceof MismatchedFileHashError) {
this._log.warn(docSession, `Failed to upload attachment: ${err.message}`);
}
this._log.error(docSession, `Failed to upload attachment: ${err}`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also just be a warning?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no particular standard. This seems ok. The log isn't very structured for ingestion, but that's ok.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder about maybe returning the stringified errors in a list in the results, since otherwise the problem(s) will be very opaque to user. Optional, easy to add later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hesitant about doing that, just in case they're cryptic and unhelpful runtime errors (like the classic "access property of undefined"). Easy either way from my perspective.

Comment on lines 992 to 1001
const fileIdentParts = attachment.fileIdent.split(".");
const fileHash = fileIdentParts[0];
const fileIdentExt = path.extname(attachment.fileIdent);
const fileNameExt = path.extname(attachment.fileName);
const fileNameNoExt = path.basename(attachment.fileName, fileNameExt);
// We need to make sure the downloaded attachment's extension matches Grist's internal
// file extension, otherwise we can't recreate the file identifier when uploading.
// They might not match, as the upload process considers things like mime type when
// adding the extension to the file identifier.
const name = `${fileHash}_${fileNameNoExt}${fileIdentExt}`;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small tweak to the names of files in downloaded archives (see comment). Shouldn't make any difference 99% of the time, but covers an edge case.

Copy link
Member

@paulfitz paulfitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks plausible, small comments, thanks @Spoffy

if (err instanceof MismatchedFileHashError) {
this._log.warn(docSession, `Failed to upload attachment: ${err.message}`);
}
this._log.error(docSession, `Failed to upload attachment: ${err}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no particular standard. This seems ok. The log isn't very structured for ingestion, but that's ok.

if (err instanceof MismatchedFileHashError) {
this._log.warn(docSession, `Failed to upload attachment: ${err.message}`);
}
this._log.error(docSession, `Failed to upload attachment: ${err}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder about maybe returning the stringified errors in a list in the results, since otherwise the problem(s) will be very opaque to user. Optional, easy to add later.

return this._addFile(storeId, fileIdent, fileData);
}

public async addMissingFileData(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are enough nuances in this method that it could do with a solid docstring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants