storemodel: define traits to decouple heavyweight implementation details

Summary:
Similar to `configmodel` introduced by D27641666 (a25ec579bf). Introduce a trait so we can
decouple from various storage implementation details.

This helps in many ways:
- De-couple store details. For example, `checkout` should not care about how to strip hg filelog header.
- Adds flexibility. For example, adopting the eagerepo store, or a git store, and they "just work" in various places (ex. in `checkout`, and the Python world).

For now, it only defines the pure content reading trait. The interface is now chosen to
match `checkout`'s needs. `(Key, Result<Bytes>)` might be arguably better than
`Result<(Key, Bytes)>` or `Result<(Bytes, Key)>`. But that can be changed later
after moving code from `checkout` to `revisionstore`.

More traits will be added later as we need them.

Reviewed By: DurhamG

Differential Revision: D33118996

fbshipit-source-id: 7f2b00b5bdefdf5b45ecf581f1586b5216e3e1cb
This commit is contained in:
Jun Wu 2021-12-15 12:43:47 -08:00 committed by Facebook GitHub Bot
parent 8e3be60f73
commit 0c2f73ac72
2 changed files with 55 additions and 0 deletions

View File

@ -0,0 +1,11 @@
# @generated by autocargo from //eden/scm/lib/storemodel:storemodel
[package]
name = "storemodel"
version = "0.1.0"
edition = "2021"
[dependencies]
async-trait = "0.1.51"
futures = { version = "0.3.13", features = ["async-await", "compat"] }
minibytes = { path = "../minibytes" }
types = { path = "../types" }

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
//! # storemodel
//!
//! Provides trait definitions for storage needs.
//! Useful to de-couple from heavyweight storage implementations.
//!
//! Traits defined by this crate are ideally tech-debt free and
//! consider both hg and git use-cases. This mainly means:
//! - APIs do expose hg details like filelog "copy from" or LFS pointer.
//! - History-related APIs should avoid linkrev or linknode, which do not exist
//! in git.
//!
//! For flexibility, different features might be defined in different traits.
//! Traits can be combined later. For example, reading file content, metadata,
//! and history should probably be 3 different traits.
use async_trait::async_trait;
use futures::stream::BoxStream;
pub use minibytes::Bytes;
use types::Key;
#[async_trait]
pub trait ReadFileContents {
type Error;
/// Read the content of specified files.
///
/// The returned content should be just the file contents. This means:
/// - The returned content does not contain the "copy from" header.
/// - The returned content does not contain raw LFS content. LFS pointer
/// is resolved transparently.
/// - If the file content is redacted, it's an error instead of an explicit
/// instead of a placeholder of dummy data.
async fn read_file_contents(
&self,
keys: Vec<Key>,
) -> BoxStream<Result<(Bytes, Key), Self::Error>>;
}