sui_indexer_alt_jsonrpc/
data.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3use std::time::Duration;
4
5use anyhow::Context as _;
6use serde::de::DeserializeOwned;
7use sui_indexer_alt_reader::object_versions::LatestObjectVersionKey;
8use sui_types::base_types::ObjectID;
9use sui_types::object::Object;
10
11use crate::context::Context;
12
13/// Load the contents of the live version of an object from the store and deserialize it as an
14/// `Object`. Returns `None` if the object is deleted, wrapped, or never existed.
15pub(crate) async fn load_live(
16    ctx: &Context,
17    object_id: ObjectID,
18) -> Result<Option<Object>, anyhow::Error> {
19    let Some(latest_version) = ctx
20        .pg_loader()
21        .load_one(LatestObjectVersionKey(object_id))
22        .await
23        .context("Failed to load latest version")?
24    else {
25        return Ok(None);
26    };
27
28    if latest_version.object_digest.is_none() {
29        return Ok(None);
30    }
31
32    // Read from kv store and retry if the object is not found.
33    let mut object = None;
34    let config = &ctx.config().objects;
35    let mut interval = tokio::time::interval(Duration::from_millis(config.obj_retry_interval_ms));
36    let mut retries = 0;
37
38    for _ in 0..=config.obj_retry_count {
39        interval.tick().await;
40
41        object = ctx
42            .kv_loader()
43            .load_one_object(object_id, latest_version.object_version as u64)
44            .await
45            .context("Failed to load latest object")?;
46        if object.is_some() {
47            break;
48        }
49
50        retries += 1;
51        ctx.metrics()
52            .read_retries
53            .with_label_values(&["kv_object"])
54            .inc();
55    }
56
57    ctx.metrics()
58        .read_retries_per_request
59        .with_label_values(&["kv_object"])
60        .observe(retries as f64);
61
62    Ok(object)
63}
64
65/// Fetch the latest version of the object at ID `object_id`, and deserialize its contents as a
66/// Rust type `T`, assuming that it exists and is a Move object (not a package).
67pub(crate) async fn load_live_deserialized<T: DeserializeOwned>(
68    ctx: &Context,
69    object_id: ObjectID,
70) -> Result<T, anyhow::Error> {
71    let object = load_live(ctx, object_id).await?.context("No data found")?;
72
73    let move_object = object.data.try_as_move().context("Not a Move object")?;
74    bcs::from_bytes(move_object.contents()).context("Failed to deserialize Move value")
75}