2024-12-01 18:06:34 +01:00
|
|
|
//! Waku store protocol related methods
|
|
|
|
|
|
|
|
|
|
// std
|
|
|
|
|
use std::ffi::CString;
|
2024-12-22 16:38:22 +01:00
|
|
|
use uuid::Uuid;
|
2024-12-01 18:06:34 +01:00
|
|
|
// internal
|
2024-12-22 14:45:07 +01:00
|
|
|
use crate::general::libwaku_response::{handle_response, LibwakuResponse};
|
2024-12-22 16:38:22 +01:00
|
|
|
use crate::general::time::get_now_in_nanosecs;
|
2024-12-22 14:45:07 +01:00
|
|
|
use crate::general::waku_decode::WakuDecode;
|
2024-12-01 18:06:34 +01:00
|
|
|
use crate::general::{
|
2024-12-15 21:29:44 +01:00
|
|
|
contenttopic::WakuContentTopic, messagehash::MessageHash, pubsubtopic::PubsubTopic, Result,
|
2024-12-01 20:58:33 +01:00
|
|
|
WakuStoreRespMessage,
|
2024-12-01 18:06:34 +01:00
|
|
|
};
|
2024-12-22 14:45:07 +01:00
|
|
|
use crate::handle_ffi_call;
|
2024-12-01 18:06:34 +01:00
|
|
|
use crate::node::context::WakuNodeContext;
|
|
|
|
|
use multiaddr::Multiaddr;
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
|
pub struct PagingOptions {
|
|
|
|
|
pub page_size: usize,
|
|
|
|
|
pub cursor: Option<MessageHash>,
|
|
|
|
|
pub forward: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Criteria used to retrieve historical messages
|
|
|
|
|
#[derive(Clone, Serialize, Debug)]
|
2024-12-22 16:38:22 +01:00
|
|
|
pub struct StoreQueryRequest {
|
2024-12-01 18:06:34 +01:00
|
|
|
/// if true, the store-response will include the full message content. If false,
|
|
|
|
|
/// the store-response will only include a list of message hashes.
|
|
|
|
|
request_id: String,
|
|
|
|
|
include_data: bool,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pubsub_topic: Option<PubsubTopic>,
|
|
|
|
|
content_topics: Vec<WakuContentTopic>,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2024-12-22 16:38:22 +01:00
|
|
|
time_start: Option<u64>,
|
2024-12-01 18:06:34 +01:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2024-12-22 16:38:22 +01:00
|
|
|
time_end: Option<u64>,
|
2024-12-01 18:06:34 +01:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
message_hashes: Option<Vec<MessageHash>>,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pagination_cursor: Option<MessageHash>, // Message hash (key) from where to start query (exclusive)
|
|
|
|
|
pagination_forward: bool,
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
|
pagination_limit: Option<u64>,
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-22 16:38:22 +01:00
|
|
|
impl StoreQueryRequest {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
StoreQueryRequest {
|
|
|
|
|
request_id: Uuid::new_v4().to_string(),
|
|
|
|
|
include_data: true,
|
|
|
|
|
pubsub_topic: None,
|
|
|
|
|
content_topics: Vec::new(),
|
|
|
|
|
time_start: Some(get_now_in_nanosecs()),
|
|
|
|
|
time_end: Some(get_now_in_nanosecs()),
|
|
|
|
|
message_hashes: None,
|
|
|
|
|
pagination_cursor: None,
|
|
|
|
|
pagination_forward: true,
|
|
|
|
|
pagination_limit: Some(25),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_include_data(mut self, include_data: bool) -> Self {
|
|
|
|
|
self.include_data = include_data;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_pubsub_topic(mut self, pubsub_topic: Option<PubsubTopic>) -> Self {
|
|
|
|
|
self.pubsub_topic = pubsub_topic;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_content_topics(mut self, content_topics: Vec<WakuContentTopic>) -> Self {
|
|
|
|
|
self.content_topics = content_topics;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_time_start(mut self, time_start: Option<u64>) -> Self {
|
|
|
|
|
self.time_start = time_start;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_time_end(mut self, time_end: Option<u64>) -> Self {
|
|
|
|
|
self.time_end = time_end;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-23 01:13:15 +01:00
|
|
|
#[allow(dead_code)]
|
2024-12-22 16:38:22 +01:00
|
|
|
pub fn with_message_hashes(mut self, message_hashes: Vec<MessageHash>) -> Self {
|
|
|
|
|
self.message_hashes = Some(message_hashes);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_pagination_cursor(mut self, pagination_cursor: Option<MessageHash>) -> Self {
|
|
|
|
|
self.pagination_cursor = pagination_cursor;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn with_pagination_forward(mut self, pagination_forward: bool) -> Self {
|
|
|
|
|
self.pagination_forward = pagination_forward;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-01 18:06:34 +01:00
|
|
|
#[derive(Clone, Deserialize, Debug)]
|
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
|
pub struct StoreWakuMessageResponse {
|
2024-12-15 21:29:44 +01:00
|
|
|
pub message_hash: MessageHash,
|
2024-12-01 20:58:33 +01:00
|
|
|
pub message: WakuStoreRespMessage,
|
2024-12-01 18:06:34 +01:00
|
|
|
pub pubsub_topic: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Deserialize, Debug)]
|
|
|
|
|
#[serde(rename_all = "camelCase")]
|
|
|
|
|
pub struct StoreResponse {
|
2024-12-23 01:13:15 +01:00
|
|
|
#[allow(unused)]
|
2024-12-01 18:06:34 +01:00
|
|
|
pub request_id: String,
|
2024-12-23 01:13:15 +01:00
|
|
|
|
2024-12-01 18:06:34 +01:00
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2024-12-23 01:13:15 +01:00
|
|
|
#[allow(unused)]
|
2024-12-01 18:06:34 +01:00
|
|
|
pub status_code: u32,
|
2024-12-23 01:13:15 +01:00
|
|
|
|
|
|
|
|
#[allow(unused)]
|
2024-12-01 18:06:34 +01:00
|
|
|
pub status_desc: String,
|
|
|
|
|
|
|
|
|
|
/// Array of retrieved historical messages in [`WakuMessage`] format
|
|
|
|
|
// #[serde(default)]
|
|
|
|
|
pub messages: Vec<StoreWakuMessageResponse>,
|
|
|
|
|
/// Paging information in [`PagingOptions`] format from which to resume further historical queries
|
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
2024-12-15 21:29:44 +01:00
|
|
|
pub pagination_cursor: Option<MessageHash>,
|
2024-12-01 18:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Implement WakuDecode for Vec<Multiaddr>
|
|
|
|
|
impl WakuDecode for StoreResponse {
|
|
|
|
|
fn decode(input: &str) -> Result<Self> {
|
2024-12-15 21:29:44 +01:00
|
|
|
Ok(serde_json::from_str(input).expect("could not parse store resp"))
|
2024-12-01 18:06:34 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-19 23:05:39 +01:00
|
|
|
pub async fn waku_store_query(
|
2024-12-01 18:06:34 +01:00
|
|
|
ctx: &WakuNodeContext,
|
2024-12-22 16:38:22 +01:00
|
|
|
query: StoreQueryRequest,
|
2024-12-01 18:06:34 +01:00
|
|
|
peer_addr: &str,
|
|
|
|
|
timeout_millis: Option<i32>,
|
|
|
|
|
) -> Result<StoreResponse> {
|
|
|
|
|
let json_query = CString::new(
|
|
|
|
|
serde_json::to_string(&query).expect("StoreQuery should always be able to be serialized"),
|
|
|
|
|
)
|
2024-12-19 23:05:39 +01:00
|
|
|
.expect("CString should build properly from the serialized filter subscription");
|
2024-12-01 18:06:34 +01:00
|
|
|
|
|
|
|
|
peer_addr
|
|
|
|
|
.parse::<Multiaddr>()
|
|
|
|
|
.expect("correct multiaddress in store query");
|
2024-12-19 23:05:39 +01:00
|
|
|
let peer_addr = CString::new(peer_addr).expect("peer_addr CString should be created");
|
2024-12-01 18:06:34 +01:00
|
|
|
|
2024-12-22 14:45:07 +01:00
|
|
|
handle_ffi_call!(
|
|
|
|
|
waku_sys::waku_store_query,
|
|
|
|
|
handle_response,
|
|
|
|
|
ctx.get_ptr(),
|
|
|
|
|
json_query.as_ptr(),
|
|
|
|
|
peer_addr.as_ptr(),
|
|
|
|
|
timeout_millis.unwrap_or(10000i32)
|
|
|
|
|
)
|
2024-12-01 18:06:34 +01:00
|
|
|
}
|