pub mod error;
pub mod handle;
pub mod model;
mod service;
use self::service::TextMessageService;
use crate::text_message_service::{handle::TextMessageHandle, model::ReceivedTextMessage, service::TextMessageAck};
use futures::{future, stream::StreamExt, Future, Stream};
use log::*;
use std::sync::Arc;
use tari_broadcast_channel::bounded;
use tari_comms::types::CommsPublicKey;
use tari_comms_dht::outbound::OutboundMessageRequester;
use tari_p2p::{
comms_connector::PeerMessage,
domain_message::DomainMessage,
services::{
liveness::handle::LivenessHandle,
utils::{map_deserialized, ok_or_skip_result},
},
tari_message::{ExtendedMessage, TariMessageType},
};
use tari_pubsub::TopicSubscriptionFactory;
use tari_service_framework::{
handles::ServiceHandlesFuture,
reply_channel,
ServiceInitializationError,
ServiceInitializer,
};
use tokio::runtime::runtime::Handle;
const LOG_TARGET: &str = "wallet::text_message_service::initializer";
pub struct TextMessageServiceInitializer {
pub_key: Option<CommsPublicKey>,
database_path: Option<String>,
subscription_factory: Arc<TopicSubscriptionFactory<TariMessageType, Arc<PeerMessage<TariMessageType>>>>,
}
impl TextMessageServiceInitializer {
pub fn new(
subscription_factory: Arc<TopicSubscriptionFactory<TariMessageType, Arc<PeerMessage<TariMessageType>>>>,
pub_key: CommsPublicKey,
database_path: String,
) -> Self
{
Self {
pub_key: Some(pub_key),
database_path: Some(database_path),
subscription_factory,
}
}
fn text_message_stream(&self) -> impl Stream<Item = DomainMessage<ReceivedTextMessage>> {
self.subscription_factory
.get_subscription(TariMessageType::new(ExtendedMessage::Text))
.map(map_deserialized::<ReceivedTextMessage>)
.filter_map(ok_or_skip_result)
}
fn text_message_ack_stream(&self) -> impl Stream<Item = DomainMessage<TextMessageAck>> {
self.subscription_factory
.get_subscription(TariMessageType::new(ExtendedMessage::TextAck))
.map(map_deserialized::<TextMessageAck>)
.filter_map(ok_or_skip_result)
}
}
impl ServiceInitializer for TextMessageServiceInitializer {
type Future = impl Future<Output = Result<(), ServiceInitializationError>>;
fn initialize(&mut self, executor: runtime::Handle, handles_fut: ServiceHandlesFuture) -> Self::Future {
let pub_key = self
.pub_key
.take()
.expect("text message service initializer already called");
let database_path = self
.database_path
.take()
.expect("text message service initializer already called");
let (sender, receiver) = reply_channel::unbounded();
let (publisher, subscriber) = bounded(100, 117);
let text_message_stream = self.text_message_stream();
let text_message_ack_stream = self.text_message_ack_stream();
let tms_handle = TextMessageHandle::new(sender, subscriber);
handles_fut.register(tms_handle);
executor.spawn(async move {
let handles = handles_fut.await;
let oms = handles
.get_handle::<OutboundMessageRequester>()
.expect("OMS handle required for TextMessageService");
let liveness = handles
.get_handle::<LivenessHandle>()
.expect("Liveness handle required for TextMessageService");
let service = TextMessageService::new(
receiver,
text_message_stream,
text_message_ack_stream,
pub_key,
database_path,
oms,
liveness,
publisher,
);
match service.start().await {
Ok(_) => {
info!(target: LOG_TARGET, "Text message service initializer exited cleanly");
},
Err(err) => {
error!(target: LOG_TARGET, "Text message service failed to start: {}", err);
},
}
});
future::ready(Ok(()))
}
}