Depends on: Storage Layout
RFCs: RFC-007, RFC-008
Abstract
This spec defines how are shared and synchronized between . It defines the minimal read-only Simple Transfer Protocol that works on top of any storage that can read objects by key, the efficient read-write Smart Transfer Protocol that allows transferring data directly to and from the storage of a repository, and the rules that keep shared datasets consistent for concurrent readers.Design Goals
The guiding factors in designing how data is shared were:- Minimal storage requirements - while a certain degree of replication is necessary to keep data highly available, we don’t want to duplicate data more than it’s necessary.
- Decentralization - there should be no central authority that decides what the “right data” is.
- Verifiable trust - even when data is hosted by a single party any tampering or alterations must still be impossible.
- Minimize the movement of data - when a trusted party keeps data in an environment that also provides compute resources, we would like to be able to process and query data without the need to always download it locally.
Dataset Sharing
Dataset sharing involves uploading the data to some where it can be discovered and accessed by other peers. Due to immutable nature of data and metadata it is very easy to keep shared data up-to-date as only new blocks and part files need to be uploaded. It is important to ensure the atomicity of the sharing, or at least create the perception of atomicity to someone who happens to be downloading the data concurrently with the upload. For that do not support atomic file/object operations the following sequence of operations can ensure that concurrent downloads will always see the in a consistent state:- Upload data part files and checkpoints
- Upload metadata blocks
- Update references in the
refssection (see Storage Layout)
Validation of Transferred Data
Repositories, storage systems, and peers that data is transferred from are not trusted. Regardless of the transfer protocol used, the receiving party must validate all received objects before committing them:- Metadata blocks are validated according to Metadata Chain: Validation, and must form a valid continuation of the chain the receiver already has
- Data part files and checkpoints are validated against the physical hashes stored in metadata (see Data & Checkpoint Hashing: Validation and Verification)
- Block references are updated only after all objects they make reachable were received and validated
Simple Transfer Protocol
Simple Transfer Protocol is a bare-minimum read-only protocol used for synchronizing between . It requires no ODF-specific logic on the server side and can be easily implemented, for example, by serving a dataset directory under an HTTP server. It’s designed for maximal interoperability, not for efficiency. The only operation a server needs to support is reading an object by key. The protocol purposefully does not rely on any advanced features like the ability to list a directory, so a dataset can be served from any storage that uses the layout of file systems and object stores, including content-addressable storage networks that provide HTTP gateways. To describe the protocol we will use HTTPGET {object-key} notation below, but note that this protocol can be implemented on top of any block or file-based protocol that supports Unix path-like object keys.
- Process begins with
GET /refs/headto get the hash of the last - The “metadata walking” process starts with
GET /blocks/{blockHash}and continues following theprevBlockHashlinks - Data part files can be downloaded by using links with
GET /data/{physicalHash} - Checkpoints are similarly downloaded using links with
GET /checkpoints/{physicalHash} - The process continues until reaching the first block of the dataset or other termination condition (e.g. reaching the block that has already been synced previously)
DataSlice and Checkpoint objects also carry the size of the files, which can be used as a size hint when transferring files between repositories in a streaming fashion.
Smart Transfer Protocol
Smart Transfer Protocol is a superset of the Simple Transfer Protocol, which allows both reads and writes and solves performance issues to allow efficient synchronization between remote dataset repositories:- Metadata blocks are transferred in batches as archives instead of one at a time
- Object files (data part files and checkpoints) are transferred directly to and from the storage system of the repository, with unrestricted degree of parallelism, instead of being proxied through the server
Establishing a Session
In addition to the HTTP endpoints of the Simple Transfer Protocol, servers implementing the Smart Transfer Protocol provide two more endpoints:GET /pull- to start the smart pull flow on the datasetGET /push- to start the smart push flow on the dataset
Sec-WebSocket-Protocolheader is set toodf/smart-transfer-protocol/v1x-odf-smtp-versionheader specifies the version of the Smart Transfer Protocol the client wants to use
Pull Flow
- Client sends
DatasetPullRequestwith the dataset ID and the desired block range:beginAfter- the last block the client already has (absent for the initial pull), andstopAt- the last block the client wants to pull (absent forhead) - Server responds with
DatasetPullResponsecontaining the size estimation of the transfer (number of blocks and objects and their raw sizes) - Client sends
DatasetPullMetadataRequest, and the server responds withDatasetMetadataPullResponsecontaining an archive of all metadata blocks in the requested range - Client analyzes the received blocks and identifies missing object files
- Client sends one or more
DatasetPullObjectsTransferRequestmessages listing a subset or the full set of missing object files, and the server responds to each withDatasetPullObjectsTransferResponsecontaining the download strategy for every object (a time-limited download URL with read-only access to the storage system) - Client downloads the object files directly from the storage system
- Client commits the new blocks locally and closes the session
Push Flow
- Client sends
DatasetPushRequestwith the dataset ID, thecurrentHeadthat the client assumes to be the current head on the server, and the size estimation of the transfer - Server responds with
DatasetPushRequestAccepted - Client sends
DatasetPushMetadatacontaining an archive of the new metadata blocks, and the server responds withDatasetPushMetadataAcceptedif it does not detect a divergence in the metadata - Client sends one or more
DatasetPushObjectsTransferRequestmessages listing a subset or the full set of new object files, and the server responds to each withDatasetPushObjectsTransferResponsecontaining the upload strategy for every object: a time-limited upload URL with write-only access to the storage system, or an instruction to skip the upload of an object that the server already has - Client uploads the object files directly to the storage system
- Client sends
DatasetPushComplete - Server verifies that the required objects exist and attempts to commit the new metadata blocks
- In case of success, server responds with
DatasetPushCompleteConfirmedand closes the session
Object Transfer
Object files are transferred out-of-band, directly between the client and the storage system of the repository, using pre-signed URLs:- The exchange of object files should be performed with delays and object sizes taken into account. As the expiration time of pre-signed URLs is limited, when large bulks of objects have to be exchanged the URLs may expire before the actual transfer starts - in this case they need to be re-requested.
- The parallelism of downloads and uploads is not limited by the protocol and is not to be constrained by the server - it’s an implementation detail of the client.
Error Handling
Errors that happen during any operation are reported by the server with theDatasetError message that carries an error code, a description, and optional extra fields.
In case of errors and timeouts the client needs to re-initiate the operation by opening another session. A new operation may skip the transfer of object files that were already processed in previous sessions, even if the changes have not been committed to the metadata.
Object files that were uploaded during failed operations remain orphaned in the storage until removed by a garbage collection mechanism, which is out of scope of this spec.
Messages
API Definitions
- Smart Transfer Protocol: OpenAPI - HTTP endpoints of the Simple and Smart Transfer Protocols
- Smart Transfer Protocol: AsyncAPI - asynchronous messages of the Smart Transfer Protocol