From ce184461cfe50df875b90a9dacc4934bdefd3123 Mon Sep 17 00:00:00 2001
From: Denis Smirnov <sd@picodata.io>
Date: Tue, 11 Oct 2022 12:06:51 +0700
Subject: [PATCH] feat: add statistics initialization to the API

Though we can lazily initialize statistics spaces, there is still a
problem with read-only replicas. If the workload does not write to
the storage (only reads with SELECTs), then callbre is used and no
queries will be dispatched to the storage master. As a result, no
statistics spaces will be initialized on the storage failover group.

To deal with it, we add a new API method to initialize statistics
on the instance startup.
---
 sbroad-cartridge/src/api.rs             |  1 +
 sbroad-cartridge/src/api/statistics.rs  | 21 +++++++++++++++++++++
 sbroad-cartridge/src/router.lua         |  7 +++++++
 sbroad-cartridge/src/storage.lua        |  7 +++++++
 sbroad-core/src/otm/statistics/table.rs |  6 +++---
 5 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 sbroad-cartridge/src/api/statistics.rs

diff --git a/sbroad-cartridge/src/api.rs b/sbroad-cartridge/src/api.rs
index 82db1e0cbf..cbc1a7786a 100644
--- a/sbroad-cartridge/src/api.rs
+++ b/sbroad-cartridge/src/api.rs
@@ -9,3 +9,4 @@ pub mod calculate_bucket_id;
 pub mod exec_query;
 mod helper;
 pub mod invalidate_cached_schema;
+pub mod statistics;
diff --git a/sbroad-cartridge/src/api/statistics.rs b/sbroad-cartridge/src/api/statistics.rs
new file mode 100644
index 0000000000..0148c61689
--- /dev/null
+++ b/sbroad-cartridge/src/api/statistics.rs
@@ -0,0 +1,21 @@
+use sbroad::debug;
+use sbroad::otm::statistics::table::{QUERY, SPAN, STAT};
+use std::os::raw::c_int;
+
+/// Initialize query statistics tables.
+///
+/// Though the function always returns a success, it can fail to create
+/// the table (for example on read-only replica). In this case, the
+/// warning will be logged, but the function will return success.
+#[allow(clippy::module_name_repetitions)]
+#[no_mangle]
+pub extern "C" fn init_statistics() -> c_int {
+    debug!(
+        Option::from("init_statistics"),
+        "Initializing statistics tables"
+    );
+    QUERY.with(|_| {});
+    SPAN.with(|_| {});
+    STAT.with(|_| {});
+    0
+}
diff --git a/sbroad-cartridge/src/router.lua b/sbroad-cartridge/src/router.lua
index 00a069296c..be99180ca8 100644
--- a/sbroad-cartridge/src/router.lua
+++ b/sbroad-cartridge/src/router.lua
@@ -217,6 +217,13 @@ local function init()
         'libsbroad.dispatch_query',
         { if_not_exists = true, language = 'C' }
     )
+
+    box.schema.func.create(
+        'libsbroad.init_statistics',
+        { if_not_exists = true, language = 'C' }
+    )
+
+    box.func["libsbroad.init_statistics"]:call({})
 end
 
 local function calculate_bucket_id(values, space_name) -- luacheck: no unused args
diff --git a/sbroad-cartridge/src/storage.lua b/sbroad-cartridge/src/storage.lua
index a3d3bd890b..3eeca2a99b 100644
--- a/sbroad-cartridge/src/storage.lua
+++ b/sbroad-cartridge/src/storage.lua
@@ -87,6 +87,13 @@ local function init()
         'libsbroad.invalidate_segment_cache',
         { if_not_exists = true, language = 'C' }
     )
+
+    box.schema.func.create(
+        'libsbroad.init_statistics',
+        { if_not_exists = true, language = 'C' }
+    )
+
+    box.func["libsbroad.init_statistics"]:call({})
 end
 
 local function invalidate_cache()
diff --git a/sbroad-core/src/otm/statistics/table.rs b/sbroad-core/src/otm/statistics/table.rs
index f2a1e6ed98..47a68533bb 100644
--- a/sbroad-core/src/otm/statistics/table.rs
+++ b/sbroad-core/src/otm/statistics/table.rs
@@ -33,9 +33,9 @@ use tarantool::{index, space};
 
 use crate::{debug, warn};
 
-thread_local!(pub(super) static QUERY: RefCell<QuerySpace> = RefCell::new(QuerySpace::new()));
-thread_local!(pub(super) static SPAN: RefCell<SpanMap> = RefCell::new(SpanMap::new()));
-thread_local!(pub(super) static STAT: RefCell<StatSpace> = RefCell::new(StatSpace::new()));
+thread_local!(pub static QUERY: RefCell<QuerySpace> = RefCell::new(QuerySpace::new()));
+thread_local!(pub static SPAN: RefCell<SpanMap> = RefCell::new(SpanMap::new()));
+thread_local!(pub static STAT: RefCell<StatSpace> = RefCell::new(StatSpace::new()));
 
 pub trait RustMap {
     type Key;
-- 
GitLab