Skip to main content

iota_indexer/models/
move_call_metrics.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::str::FromStr;
6
7use diesel::{
8    QueryableByName,
9    prelude::*,
10    sql_types::{BigInt, Binary, Text},
11};
12use iota_json_rpc_types::MoveFunctionName;
13use iota_sdk_types::ObjectId;
14
15use crate::{
16    errors::IndexerError,
17    schema::{move_call_metrics, move_calls},
18};
19
20#[derive(Clone, Debug, Queryable, Insertable)]
21#[diesel(table_name = move_calls)]
22pub struct StoredMoveCall {
23    pub transaction_sequence_number: i64,
24    pub checkpoint_sequence_number: i64,
25    pub epoch: i64,
26    pub move_package: Vec<u8>,
27    pub move_module: String,
28    pub move_function: String,
29}
30
31#[derive(Clone, Debug, Insertable)]
32#[diesel(table_name = move_call_metrics)]
33pub struct StoredMoveCallMetrics {
34    pub id: Option<i64>,
35    pub epoch: i64,
36    pub day: i64,
37    pub move_package: String,
38    pub move_module: String,
39    pub move_function: String,
40    pub count: i64,
41}
42
43impl Default for StoredMoveCallMetrics {
44    fn default() -> Self {
45        Self {
46            id: None,
47            epoch: -1,
48            day: -1,
49            move_package: "".to_string(),
50            move_module: "".to_string(),
51            move_function: "".to_string(),
52            count: -1,
53        }
54    }
55}
56
57// for auto-incremented id, the committed id is None, so Option<i64>,
58// but when querying, the returned type is i64, thus a separate type is needed.
59#[derive(Clone, Debug, Queryable, QueryableByName)]
60#[diesel(table_name = move_call_metrics)]
61pub struct QueriedMoveCallMetrics {
62    pub id: i64,
63    pub epoch: i64,
64    pub day: i64,
65    pub move_package: String,
66    pub move_module: String,
67    pub move_function: String,
68    pub count: i64,
69}
70
71impl TryFrom<QueriedMoveCallMetrics> for (MoveFunctionName, usize) {
72    type Error = IndexerError;
73
74    fn try_from(metrics: QueriedMoveCallMetrics) -> Result<(MoveFunctionName, usize), Self::Error> {
75        let package = ObjectId::from_str(&metrics.move_package).map_err(|_| {
76            IndexerError::ObjectIdParse(iota_types::base_types::ObjectIdParseError::TryFromSlice)
77        })?;
78        Ok((
79            MoveFunctionName {
80                package,
81                module: metrics.move_module,
82                function: metrics.move_function,
83            },
84            metrics.count as usize,
85        ))
86    }
87}
88
89impl From<QueriedMoveCallMetrics> for StoredMoveCallMetrics {
90    fn from(q: QueriedMoveCallMetrics) -> Self {
91        StoredMoveCallMetrics {
92            id: Some(q.id),
93            epoch: q.epoch,
94            day: q.day,
95            move_package: q.move_package,
96            move_module: q.move_module,
97            move_function: q.move_function,
98            count: q.count,
99        }
100    }
101}
102
103#[derive(QueryableByName, Debug, Clone, Default)]
104pub struct QueriedMoveMetrics {
105    #[diesel(sql_type = BigInt)]
106    pub epoch: i64,
107    #[diesel(sql_type = BigInt)]
108    pub day: i64,
109    #[diesel(sql_type = Binary)]
110    pub move_package: Vec<u8>,
111    #[diesel(sql_type = Text)]
112    pub move_module: String,
113    #[diesel(sql_type = Text)]
114    pub move_function: String,
115    #[diesel(sql_type = BigInt)]
116    pub count: i64,
117}
118
119pub fn build_move_call_metric_query(epoch: i64, days: i64) -> String {
120    format!("SELECT {}::BIGINT AS epoch, {}::BIGINT AS day, move_package, move_module, move_function, COUNT(*)::BIGINT AS count
121        FROM move_calls
122        WHERE epoch >= {}
123        GROUP BY move_package, move_module, move_function
124        ORDER BY count DESC
125        LIMIT 10;", epoch, days, epoch - days)
126}