sui_core/
fallback_fetch.rs

1// Copyright (c) 2021, Facebook, Inc. and its affiliates
2// Copyright (c) Mysten Labs, Inc.
3// SPDX-License-Identifier: Apache-2.0
4
5use mysten_common::ZipDebugEqIteratorExt;
6
7use crate::execution_cache::cache_types::CacheResult;
8use sui_types::error::SuiResult;
9
10/// do_fallback_lookup is a helper function for multi-get operations.
11/// It takes a list of keys and first attempts to look up each key in the cache.
12/// The cache can return a hit, a miss, or a negative hit (if the object is known to not exist).
13/// Any keys that result in a miss are then looked up in the store.
14///
15/// The "get from cache" and "get from store" behavior are implemented by the caller and provided
16/// via the get_cached_key and multiget_fallback functions.
17pub fn do_fallback_lookup<K: Clone, V: Default + Clone>(
18    keys: &[K],
19    get_cached_key: impl Fn(&K) -> CacheResult<V>,
20    multiget_fallback: impl Fn(&[K]) -> Vec<V>,
21) -> Vec<V> {
22    do_fallback_lookup_fallible(
23        keys,
24        |key| Ok(get_cached_key(key)),
25        |keys| Ok(multiget_fallback(keys)),
26    )
27    .expect("cannot fail")
28}
29
30pub fn do_fallback_lookup_fallible<K: Clone, V: Default + Clone>(
31    keys: &[K],
32    get_cached_key: impl Fn(&K) -> SuiResult<CacheResult<V>>,
33    multiget_fallback: impl Fn(&[K]) -> SuiResult<Vec<V>>,
34) -> SuiResult<Vec<V>> {
35    let mut results = vec![V::default(); keys.len()];
36    let mut fallback_keys = Vec::with_capacity(keys.len());
37    let mut fallback_indices = Vec::with_capacity(keys.len());
38
39    for (i, key) in keys.iter().enumerate() {
40        match get_cached_key(key)? {
41            CacheResult::Miss => {
42                fallback_keys.push(key.clone());
43                fallback_indices.push(i);
44            }
45            CacheResult::NegativeHit => (),
46            CacheResult::Hit(value) => {
47                results[i] = value;
48            }
49        }
50    }
51
52    let fallback_results = multiget_fallback(&fallback_keys)?;
53    assert_eq!(fallback_results.len(), fallback_indices.len());
54    assert_eq!(fallback_results.len(), fallback_keys.len());
55
56    for (i, result) in fallback_indices
57        .into_iter()
58        .zip_debug_eq(fallback_results.into_iter())
59    {
60        results[i] = result;
61    }
62    Ok(results)
63}