mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
scmstore: Introduce FetchKey and FetchValue traits
Summary: Introduce `FetchKey` and `FetchValue` traits to simplify repeated trait bounds in many `ReadStore` implementations. We also newly require `Clone` for both keys and values, which was already required by the fallback combinator. Reviewed By: DurhamG Differential Revision: D27652499 fbshipit-source-id: 6a3d5eb18a904b982fdb9946b80fcc9025d391ea
This commit is contained in:
parent
fb44958218
commit
0ec6d1fcc8
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
use std::convert::{From, Into, TryFrom, TryInto};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Error;
|
||||
@ -16,7 +15,8 @@ use tracing::error;
|
||||
use streams::select_drop;
|
||||
|
||||
use crate::scmstore::{
|
||||
BoxedReadStore, BoxedWriteStore, FetchError, FetchStream, KeyStream, ReadStore,
|
||||
BoxedReadStore, BoxedWriteStore, FetchError, FetchKey, FetchStream, FetchValue, KeyStream,
|
||||
ReadStore,
|
||||
};
|
||||
|
||||
/// A combinator which queries a preferred store, then falls back to a fallback store
|
||||
@ -39,15 +39,15 @@ const CHANNEL_BUFFER: usize = 200;
|
||||
|
||||
impl<K, VP, VF, VW, VO> ReadStore<K, VO> for FallbackCache<K, VP, VF, VW>
|
||||
where
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + Clone + Unpin + 'static,
|
||||
K: FetchKey + Unpin,
|
||||
// Preferred Value Type
|
||||
VP: Send + Sync + Clone + 'static,
|
||||
VP: FetchValue,
|
||||
// Fallback Value Type
|
||||
VF: Send + Sync + Clone + 'static,
|
||||
VF: FetchValue,
|
||||
// Write Value Type (must support conversion from fallback)
|
||||
VW: Send + Sync + Clone + From<VF> + 'static,
|
||||
VW: FetchValue + From<VF>,
|
||||
// Output Value Type (must support conversion from preferred & fallback)
|
||||
VO: Send + Sync + Clone + TryFrom<VF> + TryFrom<VP> + 'static,
|
||||
VO: FetchValue + TryFrom<VF> + TryFrom<VP>,
|
||||
// TODO(meyer): For now, we just require the conversion errors to convertible to anyhow::Error
|
||||
// We can probably loosen this later. In particular, we want to associate the key, at least.
|
||||
<VO as TryFrom<VF>>::Error: Into<Error>,
|
||||
@ -136,13 +136,13 @@ pub struct Fallback<K, VP, VF> {
|
||||
|
||||
impl<K, VP, VF, VO> ReadStore<K, VO> for Fallback<K, VP, VF>
|
||||
where
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + Clone + Unpin + 'static,
|
||||
K: FetchKey + Unpin,
|
||||
// Preferred Value Type
|
||||
VP: Send + Sync + Clone + 'static,
|
||||
VP: FetchValue,
|
||||
// Fallback Value Type
|
||||
VF: Send + Sync + Clone + 'static,
|
||||
VF: FetchValue,
|
||||
// Output Value Type (must support conversion from preferred & fallback)
|
||||
VO: Send + Sync + Clone + From<VF> + From<VP> + 'static,
|
||||
VO: FetchValue + From<VF> + From<VP>,
|
||||
{
|
||||
fn fetch_stream(self: Arc<Self>, keys: KeyStream<K>) -> FetchStream<K, VO> {
|
||||
// TODO(meyer): Write a custom Stream implementation to try to avoid use of channels
|
||||
|
@ -5,12 +5,13 @@
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::scmstore::{BoxedWriteStore, WriteResults, WriteStore, WriteStream};
|
||||
use crate::scmstore::{
|
||||
BoxedWriteStore, FetchKey, FetchValue, WriteResults, WriteStore, WriteStream,
|
||||
};
|
||||
|
||||
/// A minimal "filter_map" store, which filters writes to the associated `write_store`,
|
||||
pub struct FilterMapStore<K, V, F> {
|
||||
@ -23,8 +24,8 @@ pub struct FilterMapStore<K, V, F> {
|
||||
|
||||
impl<K, V, F> WriteStore<K, V> for FilterMapStore<K, V, F>
|
||||
where
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + 'static,
|
||||
V: Send + Sync + 'static,
|
||||
K: FetchKey,
|
||||
V: FetchValue,
|
||||
F: Fn(V) -> Option<V> + Send + Sync + 'static,
|
||||
{
|
||||
fn write_stream(self: Arc<Self>, values: WriteStream<V>) -> WriteResults<K> {
|
||||
|
@ -5,12 +5,13 @@
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use std::{collections::HashMap, fmt, hash::Hash, sync::Arc};
|
||||
use std::{collections::HashMap, hash::Hash, sync::Arc};
|
||||
|
||||
use futures::{lock::Mutex, StreamExt};
|
||||
|
||||
use crate::scmstore::{
|
||||
FetchError, FetchStream, KeyStream, ReadStore, WriteResults, WriteStore, WriteStream,
|
||||
FetchError, FetchKey, FetchStream, FetchValue, KeyStream, ReadStore, WriteResults, WriteStore,
|
||||
WriteStream,
|
||||
};
|
||||
|
||||
pub struct HashMapStore<K, V> {
|
||||
@ -38,8 +39,8 @@ pub trait KeyedValue {
|
||||
|
||||
impl<K, V> ReadStore<K, V> for HashMapStore<K, V>
|
||||
where
|
||||
K: fmt::Display + fmt::Debug + std::cmp::Eq + Hash + Send + Sync + 'static,
|
||||
V: Clone + Send + Sync + 'static,
|
||||
K: FetchKey + std::cmp::Eq + Hash,
|
||||
V: FetchValue,
|
||||
{
|
||||
fn fetch_stream(self: Arc<Self>, keys: KeyStream<K>) -> FetchStream<K, V> {
|
||||
Box::pin(keys.then(move |key| {
|
||||
@ -59,8 +60,8 @@ where
|
||||
|
||||
impl<K, V> WriteStore<K, V> for HashMapStore<K, V>
|
||||
where
|
||||
K: Clone + fmt::Display + fmt::Debug + std::cmp::Eq + Hash + Send + Sync + 'static,
|
||||
V: KeyedValue<Key = K> + Send + Sync + 'static,
|
||||
K: FetchKey + std::cmp::Eq + Hash,
|
||||
V: FetchValue + KeyedValue<Key = K>,
|
||||
{
|
||||
fn write_stream(self: Arc<Self>, values: WriteStream<V>) -> WriteResults<K> {
|
||||
Box::pin(values.then(move |value| {
|
||||
|
@ -55,6 +55,13 @@ pub type BoxedWriteStore<K, V> = Arc<dyn WriteStore<K, V>>;
|
||||
/// A trait object for stores which support both reading and writing.
|
||||
pub type BoxedRWStore<K, V> = Arc<dyn ReadWriteStore<K, V>>;
|
||||
|
||||
// Automatic blanket impls for FetchKey and FetchValue. For now they're just used to simplify trait bounds.
|
||||
pub trait FetchKey: fmt::Display + fmt::Debug + Clone + Send + Sync + 'static {}
|
||||
impl<K> FetchKey for K where K: fmt::Display + fmt::Debug + Clone + Send + Sync + 'static {}
|
||||
|
||||
pub trait FetchValue: Send + Sync + Clone + 'static {}
|
||||
impl<V> FetchValue for V where V: Send + Sync + Clone + 'static {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FetchError<K: fmt::Debug + fmt::Display> {
|
||||
#[error("failed to fetch key '{0}': key not found")]
|
||||
@ -108,8 +115,8 @@ where
|
||||
pub fn fetch_error<K, V, E>(e: E) -> FetchStream<K, V>
|
||||
where
|
||||
E: Into<Error> + Send + Sync + 'static,
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + 'static,
|
||||
V: Send + Sync + 'static,
|
||||
K: FetchKey,
|
||||
V: FetchValue,
|
||||
{
|
||||
Box::pin(stream::once(future::ready(Err(FetchError::from(e)))))
|
||||
}
|
||||
@ -140,34 +147,25 @@ where
|
||||
}
|
||||
|
||||
/// A typed, key-value store which supports both reading and writing.
|
||||
pub trait ReadWriteStore<
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + 'static,
|
||||
V: Send + Sync + 'static,
|
||||
>: ReadStore<K, V> + WriteStore<K, V>
|
||||
{
|
||||
}
|
||||
pub trait ReadWriteStore<K: FetchKey, V: FetchValue>: ReadStore<K, V> + WriteStore<K, V> {}
|
||||
|
||||
impl<T, K, V> ReadWriteStore<K, V> for T
|
||||
where
|
||||
K: fmt::Display + fmt::Debug + Send + Sync + 'static,
|
||||
V: Send + Sync + 'static,
|
||||
K: FetchKey,
|
||||
V: FetchValue,
|
||||
T: ReadStore<K, V> + WriteStore<K, V>,
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: Add attributes support
|
||||
/// A typed, async key-value storage API
|
||||
pub trait ReadStore<K: fmt::Display + fmt::Debug + Send + Sync + 'static, V: Send + Sync + 'static>:
|
||||
Send + Sync + 'static
|
||||
{
|
||||
pub trait ReadStore<K: FetchKey, V: FetchValue>: Send + Sync + 'static {
|
||||
/// Map a stream of keys to a stream of values by fetching from the underlying store
|
||||
fn fetch_stream(self: Arc<Self>, keys: KeyStream<K>) -> FetchStream<K, V>;
|
||||
}
|
||||
|
||||
// TODO: Add attributes support
|
||||
/// A typed, async key-value storage API
|
||||
pub trait WriteStore<K: fmt::Display + fmt::Debug + Send + Sync + 'static, V: Send + Sync + 'static>:
|
||||
Send + Sync + 'static
|
||||
{
|
||||
pub trait WriteStore<K: FetchKey, V: FetchValue>: Send + Sync + 'static {
|
||||
fn write_stream(self: Arc<Self>, values: WriteStream<V>) -> WriteResults<K>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user