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

Issue 359 support scaleway #577

Merged

Conversation

fflorent
Copy link
Collaborator

Context

ANCT Données et Territoire deploys Grist instances whose external storage are S3 and use the Minio connector. The S3 provider used is not MinIO but Scaleway.

Despite having enabled the versioning feature of the bucket, the snapshots feature had erratic behavior and mostly failed to work when importing documents.

The reason appears to be quite simple: that's because the versionId returned by Scaleway's API is not a string (as MinIO and AWS do), but is an integer.

Steps to reproduce

NB: Scaleway provides Free buckets with a limitation of 75Gb of storage.

  1. Create some document and export it in the .grist format;
  2. Make an instance of Grist and setup the env variables (GRIST_DOCS_MINIO_*) so it uses Scaleway bucket and some Redis instance;
  3. Start the instance;
  4. Log in;
  5. Import the document;

You get this kind of error message:

operation failed to become consistent: versions - 238,not ready,3360,not ready,8698,not ready,17486,not ready

And this exception:

2023-07-13 10:13:34.086 - error: HostedStorageManager error pushing 1w663WJyaYMxHhaPGNVDkd (1): Error: operation failed to become consistent: versions - 119,not ready,3250,not ready,8461,not ready,17240,not ready
    at ChecksummedExternalStorage._retry (/grist/_build/app/server/lib/ExternalStorage.js:286:15)
    at async DocSnapshotInventory._reconstruct (/grist/_build/app/server/lib/DocSnapshots.js:287:27)
    at async DocSnapshotInventory._reconstruct (/grist/_build/app/server/lib/DocSnapshots.js:287:27)
    at async DocSnapshotInventory._getSnapshots (/grist/_build/app/server/lib/DocSnapshots.js:253:20)
    at async DocSnapshotInventory._getSnapshots (/grist/_build/app/server/lib/DocSnapshots.js:253:20)
    at async /grist/_build/app/server/lib/DocSnapshots.js:173:31
    at async /grist/_build/app/server/lib/DocSnapshots.js:173:31
    at async KeyedMutex.runExclusive (/grist/_build/app/common/KeyedMutex.js:32:20)
    at async KeyedMutex.runExclusive (/grist/_build/app/common/KeyedMutex.js:32:20)
    at async DocSnapshotInventory.uploadAndAdd (/grist/_build/app/server/lib/DocSnapshots.js:167:9)
    at async DocSnapshotInventory.uploadAndAdd (/grist/_build/app/server/lib/DocSnapshots.js:167:9)
    at async HostedStorageManager._pushToS3 (/grist/_build/app/server/lib/HostedStorageManager.js:692:13) docId=null
    at async HostedStorageManager._pushToS3 (/grist/_build/app/server/lib/HostedStorageManager.js:692:13) docId=null

The solution

I just cast the versionId to a string

Unit tests

I added some unit tests to cover most of the cases that could occur while using the versions() function.

Misc

I also fixed this error which occurred while Grist was waiting a long time for response from the S3 storage:

2023-07-12 11:14:39.717 - error: ActiveDoc failed to update data size Error: Tried to use DocStorage database before it was opened
    at DocStorage._getDB (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/DocStorage.js:1253:19)
    at DocStorage.get (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/DocStorage.js:1010:21)
    at DocStorage.getDataSizeUncached (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/DocStorage.js:1098:35)
    at DocStorage.getDataSize (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/DocStorage.js:1091:112)
    at ActiveDoc._updateDataSize (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/ActiveDoc.js:1859:53)
    at ActiveDoc._checkDataSizeLimitRatio (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/ActiveDoc.js:1846:42)
    at Interval._callback (/home/florentpro/projects/grist-core-scaleway/_build/app/server/lib/ActiveDoc.js:185:48)
    at Interval._onTimeoutTriggered (/home/florentpro/projects/grist-core-scaleway/_build/app/common/Interval.js:76:49)
    at Timeout.<anonymous> (/home/florentpro/projects/grist-core-scaleway/_build/app/common/Interval.js:60:47)
    at listOnTimeout (node:internal/timers:569:17)
    at process.processTimers (node:internal/timers:512:7) docId=pfrVp1tA77Sm5ZdRx5JAVq

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 good, glad you tracked this subtle problem down. I see other uses of versionId such as in the head() method, does the MinIO client do a cast to string in statObject?

My comments are all bureaucratic in nature, nothing of substance.

test/server/lib/MinIOExternalStorage.ts Show resolved Hide resolved
test/server/lib/MinIOExternalStorage.ts Outdated Show resolved Hide resolved
test/server/lib/MinIOExternalStorage.ts Show resolved Hide resolved
@fflorent
Copy link
Collaborator Author

fflorent commented Jul 19, 2023

I see other uses of versionId such as in the head() method, does the MinIO client do a cast to string in statObject?

Thanks a lot @paulfitz for this valuable remark! 🙏

I checked the type of versionId for the results of stat() and putObject().

And that's strange that in these case, versionId is a string.

I realized that it might not be a bug of Grist but instead a minio-js inconsistency:

Therefore, I tend to think it's a bug in minio-js. We may keep the current patch as provided (maybe change the comment), but I would send a patch to the MinIO client.

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.

Thanks @fflorent

@paulfitz
Copy link
Member

Therefore, I tend to think it's a bug in minio-js. We may keep the current patch as provided (maybe change the comment), but I would send a patch to the MinIO client.

It don't know if I'd classify it as a bug exactly, I think I remember AWS S3 docs being a little vague on when exactly VersionId is included in results, and needing to probe them empirically. Still, bug or not, to be a good drop-in S3 replacement, making a patch to clean up this corner of the MinIO client (when used with Scaleway) would be helpful.

@fflorent
Copy link
Collaborator Author

making a patch to clean up this corner of the MinIO client (when used with Scaleway) would be helpful.

Done :) : https://github.com/minio/minio-js/pull/1193/files

I am changing some comments and test descriptions of the PR to reflect that.

Florent FAYOLLE and others added 2 commits July 20, 2023 11:26
While MinIO and AWS return versionId as strings, other S3 API
implementations return versionId as integers.

We must carefully convert the versionId as string in order to cover
these various behaviors.

Also ensure that docStorage is initialized before attempting to
calculate the data size in order to avoid an exception.
Introduced some unit tests to :
 - ensure listObjects is called with the right arguments;
 - cover the case when a S3 bucket implementation does not return the
   versionId as a string but rather as an integer (like Scaleway):
   in such a case, ensure that the returned snapshotId is a string;
 - cover the case when the listObjects function emits an error, ensure the
   versions() call rejets with the error emitted;
 - that the deleteMarkers are only returned when the
   includeDeleteMarkers is passed;
@paulfitz paulfitz merged commit 5e33b68 into gristlabs:main Jul 20, 2023
@paulfitz
Copy link
Member

making a patch to clean up this corner of the MinIO client (when used with Scaleway) would be helpful.

Done :) : https://github.com/minio/minio-js/pull/1193/files

Great! Thanks a lot @fflorent.

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