subing works, although be it very prototype like

This commit is contained in:
Sebastian Moser
2024-08-21 13:18:40 +02:00
parent 125c4b066a
commit f1e7d6ed68
8 changed files with 167 additions and 19 deletions

View File

@@ -10,7 +10,7 @@ use super::Instance;
use crate::item::{get_raw_from_cbor, Item, ItemData}; use crate::item::{get_raw_from_cbor, Item, ItemData};
// only created with Instance::new_connection() // only created with Instance::new_connection()
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Connection { pub struct Connection {
pub tx: Sender<MizeMessage>, pub tx: Sender<MizeMessage>,
pub id: u64, pub id: u64,
@@ -22,7 +22,7 @@ pub trait ConnListener : Send + Sync {
} }
impl Connection { impl Connection {
pub fn send(&mut self, msg: MizeMessage) -> MizeResult<()> { pub fn send(&self, msg: MizeMessage) -> MizeResult<()> {
Ok(self.tx.send(msg)?) Ok(self.tx.send(msg)?)
} }
} }

View File

@@ -26,6 +26,7 @@ use crate::proto::MizeMessage;
use tokio::runtime::Handle; use tokio::runtime::Handle;
use self::connection::{ConnListener, Connection}; use self::connection::{ConnListener, Connection};
use self::updater::handle_operation;
#[cfg(feature = "async")] #[cfg(feature = "async")]
use tokio::runtime::Runtime; use tokio::runtime::Runtime;
@@ -46,7 +47,7 @@ pub struct Instance {
pub store: Arc<Mutex<Box<dyn Store>>>, pub store: Arc<Mutex<Box<dyn Store>>>,
connections: Arc<Mutex<Vec<Connection>>>, connections: Arc<Mutex<Vec<Connection>>>,
next_con_id: Arc<Mutex<u64>>, next_con_id: Arc<Mutex<u64>>,
subs: Arc<Mutex<HashMap<MizeId, Subscription>>>, subs: Arc<Mutex<HashMap<MizeId, Vec<Subscription>>>>,
pub id_pool: Arc<Mutex<VecStringPool>>, pub id_pool: Arc<Mutex<VecStringPool>>,
pub namespace_pool: Arc<Mutex<StringPool>>, pub namespace_pool: Arc<Mutex<StringPool>>,
@@ -148,8 +149,11 @@ impl Instance {
pub fn with_config(config: ItemData) -> MizeResult<Instance> { pub fn with_config(config: ItemData) -> MizeResult<Instance> {
trace!("[ {} ] Instance::with_config()", "CALL".yellow()); trace!("[ {} ] Instance::with_config()", "CALL".yellow());
trace!("config: {}", config); trace!("config: {}", config);
let mut instance = Instance::empty()?; let mut instance = Instance::empty()?;
instance.set("0", config.clone());
instance.set_blocking("0", config.clone());
instance.init()?; instance.init()?;
Ok(instance) Ok(instance)
@@ -211,6 +215,25 @@ impl Instance {
self.op_tx.send(Operation::Set(id, value.into())); self.op_tx.send(Operation::Set(id, value.into()));
Ok(()) Ok(())
} }
pub fn set_blocking<I: IntoMizeId, V: Into<ItemData>>(&self, id: I, value: V) -> MizeResult<()> {
handle_operation(&mut Operation::Set(id.to_mize_id(self)?, value.into()), self)?;
Ok(())
}
pub fn sub<I: IntoMizeId>(&self, id: I, sub: Subscription) -> MizeResult<()> {
let mut subs_inner = self.subs.lock()?;
let id = id.to_mize_id(self)?;
match subs_inner.get_mut(&id) {
Some(vec) => {
vec.push(sub);
},
None => {
subs_inner.insert(id, vec![sub]);
}
}
Ok(())
}
pub fn new_id<T: IntoMizeId>(&self, value: T) -> MizeResult<MizeId> { pub fn new_id<T: IntoMizeId>(&self, value: T) -> MizeResult<MizeId> {
value.to_mize_id(self) value.to_mize_id(self)

View File

@@ -1,4 +1,66 @@
use core::fmt;
use std::rc::Rc;
use crossbeam::channel::Sender;
use std::sync::Arc;
use tracing::trace;
use crate::id::MizeId;
use crate::instance::connection::Connection;
use crate::item::Item;
use crate::error::MizeResult;
use crate::proto::MizeMessage;
#[derive(Debug)] use super::Instance;
pub struct Subscription;
#[derive(Clone, Debug)]
pub struct Update {
pub instance: Arc<Instance>,
pub id: MizeId,
}
impl Update {
pub fn new_item(&self) -> MizeResult<Item> {
self.instance.get(self.id.clone())
}
}
pub enum Subscription {
Connection(Connection),
Closure(Box<dyn Fn(Update) -> MizeResult<()> + Send>),
Channel(Sender<Update>),
}
impl Subscription {
pub fn from_conn(conn: Connection) -> Subscription {
Subscription::Connection(conn)
}
pub fn from_closure(closure: Box<dyn Fn(Update) -> MizeResult<()> + Send>) -> Subscription {
Subscription::Closure(closure)
}
pub fn from_sender(tx: Sender<Update>) -> Subscription {
Subscription::Channel(tx)
}
pub fn handle(&mut self, update: Update) -> MizeResult<()> {
trace!("handleing update");
match &self {
Subscription::Connection(conn) => {
let msg = MizeMessage::new_update(update.id.clone(), update.new_item()?.as_data_full()?, conn.id);
conn.send(msg)?;
}
Subscription::Closure(closure) => {
closure(update)?
}
Subscription::Channel(tx) => {
tx.send(update);
}
}
Ok(())
}
}
impl fmt::Debug for Subscription {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "...Subscription...")
}
}

View File

@@ -1,5 +1,7 @@
use crossbeam::channel::Receiver; use crossbeam::channel::Receiver;
use tracing::{error, trace, warn}; use tracing::{error, trace, warn};
use std::borrow::BorrowMut;
use std::sync::Arc;
use crate::mize_err; use crate::mize_err;
use crate::{instance::Instance, item::ItemData}; use crate::{instance::Instance, item::ItemData};
@@ -8,6 +10,7 @@ use crate:: error::{MizeResult, MizeError, MizeResultTrait};
use crate::proto::{MessageCmd, MizeMessage}; use crate::proto::{MessageCmd, MizeMessage};
use super::connection::{self, Connection}; use super::connection::{self, Connection};
use super::subscription::{Subscription, Update};
#[derive(Debug)] #[derive(Debug)]
@@ -21,13 +24,18 @@ pub fn updater_thread(operation_rx : Receiver<Operation>, instance: &Instance) -
loop { loop {
let mut operation = operation_rx.recv()?; let mut operation = operation_rx.recv()?;
trace!("OPERATION {}", count); let op_str = match operation {
Operation::Set(_, _) => "SET",
Operation::Msg(_) => "MSG",
};
trace!("OPERATION {} - {}", count, op_str);
//let mut busy = instance.update_thread_busy.lock()?; //let mut busy = instance.update_thread_busy.lock()?;
let result = handle_operation(&mut operation, instance); let result = handle_operation(&mut operation, instance);
trace!("OPERATION DONE {}", count); trace!("OPERATION {} DONE", count);
count += 1; count += 1;
if let Err(err) = result { if let Err(err) = result {
@@ -40,12 +48,26 @@ pub fn updater_thread(operation_rx : Receiver<Operation>, instance: &Instance) -
Ok(()) Ok(())
} }
fn handle_operation(operation: &mut Operation, instance: &Instance) -> MizeResult<()> { pub fn handle_operation(operation: &mut Operation, instance: &Instance) -> MizeResult<()> {
match operation { match operation {
Operation::Set(id, value) => { Operation::Set(id, value) => {
let item_data: ItemData = value.to_owned(); let item_data: ItemData = value.to_owned();
let mut item = instance.get(id.clone())?; let mut item = instance.get(id.clone())?;
item.merge(item_data)?; item.merge(item_data)?;
//check subs and handle them
let mut subs_inner = instance.subs.lock()?;
println!("goooooooooooooooooot some subs: {:?}", subs_inner);
println!("some subs id: {:?}", id);
if let Some(vec) = subs_inner.get_mut(&id) {
let update = Update {
instance: Arc::new(instance.to_owned()),
id: id.clone(),
};
for sub in vec.iter_mut() {
sub.handle(update.clone());
}
}
}, },
Operation::Msg(msg) => { Operation::Msg(msg) => {
handle_msg(msg, instance)? handle_msg(msg, instance)?
@@ -64,10 +86,20 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
connection.send(msg)?; connection.send(msg)?;
}, },
MessageCmd::GetSub => {
let id = msg.id(instance)?;
let mut connection = instance.get_connection(msg.conn_id)?.clone();
let item = instance.get(id.clone())?;
let msg = MizeMessage::new_give(id.clone(), item.as_data_full()?, msg.conn_id);
connection.send(msg)?;
let sub = Subscription::from_conn(connection.clone());
instance.sub(id, sub)?;
},
MessageCmd::Update => { MessageCmd::Update => {
let data = msg.data()?; let data = msg.data()?;
let id = msg.id(instance)?; let id = msg.id(instance)?;
instance.set(id, data); instance.set(id.clone(), data);
}, },
// this should check, if the update is valid // this should check, if the update is valid
@@ -75,7 +107,7 @@ fn handle_msg(msg: &mut MizeMessage, instance: &Instance) -> MizeResult<()> {
MessageCmd::UpdateRequest => { MessageCmd::UpdateRequest => {
let data = msg.data()?; let data = msg.data()?;
let id = msg.id(instance)?; let id = msg.id(instance)?;
instance.set(id, data); instance.set(id.clone(), data);
}, },
MessageCmd::Give => { MessageCmd::Give => {

View File

@@ -107,14 +107,14 @@ impl Item<'_> {
pub fn merge<V: Into<ItemData>>(&mut self, mut value: V) -> MizeResult<()> { pub fn merge<V: Into<ItemData>>(&mut self, mut value: V) -> MizeResult<()> {
println!("before as_data_full: {}", self.instance.op_tx.len());
let mut data = self.as_data_full()?; let mut data = self.as_data_full()?;
println!("data: {:?}", data); println!("item::merge data: {:?}", data);
println!("item::merge id: {:?}", self.id());
let new_data = value.into(); let new_data = value.into();
data.merge(new_data); data.merge(new_data);
println!("new_data: {:?}", data); println!("item::merge new_data: {:?}", data);
if self.instance.we_are_namespace()? { if self.instance.we_are_namespace()? {
let store_inner = self.instance.store.lock()?; let store_inner = self.instance.store.lock()?;

View File

@@ -25,6 +25,7 @@ static CMD_GIVE: u16 = 3;
static CMD_CREATE: u16 = 4; static CMD_CREATE: u16 = 4;
static CMD_CREATE_REPLY: u16 = 5; static CMD_CREATE_REPLY: u16 = 5;
static CMD_UPDATE_REQUEST: u16 = 6; static CMD_UPDATE_REQUEST: u16 = 6;
static CMD_GET_SUB: u16 = 7;
#[derive(Debug)] #[derive(Debug)]
pub enum MessageCmd { pub enum MessageCmd {
@@ -34,6 +35,7 @@ pub enum MessageCmd {
Create, Create,
CreateReply, CreateReply,
UpdateRequest, UpdateRequest,
GetSub,
} }
@@ -54,6 +56,16 @@ impl MizeMessage {
MizeMessage::new(value, conn_id) MizeMessage::new(value, conn_id)
} }
pub fn new_get_sub(id: MizeId, conn_id: u64) -> MizeMessage {
let id_path = id.path().into_iter().map(|string| CborValue::Text(string.to_owned())).collect();
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_GET_SUB.into()));
let id = (CborValue::Integer(MSG_ID.into()), CborValue::Array(id_path));
let value = CborValue::Map(vec![cmd, id]);
MizeMessage::new(value, conn_id)
}
pub fn new_create(conn_id: u64) -> MizeMessage { pub fn new_create(conn_id: u64) -> MizeMessage {
let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_CREATE.into())); let cmd = (CborValue::Integer(MSG_CMD.into()), CborValue::Integer(CMD_CREATE.into()));
let value = CborValue::Map(vec![cmd]); let value = CborValue::Map(vec![cmd]);

View File

@@ -1,12 +1,29 @@
use clap::ArgMatches; use clap::ArgMatches;
use mize::error::MizeResult; use crossbeam::channel::{bounded, unbounded};
use mize::error::{MizeResult, MizeError};
use mize::instance::subscription::{Subscription, Update};
use mize::instance::Instance; use mize::instance::Instance;
use mize::platform::os::config_from_cli_args;
pub fn show(sub_matches: &ArgMatches) -> MizeResult<()> { pub fn show(sub_matches: &ArgMatches) -> MizeResult<()> {
let instance = Instance::new()?; let instance = Instance::with_config(config_from_cli_args(sub_matches)?)?;
println!("0/config/test is: {}", instance.get("0/config/test")?); let id = sub_matches.get_one::<String>("id")
.ok_or(MizeError::new().msg("No id Argument specified"))?;
let item = instance.get(id)?;
let (tx, rx) = bounded::<Update>(4);
let sub = Subscription::from_sender(tx);
instance.sub(id, sub)?;
println!("ItemData: {}", item.as_data_full()?);
for update in rx {
println!("####### GOT UPDATE #######");
println!("ItemData: {}", update.new_item()?.as_data_full()?);
}
Ok(()) Ok(())
} }

View File

@@ -30,7 +30,7 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
Ok(config_file_path) => { Ok(config_file_path) => {
let config = config_from_file(config_file_path)?; let config = config_from_file(config_file_path)?;
debug!("env var MIZE_CONFIG_FILE present"); debug!("env var MIZE_CONFIG_FILE present");
instance.set("0", config)?; instance.set_blocking("0", config)?;
trace!("config after MIZE_CONFIG_FILE env var: {}", instance.get("0/config")?); trace!("config after MIZE_CONFIG_FILE env var: {}", instance.get("0/config")?);
} }
Err(var_err) => match var_err { Err(var_err) => match var_err {
@@ -48,7 +48,7 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
Ok(config_string) => { Ok(config_string) => {
let config = config_from_string(config_string)?; let config = config_from_string(config_string)?;
debug!("env var MIZE_CONFIG present"); debug!("env var MIZE_CONFIG present");
instance.set("0", config)?; instance.set_blocking("0", config)?;
trace!("config after MIZE_CONFIG env var: {}", instance.get("0/config")?); trace!("config after MIZE_CONFIG env var: {}", instance.get("0/config")?);
} }
Err(var_err) => match var_err { Err(var_err) => match var_err {
@@ -62,6 +62,8 @@ pub fn os_instance_init(instance: &mut Instance) -> MizeResult<()> {
}; };
////// if a config.store_path is set, upgrade to the filestore there ////// if a config.store_path is set, upgrade to the filestore there
let mut test = instance.get("0")?.as_data_full()?;
println!("os::Mod test: {}", test);
let mut store_path = instance.get("0/config/store_path")?.value_string()?; let mut store_path = instance.get("0/config/store_path")?.value_string()?;
if store_path == "" { if store_path == "" {