iota/iota-storage/src/util/outgoing_relay.rs
2026-09-13 20:58:41 +02:00

68 lines
2.8 KiB
Rust

/* Accepts an outgoing relay only when its retry record and retention state commit together. */
use crate::storage_error::StorageError;
use crate::util::{chat_files, db, message_storage_policy, relay_queue, relay_replay};
use rusqlite::OptionalExtension;
pub struct OutgoingRelay<'a> {
pub target: relay_queue::RelayTarget,
pub identity: &'a relay_queue::RelayIdentity,
pub frame: &'a [u8],
pub created_at: i64,
pub frame_id: u32,
pub type_map_version: &'a str,
}
pub fn commit_outgoing_relay(relay: OutgoingRelay<'_>) -> Result<(), StorageError> {
db::with_immediate_transaction(|tx| {
relay_queue::enqueue_in_tx(
tx,
relay.target,
relay.identity,
relay.frame,
relay.created_at,
relay.frame_id,
relay.type_map_version,
)?;
let signer_id = tx
.query_row(
"SELECT local_user_id FROM hosted_principals WHERE principal_handle = ?1",
[relay.identity.signer.0],
|row| row.get::<_, i64>(0),
)
.optional()?
.ok_or_else(|| StorageError::Other("outgoing signer is not hosted locally".into()))?;
if message_storage_policy::get_in_tx(tx, signer_id)?.history_mode
== message_storage_policy::MessageHistoryMode::DeleteAfterClientDelivery
{
let message_id = tx.query_row("SELECT id FROM messages WHERE storage_owner = ?1 AND relay_signer_principal = ?2 AND relay_message_id = ?3", rusqlite::params![signer_id, relay.identity.signer.0, relay.identity.message_id], |row| row.get::<_, i64>(0)).optional()?;
if let Some(message_id) = message_id {
chat_files::remove_message_history_in_tx(tx, signer_id, message_id)?;
}
}
relay_replay::mark_queued_in_tx(tx, relay.identity.signer, &relay.identity.message_id)?;
Ok(())
})
}
pub fn apply_outgoing_history_policy(
storage_owner: i64,
relay_signer_principal: iota_identity::PrincipalHandle,
relay_message_id: &str,
) -> Result<(), StorageError> {
db::with_immediate_transaction(|tx| {
if message_storage_policy::get_in_tx(tx, storage_owner)?.history_mode
!= message_storage_policy::MessageHistoryMode::DeleteAfterClientDelivery
{
return Ok(());
}
let message_id = tx.query_row(
"SELECT id FROM messages WHERE storage_owner = ?1 AND relay_signer_principal = ?2 AND relay_message_id = ?3",
rusqlite::params![storage_owner, relay_signer_principal.0, relay_message_id],
|row| row.get::<_, i64>(0),
).optional()?;
if let Some(message_id) = message_id {
chat_files::remove_message_history_in_tx(tx, storage_owner, message_id)?;
}
Ok(())
})
}