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

[Miniflare 3] Re-implement R2 gateway and add support for multipart uploads using new storage system #565

Merged
merged 2 commits into from
May 9, 2023

Conversation

mrbbot
Copy link
Contributor

@mrbbot mrbbot commented May 2, 2023

This PR builds on #555, and re-implements the R2 gateway using the new storage system. This was the last gateway we needed to migrate. 🙂 It also adds support for multipart uploads, similar to #486, but now with transactions provided by SQLite and the streaming support of the new blob store.

This is split into two commits, one for re-implementing what we had already with the new storage system, and one for extending that with multipart support. You may want to review the SQLite schema before everything else:

export interface ObjectRow {
key: string;
blob_id: string | null; // null if multipart
version: string;
size: number; // total size of object (all parts) in bytes
etag: string; // hex MD5 hash if not multipart
uploaded: number; // milliseconds since unix epoch
checksums: string; // JSON-serialised `R2StringChecksums` (workers-types)
http_metadata: string; // JSON-serialised `R2HTTPMetadata` (workers-types)
custom_metadata: string; // JSON-serialised user-defined metadata
}
export const MultipartUploadState = {
IN_PROGRESS: 0,
COMPLETED: 1,
ABORTED: 2,
} as const;
export interface MultipartUploadRow {
upload_id: string;
key: string;
http_metadata: string; // JSON-serialised `R2HTTPMetadata` (workers-types)
custom_metadata: string; // JSON-serialised user-defined metadata
state: ValueOf<typeof MultipartUploadState>;
// NOTE: we need to keep completed/aborted uploads around for referential
// integrity, and because error messages are different when attempting to
// upload parts to them
}
export interface MultipartPartRow {
upload_id: string;
part_number: number;
blob_id: string;
size: number; // NOTE: used to identify which parts to read for range requests
etag: string; // NOTE: multipart part ETag's are not MD5 checksums
checksum_md5: string; // NOTE: used in construction of final object's ETag
object_key: string | null; // null if in-progress upload
}
export const SQL_SCHEMA = `
CREATE TABLE IF NOT EXISTS _mf_objects (
key TEXT PRIMARY KEY,
blob_id TEXT,
version TEXT NOT NULL,
size INTEGER NOT NULL,
etag TEXT NOT NULL,
uploaded INTEGER NOT NULL,
checksums TEXT NOT NULL,
http_metadata TEXT NOT NULL,
custom_metadata TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS _mf_multipart_uploads (
upload_id TEXT PRIMARY KEY,
key TEXT NOT NULL,
http_metadata TEXT NOT NULL,
custom_metadata TEXT NOT NULL,
state TINYINT DEFAULT 0 NOT NULL
);
CREATE TABLE IF NOT EXISTS _mf_multipart_parts (
upload_id TEXT NOT NULL REFERENCES _mf_multipart_uploads(upload_id),
part_number INTEGER NOT NULL,
blob_id TEXT NOT NULL,
size INTEGER NOT NULL,
etag TEXT NOT NULL,
checksum_md5 TEXT NOT NULL,
object_key TEXT REFERENCES _mf_objects(key) DEFERRABLE INITIALLY DEFERRED,
PRIMARY KEY (upload_id, part_number)
);
`;
// NOTE: `object_key` foreign key constraint is deferred, meaning we can delete
// the linked object row, *then* the multipart part rows in a transaction,
// see https://www.sqlite.org/foreignkeys.html#fk_deferred for more details

Closes DEVX-592 and DEVX-593

@mrbbot mrbbot added the tre Relating to Miniflare 3 label May 2, 2023
@mrbbot mrbbot requested a review from a team May 2, 2023 09:18
@changeset-bot
Copy link

changeset-bot bot commented May 2, 2023

⚠️ No Changeset found

Latest commit: 52c7c01

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

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

LGTM with a few comments. A lot of the second commit appeared to be just replacing clock with timers, which would have been nice in a separate commit.
Nice work!

@mrbbot mrbbot force-pushed the tre-new-storage-r2 branch from 1c413ad to 52c7c01 Compare May 9, 2023 14:17
@mrbbot
Copy link
Contributor Author

mrbbot commented May 9, 2023

Rebasing...

@mrbbot mrbbot merged commit 4ada92b into tre May 9, 2023
@mrbbot mrbbot deleted the tre-new-storage-r2 branch May 9, 2023 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tre Relating to Miniflare 3
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants