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_types::base_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)?;
76        Ok((
77            MoveFunctionName {
78                package,
79                module: metrics.move_module,
80                function: metrics.move_function,
81            },
82            metrics.count as usize,
83        ))
84    }
85}
86
87impl From<QueriedMoveCallMetrics> for StoredMoveCallMetrics {
88    fn from(q: QueriedMoveCallMetrics) -> Self {
89        StoredMoveCallMetrics {
90            id: Some(q.id),
91            epoch: q.epoch,
92            day: q.day,
93            move_package: q.move_package,
94            move_module: q.move_module,
95            move_function: q.move_function,
96            count: q.count,
97        }
98    }
99}
100
101#[derive(QueryableByName, Debug, Clone, Default)]
102pub struct QueriedMoveMetrics {
103    #[diesel(sql_type = BigInt)]
104    pub epoch: i64,
105    #[diesel(sql_type = BigInt)]
106    pub day: i64,
107    #[diesel(sql_type = Binary)]
108    pub move_package: Vec<u8>,
109    #[diesel(sql_type = Text)]
110    pub move_module: String,
111    #[diesel(sql_type = Text)]
112    pub move_function: String,
113    #[diesel(sql_type = BigInt)]
114    pub count: i64,
115}
116
117pub fn build_move_call_metric_query(epoch: i64, days: i64) -> String {
118    format!("SELECT {}::BIGINT AS epoch, {}::BIGINT AS day, move_package, move_module, move_function, COUNT(*)::BIGINT AS count
119        FROM move_calls
120        WHERE epoch >= {}
121        GROUP BY move_package, move_module, move_function
122        ORDER BY count DESC
123        LIMIT 10;", epoch, days, epoch - days)
124}