blob: e2adcf41290d23cb57136084cf4f067a8c7e1c23 [file]
use futures::future::{join, try_join, try_join_all};
use futures::Future;
use iggy::error::IggyError;
use local_sync::semaphore::Semaphore;
use sled::Db;
use std::pin::Pin;
use std::sync::atomic::AtomicBool;
use std::sync::Mutex;
use std::{rc::Rc, sync::Arc};
use crate::streaming::persistence::persister::PersistenceStorage;
use crate::tcp::tcp_server::spawn_tcp_server;
use crate::tcp::{tcp_listener, tcp_tls_listener};
use crate::{configs::server::ServerConfig, streaming::storage::SystemStorage, tcp::tcp_server};
use super::shard::tasks::message_task::spawn_shard_message_task;
use super::{
connector::ShardConnector,
shard::{
shard::{IggyShard, Shard, SHARD_NAME},
shard_frame::ShardFrame,
},
};
type Task = Pin<Box<dyn Future<Output = Result<(), IggyError>>>>;
pub fn create_shard(
id: u16,
init_gate: Arc<Mutex<()>>,
config: ServerConfig,
connections: Vec<ShardConnector<ShardFrame>>,
) -> Rc<IggyShard> {
let (stop_sender, stop_receiver, receiver) = connections
.iter()
.filter(|c| c.id == id)
.map(|c| {
(
c.stop_sender.clone(),
c.stop_receiver.clone(),
c.receiver.clone(),
)
})
.next()
.unwrap();
let shards = connections
.into_iter()
.map(|c| Shard::new(c.id, c))
.collect::<Vec<_>>();
let persister = match config.system.partition.enforce_fsync {
true => Rc::new(PersistenceStorage::FileWithSync),
false => Rc::new(PersistenceStorage::File),
};
let storage = Rc::new(SystemStorage::new(config.system.clone(), persister.clone()));
Rc::new(IggyShard::new(
id,
shards,
init_gate,
config,
storage,
persister,
receiver,
stop_receiver,
stop_sender,
))
}
pub async fn shard_executor(shard: Rc<IggyShard>, is_prime_thread: bool) -> Result<(), IggyError> {
// Workaround to ensure that the statistics are initialized before the server
// loads streams and starts accepting connections. This is necessary to
// have the correct statistics when the server starts.
shard.get_stats_bypass_auth().await?;
shard.init(is_prime_thread).await?;
// Create all tasks (tcp listener, http listener, command processor, in the future also the background jobs).
let mut tasks: Vec<Task> = vec![Box::pin(spawn_shard_message_task(shard.clone()))];
if shard.config.tcp.enabled {
tasks.push(Box::pin(spawn_tcp_server(shard.clone())));
}
let result = try_join_all(tasks).await;
result?;
// If its main thread, add to the list of joined tasks the task that will wait for the stop signal.
// join_all all tasks, if it fails, then we can move to the graceful shutdown stage,
Ok(())
}