fresh start
This commit is contained in:
2826
Cargo.lock
generated
2826
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
37
Cargo.toml
37
Cargo.toml
@@ -1,24 +1,23 @@
|
||||
[package]
|
||||
name = "mize"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.6.1", features = ["ws", "headers"] }
|
||||
axum-extra = { version = "0.4.2", features = ["spa"] }
|
||||
axum-macros = "0.3.0"
|
||||
colored = "2.0.0"
|
||||
derive_more = "0.99.17"
|
||||
futures-util = "0.3.24"
|
||||
itertools = "0.10.5"
|
||||
lazy_static = "1.4.0"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
surrealdb = { version = "1.0.0-beta.7", features = ["kv-rocksdb"] }
|
||||
tokio = {version = "1.21.0", features = ["full"]}
|
||||
tokio-stream = "0.1.9"
|
||||
toml = "0.5.10"
|
||||
tower-http = "0.3.5"
|
||||
uuid = "1.3.0"
|
||||
#axum = { version = "0.6.1", features = ["ws", "headers"] }
|
||||
#axum-extra = { version = "0.4.2", features = ["spa"] }
|
||||
#axum-macros = "0.3.0"
|
||||
#colored = "2.0.0"
|
||||
#derive_more = "0.99.17"
|
||||
#futures-util = "0.3.24"
|
||||
#itertools = "0.10.5"
|
||||
#lazy_static = "1.4.0"
|
||||
#rmp-serde = "1.1.1"
|
||||
#rmpv = { version = "1.0.0", features = ["serde", "with-serde"] }
|
||||
#serde = "1.0.152"
|
||||
#serde_json = "1.0.91"
|
||||
#tokio = {version = "1.21.0", features = ["full"]}
|
||||
#tokio-stream = "0.1.9"
|
||||
#toml = "0.5.10"
|
||||
#tower-http = "0.3.5"
|
||||
#uuid = "1.3.0"
|
||||
|
||||
107
errors.toml
107
errors.toml
@@ -1,107 +0,0 @@
|
||||
|
||||
[[error]]
|
||||
code = 11
|
||||
category = "don't know yet"
|
||||
message = "Something went wrong. //TODO: give this error it's own category and code."
|
||||
|
||||
[[error]]
|
||||
category = "data_storage"
|
||||
code = 28
|
||||
message = "Something went wrong in the data storage."
|
||||
|
||||
[[error]]
|
||||
code = 29
|
||||
category = "data_storage:surrealdb_error"
|
||||
message = "Something went wrong internally with the data-storage (surrealdb/rocksdb): {}"
|
||||
|
||||
[[error]]
|
||||
code = 30
|
||||
category = "data_storage:surrealdb_error"
|
||||
message = "Could not create data_storeage at {}"
|
||||
|
||||
[[error]]
|
||||
code = 31
|
||||
category = "data_storage:surrealdb_error"
|
||||
message = "No item with id 0. There definetly should be one"
|
||||
|
||||
[[error]]
|
||||
code = 32
|
||||
category = "data_storage"
|
||||
message = "item {} was not found in storage"
|
||||
|
||||
[[error]]
|
||||
code = 100
|
||||
category = "don't know yet"
|
||||
message = "You can't delete item number 0. This item contains mandatory Config for the Server."
|
||||
|
||||
[[error]]
|
||||
code = 101
|
||||
category = "key_missing::item0::num_of_items"
|
||||
message = "num_of_items missing in item0"
|
||||
|
||||
[[error]]
|
||||
code = 102
|
||||
category = "key_missing::item0::next_free_id"
|
||||
message = "next_free_id missing in item0"
|
||||
|
||||
[[error]]
|
||||
message = "_commit missing in item0"
|
||||
code = 103
|
||||
category = "key_missing::item0::_commit"
|
||||
|
||||
[[error]]
|
||||
message = "_commit missing"
|
||||
code = 103
|
||||
category = "key_missing::_commit"
|
||||
|
||||
[[error]]
|
||||
code = 104
|
||||
category = "data_storage::index_not_found"
|
||||
message = "could not read index of item"
|
||||
|
||||
[[error]]
|
||||
code = 105
|
||||
category = "don't know yet"
|
||||
message = "_commit not 8 bytes long"
|
||||
|
||||
[[error]]
|
||||
code = 106
|
||||
category = "parse_error"
|
||||
message = "error while parsing to an int"
|
||||
|
||||
[[error]]
|
||||
code = 107
|
||||
category = "faulty_message"
|
||||
message = "some error with message sent to the server"
|
||||
|
||||
[[error]]
|
||||
code = 108
|
||||
category = "faulty_message"
|
||||
message = "There was not metadata in a message, that should have some."
|
||||
|
||||
[[error]]
|
||||
code = 109
|
||||
category = "faulty_message"
|
||||
message = "something that should be utf8 valid was not"
|
||||
|
||||
[[error]]
|
||||
code = 111
|
||||
category = "faulty_update"
|
||||
message = "mize-commit can't be updated manually"
|
||||
|
||||
[[error]]
|
||||
code = 113
|
||||
category = "don't know yet"
|
||||
message = "module header not a String"
|
||||
|
||||
[[error]]
|
||||
code = 114
|
||||
category = "error with error system"
|
||||
message = "the error with code {} was not found in the errors.toml file"
|
||||
|
||||
[[error]]
|
||||
code = 115
|
||||
category = "WebSocket Error"
|
||||
message = "Error reviecing a message from the WebSocket"
|
||||
|
||||
|
||||
Submodule js-client updated: 53c3b6cc38...ad865dac9b
@@ -1,15 +0,0 @@
|
||||
|
||||
# The miZe Protocol
|
||||
|
||||
Simple Messages that are sent between client and server via WebSockets or unix sockets.
|
||||
|
||||
## A Message
|
||||
|
||||
|
||||
## Commands
|
||||
|
||||
### From client to server
|
||||
-
|
||||
|
||||
### From server to client
|
||||
|
||||
254
src/error.rs
254
src/error.rs
@@ -1,254 +0,0 @@
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::format;
|
||||
use std::string::FromUtf8Error;
|
||||
use toml::Value;
|
||||
use colored::Colorize;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use toml;
|
||||
|
||||
use crate::server::proto::{self, JsonMessage};
|
||||
use crate::error::proto::ErrMessage;
|
||||
use crate::server::proto::MizeMessage;
|
||||
use crate::server::Peer;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref ERRORS: HashMap<u32, MizeError> = parse_errors();
|
||||
}
|
||||
|
||||
fn parse_errors() -> HashMap<u32, MizeError>{
|
||||
let mut map = HashMap::new();
|
||||
let binding = include_str!("../errors.toml")
|
||||
.parse::<Value>()
|
||||
.expect("Error pasting errors.toml file to Toml.");
|
||||
|
||||
let toml_error = binding.get("error")
|
||||
.expect("Error getting error table from errors.toml file for Error handling");
|
||||
|
||||
if let Value::Array(error_arr) = toml_error {
|
||||
for err in error_arr {
|
||||
|
||||
let code: u32 = if let Value::Integer(code) = err.get("code")
|
||||
.expect("some error object in errors.toml has no code field.") {
|
||||
u32::try_from(*code).expect(&format!("Error converting the error code {} &i64 to u32", code))
|
||||
} else {
|
||||
panic!("code value exists in errors.toml, but is not an Integer")
|
||||
};
|
||||
|
||||
let message = if let Value::String(message) = err.get("message")
|
||||
.unwrap_or(&Value::String("".to_string())) {message.to_string()} else {
|
||||
panic!("message value exists in errors.toml on error obect with code {}, but is not a String", code)
|
||||
};
|
||||
|
||||
let category = if let Value::String(category) = err.get("category")
|
||||
.expect(&format!("the error object in errors.toml with code {} has no category field", code)) {category.to_string()} else {
|
||||
panic!("category value exists in errors.toml on error obect with code {}, but is not a String", code)
|
||||
};
|
||||
|
||||
let error = MizeError{code, message, category, extra_msg: Vec::new(), caused_by_msg: None, code_location: None};
|
||||
|
||||
map.insert(code, error);
|
||||
}
|
||||
} else {
|
||||
panic!("errors.toml File wrong. error path is not an array")
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MizeError {
|
||||
pub category: String,
|
||||
pub code: u32,
|
||||
pub message: String,
|
||||
pub extra_msg: Vec<String>,
|
||||
pub caused_by_msg: Option<CausedByMessage>,
|
||||
pub code_location: Option<MizeCodeLocation>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CausedByMessage {
|
||||
client_id: u64,
|
||||
msg: Box<JsonMessage>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MizeCodeLocation {
|
||||
file: String,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
impl From<&std::panic::Location <'_>> for MizeCodeLocation {
|
||||
fn from(panic_location: &std::panic::Location) -> MizeCodeLocation {
|
||||
let file = panic_location.file().to_string();
|
||||
let line = panic_location.line();
|
||||
let column = panic_location.column();
|
||||
MizeCodeLocation {file, line, column}
|
||||
}
|
||||
}
|
||||
|
||||
impl MizeError {
|
||||
#[track_caller]
|
||||
pub fn new(code: u32) -> MizeError {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
|
||||
if let Some(err_ref) = ERRORS.get(&code) {
|
||||
let mut err = err_ref.clone();
|
||||
err.code_location = Some(caller_location.into());
|
||||
return err;
|
||||
} else {
|
||||
return MizeError {
|
||||
category: "error with error system".to_string(),
|
||||
code: 114,
|
||||
message: format!("The error with code {} was not found in the Errors that where imported from the errors.toml file at build time.", code),
|
||||
extra_msg: Vec::new(),
|
||||
caused_by_msg: None,
|
||||
code_location: Some(caller_location.into()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extra_msg<E>(mut self, msg: E) -> MizeError
|
||||
where E: std::fmt::Display
|
||||
{
|
||||
self.extra_msg.push(format!("{}", msg));
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn format(mut self, values: Vec<&str>) -> MizeError {
|
||||
let count = 0;
|
||||
for val in values {
|
||||
self.message += &(" FORMAT_".to_string() + &format!("{}", count) + ": " + val)
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
fn set_msg(self, msg: MizeMessage, origin: Peer) -> MizeError {
|
||||
MizeError::new(11).extra_msg("in set_msg TODO!!")
|
||||
}
|
||||
|
||||
fn send(self) -> MizeError{
|
||||
self
|
||||
}
|
||||
|
||||
fn add_to_err_item(self) -> MizeError {
|
||||
self
|
||||
}
|
||||
|
||||
fn write_to_stderr(self) -> MizeError {
|
||||
eprintln!("[{}] {}", "ERROR".red(), self.to_json());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn handle(self) -> MizeError {
|
||||
return self.send().add_to_err_item().write_to_stderr();
|
||||
}
|
||||
|
||||
pub fn is_critical(self){
|
||||
panic!("Aborting because of a critical Error")
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> JsonValue{
|
||||
if let Ok(string) = serde_json::to_string(self) {
|
||||
if let Ok(json) = serde_json::from_str(&string) {
|
||||
return json;
|
||||
} else {
|
||||
return serde_json::json!({
|
||||
"category": "error with error system",
|
||||
"code": 114,
|
||||
"message": "error converting a String to a JsonValue for the ErrMsg",
|
||||
})
|
||||
}
|
||||
} else {
|
||||
return serde_json::json!({
|
||||
"category": "error with error system",
|
||||
"code": 114,
|
||||
"message": "error converting an MizeError to String",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_json_message(self) -> JsonMessage {
|
||||
proto::JsonMessage::ErrMsg(
|
||||
ErrMessage{
|
||||
err: self,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MizeResultExtension<T> {
|
||||
fn extra_msg<E>(self, msg: E) -> Result<T, MizeError>
|
||||
where E: std::fmt::Display
|
||||
;
|
||||
fn handle(self) -> Result<T, MizeError>;
|
||||
|
||||
fn is_critical(self) -> T;
|
||||
}
|
||||
|
||||
impl<T> MizeResultExtension<T> for Result<T, MizeError> {
|
||||
fn extra_msg<E>(mut self, msg: E) -> Result<T, MizeError>
|
||||
where E: std::fmt::Display
|
||||
{
|
||||
match self {
|
||||
Err(ref mut e) => {
|
||||
e.extra_msg.push(format!("{}", msg));
|
||||
return self;
|
||||
},
|
||||
Ok(something) => Ok(something),
|
||||
}
|
||||
}
|
||||
fn handle(self) -> Result<T, MizeError> {
|
||||
match self {
|
||||
Err(e) => {
|
||||
Err(e.send().add_to_err_item().write_to_stderr())
|
||||
},
|
||||
Ok(something) => Ok(something)
|
||||
}
|
||||
}
|
||||
fn is_critical(self) -> T {
|
||||
self.expect("Aborting because of a critical Error")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FromUtf8Error> for MizeError {
|
||||
#[track_caller]
|
||||
fn from(utf_err: FromUtf8Error) -> MizeError{
|
||||
let caller_location = std::panic::Location::caller();
|
||||
|
||||
let mut err = MizeError::new(109).extra_msg(format!("From std::string::FromUtf8Error: {}", utf_err));
|
||||
err.code_location = Some(caller_location.into());
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<surrealdb::error::Db> for MizeError {
|
||||
#[track_caller]
|
||||
fn from(sur_err: surrealdb::error::Db) -> MizeError {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
|
||||
let mut err = MizeError::new(129).extra_msg(format!("From surrealdb Error: {}", sur_err));
|
||||
err.code_location = Some(caller_location.into());
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for MizeError {
|
||||
#[track_caller]
|
||||
fn from(serde_err: serde_json::Error) -> MizeError {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
|
||||
let mut err = MizeError::new(11).extra_msg(format!("From an serde_json::Error: {}", serde_err));
|
||||
err.code_location = Some(caller_location.into());
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use hyper::{Body, Request, Response, Server};
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::body::Bytes;
|
||||
|
||||
#[tokio::main]
|
||||
async fn hyper_server() {
|
||||
// Construct our SocketAddr to listen on...
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||
|
||||
// And a MakeService to handle each connection...
|
||||
let make_service = make_service_fn(|_conn| async {
|
||||
Ok::<_, Infallible>(service_fn(handle))
|
||||
});
|
||||
|
||||
// Then bind and serve...
|
||||
let server = Server::bind(&addr).serve(make_service);
|
||||
|
||||
// And run forever...
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("server error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
let (mut sender, _body) = Body::channel();
|
||||
sender.send_data(Bytes::from("sending from the sender\n"));
|
||||
sender.abort();
|
||||
println!("{:?}", req.body());
|
||||
//println!("{:?}", Body::to_bytes());
|
||||
Ok(Response::new(Body::from("hi")))
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
pub fn main(){}
|
||||
13
src/lib.rs
13
src/lib.rs
@@ -1,13 +0,0 @@
|
||||
|
||||
#![ allow( warnings ) ]
|
||||
|
||||
static PROTO_VERSION: u8 = 1;
|
||||
|
||||
pub mod server;
|
||||
pub mod error;
|
||||
pub mod integrated_types {
|
||||
pub mod test_same;
|
||||
}
|
||||
|
||||
|
||||
|
||||
91
src/main.rs
91
src/main.rs
@@ -1,91 +0,0 @@
|
||||
|
||||
#![ allow( warnings ) ]
|
||||
|
||||
extern crate mize;
|
||||
|
||||
static HELP_MESSAGE: &str = "\
|
||||
Usage:
|
||||
mize-server [options] [command] [options for command]
|
||||
|
||||
Available Commands:
|
||||
run starts the server
|
||||
help prints this help message
|
||||
version prints the version
|
||||
import imports a file as a item of type file into the server
|
||||
|
||||
Available options
|
||||
-h --help prints this help message
|
||||
-v --version prints the version
|
||||
-f --folder the mize-server-folder
|
||||
";
|
||||
|
||||
//some flags e.g: "--file /tmp" can require that the next argument belongs to them instead of being
|
||||
//the command
|
||||
static FLAGS_WITH_ARGUMENTS: [&str; 2] = ["--folder", "-f"];
|
||||
|
||||
static AVAILABLE_COMMANDS: [&str; 6] = ["run", "help", "version", "import-js", "import-render", "import"];
|
||||
|
||||
static AVAILABLE_FLAGS: [&str; 4] = ["--version", "--help", "--folder", "-f"];
|
||||
//static AVAILABLE_ONE_LETTER_FLAGS: [&str; 2] = ["v", "h"];
|
||||
|
||||
static VERSION_MESSAGE: &str = "\
|
||||
Version: 0
|
||||
";
|
||||
|
||||
|
||||
fn main() {
|
||||
/*
|
||||
* WHAT IT DOES
|
||||
* - get the arguments passed to the programm
|
||||
*
|
||||
* - sort out the flags for the main programm and the args for the comand
|
||||
* - in "mize -h -u --lol server --file=/tmp --folder /home" the flags for the main programm would be ["-h","-u","--lol"]
|
||||
* - and the args for the command would be ["server", "--file=/tmp --folder /home"]
|
||||
*
|
||||
* - get the command to "run"
|
||||
* - in "mize -h -u --lol server --file=/tmp" it would be "server"
|
||||
*
|
||||
* - "run" the command and pass the options and subcommands to it
|
||||
*
|
||||
*/
|
||||
|
||||
//### get the arguments passed to the programm
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
|
||||
//### sort out the flags for the main program and the args for the command
|
||||
let mut main_flags:Vec<String> = Vec::new();
|
||||
let mut command= String::from("");
|
||||
let mut command_args = Vec::new();
|
||||
|
||||
for i in 1..args.len() {
|
||||
if args[i].chars().next().unwrap() == '-' {
|
||||
main_flags.push(args[i].clone());
|
||||
// i != 0 bcs what if the programm name is in FLAGS_WITH_ARGUMENTS for some reason?
|
||||
} else if i != 0 && FLAGS_WITH_ARGUMENTS.contains(&&args[i -1][..]) {
|
||||
main_flags.push(args[i].clone());
|
||||
|
||||
//#### get the command to "run"
|
||||
} else if AVAILABLE_COMMANDS.contains(&&args[i][..]){
|
||||
command = args[i].clone();
|
||||
for a in i..args.len(){
|
||||
command_args.push(args[a].clone());
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
println!("Command \"{}\" not found!!\n", args[i]);
|
||||
println!("{}", HELP_MESSAGE);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//#### "run" the command and pass the options and subcommands to it
|
||||
match &command[..] {
|
||||
"run" => mize::server::run_server(args),
|
||||
"import" => mize::server::server_utils::import(args),
|
||||
"help" => println!("{}", HELP_MESSAGE),
|
||||
"version" => println!("{}", VERSION_MESSAGE),
|
||||
_ => {println!("Command not found!!\n"); println!("{}", HELP_MESSAGE);},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
656
src/server.rs
656
src/server.rs
@@ -1,656 +0,0 @@
|
||||
|
||||
|
||||
pub mod server_utils;
|
||||
pub mod itemstore;
|
||||
|
||||
pub mod proto;
|
||||
|
||||
//use futures_util::lock::Mutex;
|
||||
use futures_util::{FutureExt, StreamExt, SinkExt};
|
||||
use std::collections::HashMap;
|
||||
use std::boxed::Box;
|
||||
use std::path::Path;
|
||||
use crate::error;
|
||||
use crate::error::MizeError;
|
||||
use crate::error::ERRORS;
|
||||
use crate::server::proto::MizeMessage;
|
||||
use crate::server::proto::MizeId;
|
||||
use crate::server::proto::Update;
|
||||
use crate::server::proto::update_thread;
|
||||
use crate::error::MizeResultExtension;
|
||||
|
||||
use serde_json::Value as JsonValue;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use uuid::Uuid;
|
||||
use std::str::FromStr;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use tokio::sync::mpsc::{Sender, channel, Receiver};
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
use std::alloc::handle_alloc_error;
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use self::itemstore::Itemstore;
|
||||
|
||||
use axum_extra::routing::SpaRouter;
|
||||
use axum::Router;
|
||||
use axum::routing::{get, get_service};
|
||||
use std::net::SocketAddr;
|
||||
use axum::response::{IntoResponse, Html};
|
||||
use axum::extract::ws::{Message, WebSocket, WebSocketUpgrade, CloseFrame};
|
||||
use axum::extract::{State, self};
|
||||
use axum::http::{StatusCode, Uri, Response, self};
|
||||
use axum::http::header::{HeaderName, HeaderValue, HeaderMap};
|
||||
use tower_http::services::{ServeDir, ServeFile};
|
||||
|
||||
static SERVER_PORT: u16 = 9432;
|
||||
|
||||
//static API_PATH_STRING: &str = "$api";
|
||||
static SOCKET_CHANNEL_SIZE: usize = 200;
|
||||
static UPDATE_CHANNEL_SIZE: usize = 200;
|
||||
|
||||
// max file sizez in the mize/data folder (in bytes)
|
||||
static MAX_INDEX_FILE_SIZE: usize = 1_800_000;
|
||||
static MAX_FIELDS_FILE_SIZE: usize = 2_600_000;
|
||||
static MAX_KEYS_FILE_SIZE: usize = 30_000_000;
|
||||
static MAX_DATA_FILE_SIZE: usize = 3_000_000_000;
|
||||
|
||||
|
||||
//static HELP_MESSAGE: &str = "\
|
||||
//Usage:
|
||||
//mize-server server [options]
|
||||
//
|
||||
//Available options
|
||||
//-h --help prints this help message
|
||||
//-v --version prints the version
|
||||
//--folder=<folder> mize-folder: where mize stores all it's stuff.
|
||||
//";
|
||||
|
||||
//some flags e.g: "--file /tmp" can require that the next argument belongs to them instead of being
|
||||
//the command
|
||||
//static FLAGS_WITH_ARGUMENTS: [&str; 0] = [];
|
||||
|
||||
//static AVAILABLE_COMMANDS: [&str; 3] = ["run", "help", "version"];
|
||||
|
||||
//static AVAILABLE_FLAGS: [&str; 2] = ["--version", "--help"];
|
||||
//static AVAILABLE_ONE_LETTER_FLAGS: [&str; 2] = ["v", "h"];
|
||||
|
||||
//static VERSION_MESSAGE: &str = "\
|
||||
//Version: 0
|
||||
//";
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Peer {
|
||||
Client(Client), //the client id
|
||||
Module(Module), //Module_name
|
||||
Upstream(Upstream), //a hostname Type, but for now just a string
|
||||
}
|
||||
|
||||
impl Peer {
|
||||
pub async fn send<T> (&self, message: T) where T: Into<proto::MizeMessage>{
|
||||
let message: proto::MizeMessage = message.into();
|
||||
match self {
|
||||
Peer::Client(client) => {client.tx.send(message).await;},
|
||||
Peer::Module(module) => {module.tx.send(message).await;},
|
||||
Peer::Upstream(_) => {},
|
||||
}
|
||||
}
|
||||
pub fn get_id(&self) -> u64{
|
||||
match self {
|
||||
Peer::Client(client) => client.id,
|
||||
Peer::Module(module) => module.client_id,
|
||||
Peer::Upstream(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Upstream {
|
||||
id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client {
|
||||
// rx: UnboundedReceiverStream<Result<ws::Message, warp::Error>>,
|
||||
tx: Sender<proto::MizeMessage>,
|
||||
id: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Module {
|
||||
tx: Sender<proto::MizeMessage>,
|
||||
name: String,
|
||||
client_id: u64,
|
||||
kind: ModuleKind,
|
||||
registered_types: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ModuleKind {
|
||||
Rust(),
|
||||
Python(),
|
||||
JS(),
|
||||
Lua(),
|
||||
|
||||
//connects to ws server
|
||||
Extern(),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct Render {
|
||||
#[serde(rename="type")]
|
||||
render_type: RenderType,
|
||||
webroot: String,
|
||||
name: String,
|
||||
main: String,
|
||||
folder: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub enum RenderType {
|
||||
#[serde(rename="json-ui")]
|
||||
JsonUi,
|
||||
#[serde(rename="webcomponent")]
|
||||
WebComponent,
|
||||
}
|
||||
|
||||
trait SendMize<T> where T: Into<MizeMessage> {
|
||||
fn send(&self, msg: T);
|
||||
}
|
||||
|
||||
impl<T> SendMize<T> for Sender<MizeMessage> where MizeMessage: From<T> {
|
||||
fn send(&self, msg: T){
|
||||
self.send(msg.into());
|
||||
}
|
||||
}
|
||||
|
||||
//pub struct Upstream maybe???? ... I'd say later....
|
||||
|
||||
|
||||
// A collection of all the things, that most functions need
|
||||
#[derive(Clone)]
|
||||
pub struct Mutexes {
|
||||
next_free_client_id: Arc<Mutex<u64>>,
|
||||
clients: Arc<Mutex<Vec<Client>>>,
|
||||
modules: Arc<Mutex<Vec<Module>>>,
|
||||
subs: Arc<Mutex<HashMap<MizeId, Vec<Peer>>>>,
|
||||
renders: Arc<Mutex<Vec<Render>>>,
|
||||
//maybe a list of upstream servers??
|
||||
itemstore: Arc<Mutex<Itemstore>>,
|
||||
mize_folder: String,
|
||||
server_uuid: Uuid,
|
||||
update_tx: mpsc::Sender<(Update, Peer)>,
|
||||
}
|
||||
|
||||
impl Mutexes {
|
||||
pub fn clone(mutexes: &Mutexes) -> Mutexes {
|
||||
Mutexes {
|
||||
next_free_client_id: Arc::clone(&mutexes.next_free_client_id),
|
||||
clients: Arc::clone(&mutexes.clients),
|
||||
modules: Arc::clone(&mutexes.modules),
|
||||
renders: Arc::clone(&mutexes.renders),
|
||||
subs: Arc::clone(&mutexes.subs),
|
||||
mize_folder: mutexes.mize_folder.clone(),
|
||||
itemstore: Arc::clone(&mutexes.itemstore),
|
||||
server_uuid: mutexes.server_uuid,
|
||||
update_tx: mutexes.update_tx.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn run_server(args: Vec<String>) {
|
||||
/*
|
||||
* WHAT IT DOES
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
//### get the mize_folder
|
||||
let mut mize_folder = String::new();
|
||||
for i in 1..args.len() {
|
||||
if args[i].contains('=') {
|
||||
let split: Vec<_> = args[i].split('=').collect();
|
||||
if split[0] == "--folder" {
|
||||
mize_folder += split[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let (server_uuid, itemstore, renders) = init_server(mize_folder.clone()).await.extra_msg("Could not init server").handle().is_critical();
|
||||
|
||||
// the channel to send updates to, that are then handeled in another thread
|
||||
let (update_tx, update_rx) = mpsc::channel::<(Update, Peer)>(UPDATE_CHANNEL_SIZE);
|
||||
|
||||
// Collection of all the things, that most functions need
|
||||
let mutexes: Mutexes = Mutexes {
|
||||
next_free_client_id: Arc::new(Mutex::new(0)),
|
||||
clients: Arc::new(Mutex::new(Vec::new())),
|
||||
subs: Arc::new(Mutex::new(HashMap::new())),
|
||||
modules: Arc::new(Mutex::new(Vec::new())),
|
||||
renders: Arc::new(Mutex::new(renders)),
|
||||
itemstore: Arc::new(Mutex::new(itemstore)),
|
||||
mize_folder: mize_folder.clone(),
|
||||
server_uuid,
|
||||
update_tx,
|
||||
};
|
||||
|
||||
// the update handling task
|
||||
let update_mutexes = mutexes.clone();
|
||||
tokio::spawn(async move {
|
||||
proto::update_thread(update_rx, update_mutexes).await.handle().extra_msg("update thread crashed").is_critical();
|
||||
});
|
||||
|
||||
|
||||
//listen on the local unix socket
|
||||
//local_socket_server(mize_folder);
|
||||
|
||||
//run the webserver
|
||||
axum_server(mize_folder, mutexes).await;
|
||||
}
|
||||
|
||||
|
||||
async fn axum_server(mize_folder: String, mutexes: Mutexes) {
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//### Main Endpoints:
|
||||
//## any number (with "-" in them) is interpreted as an item id
|
||||
//## $api/socket/id
|
||||
//## $api/rest/
|
||||
|
||||
let mutexes_clone = Mutexes::clone(&mutexes);
|
||||
|
||||
let serve_client = get_service(ServeDir::new("js-client/src")).handle_error(handle_error);
|
||||
|
||||
let mut app = Router::new()
|
||||
.route("/api/socket", get(websocket_handler))
|
||||
.route("/api/render/:id", get(get_render_main))
|
||||
// .route("/$api/file", get(get_file_handler))
|
||||
// .merge(SpaRouter::new("/$api/client", "js-client/src").index_file("main.html"))
|
||||
.nest_service("/api/client", serve_client)
|
||||
.with_state(mutexes.clone())
|
||||
.fallback(render_item);
|
||||
|
||||
let renders = mutexes.renders.lock().await;
|
||||
|
||||
for render in &*renders {
|
||||
match render.render_type {
|
||||
RenderType::JsonUi => {},
|
||||
RenderType::WebComponent => {
|
||||
let url_path = String::from("/api/render/") + &render.name + "/webroot";
|
||||
let file_path = mutexes.mize_folder.clone() + "/mr/" + &render.folder[..] + "/" + &render.webroot.clone()[..];
|
||||
let serve_dir = get_service(ServeDir::new(&file_path)).handle_error(handle_error);
|
||||
|
||||
app = app.nest_service(&url_path, serve_dir);
|
||||
},
|
||||
}
|
||||
}
|
||||
drop(renders);
|
||||
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], SERVER_PORT));
|
||||
// tracing::debug!("listening on {}", addr);
|
||||
axum::Server::bind(&addr)
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
}
|
||||
|
||||
async fn handle_error(_err: std::io::Error) -> impl IntoResponse {
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong...")
|
||||
}
|
||||
|
||||
async fn render_item(uri: Uri) -> impl IntoResponse {
|
||||
Html(fs::read_to_string("js-client/src/main.html").unwrap())
|
||||
}
|
||||
|
||||
//#[axum_macros::debug_handler]
|
||||
async fn get_render_main(extract::Path(id): extract::Path<String>, State(mutexes): State<Mutexes>) -> http::Response<String> {
|
||||
let renders = &*mutexes.renders.lock().await;
|
||||
|
||||
let render = renders.iter().filter(|&render| render.name == id).nth(0)
|
||||
.unwrap_or(renders.iter().filter(|&render| render.name == "mize-mmejs").nth(0).expect("mize-mmejs"));
|
||||
|
||||
let file_path = mutexes.mize_folder.clone() + "/mr/" + &render.folder + "/" + &render.main;
|
||||
|
||||
match render.render_type {
|
||||
RenderType::JsonUi => {
|
||||
return Response::builder()
|
||||
.header("content-type", "application/json")
|
||||
.status(StatusCode::OK)
|
||||
.body(fs::read_to_string(file_path).unwrap()).unwrap();
|
||||
},
|
||||
RenderType::WebComponent => {
|
||||
return Response::builder()
|
||||
.header("content-type", "application/javascript")
|
||||
.status(StatusCode::OK)
|
||||
.body(fs::read_to_string(file_path).unwrap()).unwrap();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn websocket_handler(
|
||||
ws: WebSocketUpgrade,
|
||||
State(mutexes): State<Mutexes>,
|
||||
headers: HeaderMap,
|
||||
) -> impl IntoResponse {
|
||||
ws.on_upgrade(|socket| handle_websocket_connection(socket, mutexes, headers))
|
||||
}
|
||||
|
||||
async fn handle_websocket_connection(
|
||||
socket: WebSocket,
|
||||
mutexes: Mutexes,
|
||||
headers: HeaderMap,
|
||||
){
|
||||
let (mut socket_tx, mut socket_rx) = socket.split();
|
||||
let (msg_tx, msg_rx): (Sender<proto::MizeMessage>, Receiver<proto::MizeMessage>) = mpsc::channel(SOCKET_CHANNEL_SIZE);
|
||||
|
||||
let mut msg_rx = ReceiverStream::new(msg_rx);
|
||||
|
||||
// check if mize-module header exists
|
||||
let origin = if let Some(mod_header_val) = headers.get("mize-module"){
|
||||
|
||||
let mut mods = mutexes.modules.lock().await;
|
||||
let mut client_id = mutexes.next_free_client_id.lock().await;
|
||||
let mut module = Module{
|
||||
tx: msg_tx.clone(),
|
||||
client_id: *client_id,
|
||||
name: String::from("tmp"),
|
||||
kind: ModuleKind::Extern(),
|
||||
registered_types: Vec::new(),
|
||||
};
|
||||
|
||||
*client_id += 1;
|
||||
|
||||
if let Ok(name) = mod_header_val.to_str() {
|
||||
module.name = name.to_string();
|
||||
} else {
|
||||
let err = MizeError::new(113)
|
||||
.extra_msg("The mize-module Header could not be decoded into a String.");
|
||||
|
||||
msg_tx.send(proto::MizeMessage::Json(err.to_json_message())).await;
|
||||
return;
|
||||
};
|
||||
println!("module {} connected", module.name);
|
||||
mods.push(module.clone());
|
||||
drop(mods);
|
||||
Peer::Module(module)
|
||||
|
||||
} else {
|
||||
let mut cli = mutexes.clients.lock().await;
|
||||
let mut client_id = mutexes.next_free_client_id.lock().await;
|
||||
let client = Client{tx: msg_tx.clone(), id: *client_id};
|
||||
cli.push(client.clone());
|
||||
*client_id += 1;
|
||||
drop(cli);
|
||||
Peer::Client(client)
|
||||
};
|
||||
|
||||
// Forwarding messages
|
||||
let myorigin = origin.clone();
|
||||
let mymutexes = mutexes.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some(msg) = msg_rx.next().await {
|
||||
match msg {
|
||||
proto::MizeMessage::Json(json_msg) => {
|
||||
if let Ok(msg) = serde_json::to_string(&json_msg) {
|
||||
let result = socket_tx.send(Message::Text(msg.clone())).await;
|
||||
if let Err(e) = result {
|
||||
println!("Client no longer Connected: {:?}", e);
|
||||
remove_peer(myorigin.clone(), mymutexes.clone()).await;
|
||||
} else {
|
||||
println!("SENDING: {}", msg);
|
||||
}
|
||||
} else {
|
||||
let err: MizeError = MizeError::new(11).extra_msg("error while serializing a json message").handle();
|
||||
if let Ok(text) = serde_json::to_string(&err.to_json()){
|
||||
socket_tx.send(Message::Text(text));
|
||||
} else {
|
||||
MizeError::new(11).extra_msg("not even being able to serialize an error, while failing to serializing a message").handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
proto::MizeMessage::Bin(bin_msg) => {
|
||||
socket_tx.send(Message::Binary(bin_msg.raw)).await;
|
||||
}
|
||||
proto::MizeMessage::Pong() => {
|
||||
socket_tx.send(Message::Pong(Vec::new())).await;
|
||||
}
|
||||
proto::MizeMessage::Close((num, reason)) => {
|
||||
println!("SENDING Close message");
|
||||
socket_tx.send(Message::Close(Some(CloseFrame{code: num, reason: Cow::Owned(reason)}))).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Reading messages
|
||||
while let Some(result) = socket_rx.next().await {
|
||||
let msg = if let Ok(msg) = result {msg} else {
|
||||
let err = MizeError::new(115).extra_msg("TCP Connection Closed");
|
||||
remove_peer(origin.clone(), mutexes.clone());
|
||||
return;
|
||||
};
|
||||
match msg {
|
||||
Message::Binary(b) => {
|
||||
println!("Recieved a Binary Message. Those are not implemented yet.")
|
||||
},
|
||||
|
||||
|
||||
Message::Text(text) => {
|
||||
println!("GOT: {}", text);
|
||||
let json_msg: proto::JsonMessage = serde_json::from_str(&text).expect("error parsing json");
|
||||
if let Err(err) = proto::handle_json_msg(json_msg, origin.clone(), mutexes.clone()).await {
|
||||
let err_msg: MizeMessage = err.handle().into();
|
||||
origin.send(err_msg).await;
|
||||
};
|
||||
},
|
||||
|
||||
Message::Close(inner) => {
|
||||
match inner {
|
||||
Some(CloseFrame{code, reason}) => {
|
||||
origin.send(MizeMessage::Close((code, reason.into_owned()))).await;
|
||||
},
|
||||
None => {
|
||||
origin.send(MizeMessage::Close((1000, "You didn't send a Close Reason".to_owned()))).await;
|
||||
}
|
||||
};
|
||||
|
||||
println!("Close from Client");
|
||||
remove_peer(origin.clone(), mutexes.clone()).await;
|
||||
}
|
||||
|
||||
|
||||
Message::Ping(_) => {
|
||||
msg_tx.send(MizeMessage::Pong());
|
||||
},
|
||||
|
||||
|
||||
Message::Pong(_) => {
|
||||
let err = MizeError::new(11)
|
||||
.extra_msg("unhandeld WebSocket-Message type: Pong")
|
||||
.handle();
|
||||
msg_tx.send(proto::MizeMessage::Json(err.to_json_message())).await;
|
||||
},
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
fn load_mr(mize_folder: String) -> Result<Vec<Render>, MizeError> {
|
||||
//load modules and renders
|
||||
|
||||
let mr_folders = std::fs::read_dir(mize_folder.clone() + "/mr")
|
||||
.expect("error reading the modules-renders dir in the mize-folder")
|
||||
.filter(|entry| entry.as_ref().unwrap().file_type().unwrap().is_dir());
|
||||
|
||||
let mut renders: Vec<Render> = Vec::new();
|
||||
|
||||
for mr_folder in mr_folders {
|
||||
|
||||
let mr_folder = match mr_folder {
|
||||
Err(_) => {MizeError::new(11).extra_msg("Error unwrapping DirEntry").handle(); continue;},
|
||||
Ok(idk) => idk,
|
||||
};
|
||||
|
||||
let mr_string = match fs::read_to_string(format!("{}/mize.toml", mr_folder.path().display())) {
|
||||
Err(_) => {MizeError::new(11).extra_msg("Error parsing mize.toml file to a toml string").handle(); continue;},
|
||||
Ok(idk) => idk,
|
||||
};
|
||||
|
||||
let mut mr_data = match mr_string.parse::<toml::Value>() {
|
||||
Err(_) => {MizeError::new(11).extra_msg("Error parsing mize.toml string to toml::Value").handle(); continue;},
|
||||
Ok(idk) => idk,
|
||||
};
|
||||
|
||||
if let Some(local_renders) = mr_data.get_mut("render") {
|
||||
if let Some(arr) = local_renders.as_array_mut(){
|
||||
//add folder to local_renders
|
||||
for mut el in arr.iter_mut() {
|
||||
if let Some(table) = el.as_table_mut(){
|
||||
table.insert("folder".to_owned(), toml::Value::String(mr_folder.file_name().into_string().unwrap()));
|
||||
table.insert("type".to_owned(), toml::Value::String("json-ui".to_owned()));
|
||||
table.insert("webroot".to_owned(), toml::Value::String("".to_owned()));
|
||||
}
|
||||
|
||||
let render = match Render::deserialize(el.clone()) {
|
||||
Ok(render) => render,
|
||||
Err(err) => {MizeError::new(11).extra_msg(&format!("{}", err)).handle(); continue;}
|
||||
};
|
||||
|
||||
renders.push(render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(local_webcomponents) = mr_data.get_mut("webcomponent") {
|
||||
if let Some(arr) = local_webcomponents.as_array_mut(){
|
||||
//add folder to local_renders
|
||||
for mut el in arr.iter_mut() {
|
||||
if let Some(table) = el.as_table_mut(){
|
||||
table.insert("folder".to_owned(), toml::Value::String(mr_folder.file_name().into_string().unwrap()));
|
||||
table.insert("type".to_owned(), toml::Value::String("webcomponent".to_owned()));
|
||||
}
|
||||
|
||||
let render = match Render::deserialize(el.clone()) {
|
||||
Ok(render) => render,
|
||||
Err(err) => {MizeError::new(11).extra_msg(&format!("{}", err)).handle(); continue;}
|
||||
};
|
||||
|
||||
renders.push(render);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Ok((renders));
|
||||
}
|
||||
|
||||
async fn init_server(mize_folder: String) -> Result<(Uuid, Itemstore, Vec<Render>), MizeError> {
|
||||
/*
|
||||
* This function initializes the server.
|
||||
* - create a mize folder if not there yet
|
||||
* - get or generate the uuid for the server
|
||||
* - load the renders and modules from the <mize-folder>/mr folder
|
||||
* - create a surrealdb::Datastore inside the <mize-folder>/db folder
|
||||
*
|
||||
*/
|
||||
|
||||
let server_uuid;
|
||||
|
||||
//create mize.toml with id inside in folder if net yet done
|
||||
match fs::read_to_string(format!("{}/mize.toml", mize_folder)) {
|
||||
Err(err) => {
|
||||
match err.kind() {
|
||||
std::io::ErrorKind::NotFound => {
|
||||
//create the file with new uuid
|
||||
server_uuid = uuid::Uuid::new_v4();
|
||||
let mut toml_val = toml::Value::Table(toml::map::Map::new());
|
||||
toml_val.as_table_mut()
|
||||
.ok_or(MizeError::new(11))?
|
||||
.insert("uuid".to_owned(), toml::Value::String(server_uuid.to_string()));
|
||||
|
||||
fs::write(format!("{}/mize.toml", mize_folder), toml::to_string(&toml_val)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))?)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))?;
|
||||
|
||||
}
|
||||
_ => {
|
||||
server_uuid = uuid::Uuid::new_v4();
|
||||
Err(err)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))
|
||||
.extra_msg("Could not read <mize-folder>/mize.toml file")?;
|
||||
}
|
||||
}
|
||||
},
|
||||
Ok(toml_string) => {
|
||||
let mut toml_val = toml_string.parse::<toml::Value>().map_err(|e| MizeError::new(11).extra_msg(e))?;
|
||||
|
||||
if let Some(uuid) = toml_val.get("uuid") {
|
||||
server_uuid = Uuid::from_str(uuid.as_str().ok_or(MizeError::new(11))?)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))?;
|
||||
} else {
|
||||
//generate uuid and write that to toml file
|
||||
server_uuid = uuid::Uuid::new_v4();
|
||||
toml_val.as_table_mut().ok_or(MizeError::new(11))?.insert("uuid".to_owned(), toml::Value::String(server_uuid.to_string()));
|
||||
|
||||
fs::write(format!("{}/mize.toml", mize_folder), toml::to_string(&toml_val)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))?)
|
||||
.map_err(|e| MizeError::new(11).extra_msg(e))?;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// create the itemstore
|
||||
let itemstore = crate::server::itemstore::Itemstore::new(mize_folder.clone() + "/db").await.expect("error creating itemstore");
|
||||
|
||||
// load the modules and renders from <mize-folder>/mr
|
||||
let renders = load_mr(mize_folder.clone())
|
||||
.map_err(|e| MizeError::new(11))
|
||||
.extra_msg("Error loading Modules and Renders")?;
|
||||
|
||||
return Ok((server_uuid, itemstore, renders));
|
||||
}
|
||||
|
||||
pub async fn remove_peer(origin: Peer, mutexes: Mutexes) {
|
||||
match origin {
|
||||
Peer::Client(ref client) => {
|
||||
//remove client from client list
|
||||
let mut clients = mutexes.clients.lock().await;
|
||||
let index = match clients.iter()
|
||||
.position(|client_iter| client_iter.id == client.id)
|
||||
.ok_or(MizeError::new(11).extra_msg("A Client disconected, that had never connected......")){
|
||||
Ok(index) => index,
|
||||
Err(err) => {
|
||||
let msg: MizeMessage = err.into();
|
||||
origin.send(msg);
|
||||
return;
|
||||
},
|
||||
};
|
||||
clients.remove(index);
|
||||
return;
|
||||
},
|
||||
Peer::Module(module) => {
|
||||
//remove module from module list
|
||||
let mut modules = mutexes.modules.lock().await;
|
||||
let index = modules.iter()
|
||||
.position(|module_iter| module_iter.client_id == module.client_id)
|
||||
.expect("A Module disconected, that had never connected.....");
|
||||
modules.remove(index);
|
||||
println!("Close from Module");
|
||||
return;
|
||||
}
|
||||
Peer::Upstream(_) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::{io, fmt::format, vec};
|
||||
use surrealdb::kvs::{Datastore, Key, Val};
|
||||
use itertools::Itertools;
|
||||
use crate::error;
|
||||
use crate::error::MizeError;
|
||||
use crate::server::proto::{self};
|
||||
use crate::server::Mutexes;
|
||||
use crate::server::Peer;
|
||||
|
||||
use serde_json::Value as JsonValue;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use super::proto::{Delta, MizeId};
|
||||
|
||||
// The struct to do the storage and updates to it
|
||||
// is responsible, that no illegal states can occur in the storage, by using transactions
|
||||
// currently it's just a surrealdb Datastore. should be replaced by a completely custom File-System in the future.
|
||||
pub struct Itemstore {
|
||||
db: Datastore,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Item {
|
||||
#[serde(flatten)]
|
||||
pub json: JsonValue,
|
||||
}
|
||||
|
||||
pub struct Array {
|
||||
}
|
||||
|
||||
//later
|
||||
//pub struct Map {
|
||||
//}
|
||||
|
||||
//pub struct Table {
|
||||
//}
|
||||
|
||||
impl Item {
|
||||
pub fn get_id(&self) -> Result<String, MizeError> {
|
||||
if let JsonValue::Object(ob) = &self.json{
|
||||
if let Some(id_val) = ob.get("__item__") {
|
||||
if let JsonValue::String(id) = id_val {
|
||||
return Ok(id.to_string())
|
||||
} else {
|
||||
return Err(MizeError::new(11).extra_msg("mize-id field in an item was not a String"));
|
||||
}
|
||||
} else {
|
||||
return Err(MizeError::new(11).extra_msg("There was no mize-id field in an item"));
|
||||
}
|
||||
} else {
|
||||
return Err(MizeError::new(11).extra_msg("An Item was not a JsonValue::Object"));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_delta(&mut self, delta: Delta) -> Result<(), MizeError> {
|
||||
//println!("DELTA: {:?}", delta);
|
||||
for (path, value) in delta.delta {
|
||||
let mut to_replace = &mut self.json;
|
||||
let mut counter = path.len() as i32;
|
||||
for name in path {
|
||||
counter -= 1;
|
||||
|
||||
// if let Some(inner) = to_replace.get(&name) {
|
||||
// to_replace = inner
|
||||
|
||||
// } else if let JsonValue::Object(ob) = to_replace {
|
||||
//let mut new_map = JsonValue::Object(serde_json::Map::new());
|
||||
//ob.insert(name, new_map);
|
||||
//to_replace = &mut new_map;
|
||||
// } else {
|
||||
// return Err(MizeError::new(11)
|
||||
// .extra_msg("Error applying a Delta to an Item. The path could not be followed."));
|
||||
// }
|
||||
|
||||
|
||||
//on last iteration
|
||||
if counter == 0 {
|
||||
if value.is_none() {
|
||||
if to_replace.is_object() {
|
||||
to_replace.as_object_mut().ok_or(MizeError::new(11))?.remove(&name);
|
||||
return Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
to_replace = if to_replace.get_mut(&name).is_some() {
|
||||
to_replace.get_mut(&name).ok_or(MizeError::new(11))?
|
||||
|
||||
} else if to_replace.is_object() {
|
||||
// when path does not exist
|
||||
|
||||
let mut new_map = JsonValue::Object(serde_json::Map::new());
|
||||
to_replace.as_object_mut().ok_or(MizeError::new(11))?.insert(name.clone(), new_map);
|
||||
to_replace.get_mut(&name).ok_or(MizeError::new(11))?
|
||||
|
||||
} else {
|
||||
|
||||
return Err(MizeError::new(11)
|
||||
.extra_msg("Error applying a Delta to an Item. The path could not be followed."));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// replace with value from the delta
|
||||
*to_replace = value.into();
|
||||
}
|
||||
|
||||
//println!("After applying a Delta, {}", self.json);
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
pub fn from_bytes(vec: Vec<u8>) -> Result<Item, MizeError> {
|
||||
let string = String::from_utf8(vec)?;
|
||||
let item = serde_json::from_str(&string)?;
|
||||
return Ok(item);
|
||||
}
|
||||
}
|
||||
|
||||
impl Itemstore {
|
||||
pub async fn new(path: String) -> Result<Itemstore, MizeError> {
|
||||
//println!("PATH of DB: {}", path);
|
||||
let ds = Datastore::new(&(String::from("file://") + &path[..])[..]).await
|
||||
.map_err(|e| MizeError::new(30).extra_msg(format!("surrealdb Error: {}", e)).extra_msg(format!("Trying to create at Location: {}", path)))?;
|
||||
|
||||
let mut tr = ds.transaction(true, false).await?;
|
||||
|
||||
match tr.get(MizeId::zero().into_bytes()).await {
|
||||
Ok(Some(val)) => println!("Item 0 already created"),
|
||||
Ok(None) => {
|
||||
let data = serde_json::json!({
|
||||
"num_of_items": 1,
|
||||
"next_free_id": 1,
|
||||
"__commit__": 0,
|
||||
"__type__": "mize-main",
|
||||
"__item__": "0"
|
||||
});
|
||||
|
||||
tr.set(MizeId::zero().into_bytes(), data.to_string()).await?;
|
||||
tr.commit().await?;
|
||||
},
|
||||
|
||||
Err(e) => {return Err(MizeError::from(e))},
|
||||
};
|
||||
return Ok(Itemstore {db:ds});
|
||||
}
|
||||
|
||||
pub async fn create(&self, mut item: Item, mutexes: Mutexes, origin: Peer) -> Result<MizeId, MizeError> {
|
||||
let mut tr = self.db.transaction(true, false).await?;
|
||||
|
||||
//get next_free_id
|
||||
let json: JsonValue = serde_json::from_str(&String::from_utf8(tr.get(MizeId::zero().into_bytes()).await?.ok_or(MizeError::new(31))?)
|
||||
.map_err(|_| MizeError::new(11))?)
|
||||
.map_err(|_| MizeError::new(11))?;
|
||||
|
||||
let new_id_u64: u64 = json.get("next_free_id").ok_or(MizeError::new(11))?.as_u64().ok_or(MizeError::new(11))?;
|
||||
let new_id = MizeId::new(format!("{}", new_id_u64));
|
||||
|
||||
let num_of_items: u64 = json.get("num_of_items").ok_or(MizeError::new(11))?.as_u64().ok_or(MizeError::new(11))?;
|
||||
|
||||
let new_next_id = new_id_u64 +1;
|
||||
let new_num = num_of_items + 1;
|
||||
|
||||
//add mize-id field to item
|
||||
//let delta: Delta = serde_json::from_str(&format!("[[[\"__item__\"], \"{}\"]]", new_id))?;
|
||||
let mut delta = Delta::new();
|
||||
delta.append(vec!["__item__"], serde_json::json!(new_id_u64));
|
||||
item.apply_delta(delta)?;
|
||||
|
||||
tr.set(new_id.clone().into_bytes(), item.json.to_string()).await?;
|
||||
|
||||
tr.commit().await?;
|
||||
|
||||
//handle update to item0
|
||||
let mut delta_item0: Delta = Delta::new();
|
||||
delta_item0.append(vec!["num_of_items"], serde_json::json!(new_num));
|
||||
delta_item0.append(vec!["next_free_id"], serde_json::json!(new_next_id));
|
||||
|
||||
proto::handle_update(vec![(proto::MizeId::new(format!("0")), delta_item0)], origin, mutexes.clone()).await?;
|
||||
|
||||
return Ok(new_id);
|
||||
}
|
||||
|
||||
|
||||
pub async fn update(&self, id: MizeId, delta: Delta) -> Result<(), MizeError>{
|
||||
let mut tr = self.db.transaction(true, true).await?;
|
||||
|
||||
let item_bytes: Vec<u8> = tr.get(id.clone().into_bytes()).await?
|
||||
.ok_or(MizeError::new(11)
|
||||
.extra_msg("The Item an update should be applied to does not exist."))?;
|
||||
|
||||
let mut item = Item::from_bytes(item_bytes)?;
|
||||
|
||||
item.apply_delta(delta)?;
|
||||
//println!("after applying delta: {:?}", item);
|
||||
|
||||
tr.set(id.into_bytes(), serde_json::to_string(&item)?).await?;
|
||||
|
||||
tr.commit().await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub async fn delete(&self, id: MizeId) -> Result<(), error::MizeError>{
|
||||
let mut tr = self.db.transaction(true, true).await?;
|
||||
|
||||
tr.del(id.into_bytes()).await?;
|
||||
|
||||
tr.commit().await?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
pub async fn get(&self, id: MizeId) -> Result<Item, MizeError> {
|
||||
let mut tr = self.db.transaction(false, false).await?;
|
||||
|
||||
let item_res = tr.get(id.clone().into_bytes()).await?;
|
||||
if let Some(item_vec) = item_res {
|
||||
let item_str: String = String::from_utf8(item_vec).map_err(|_|MizeError::new(11))?;
|
||||
let item: JsonValue = serde_json::from_str(&item_str).map_err(|_|MizeError::new(11))?;
|
||||
return Ok(Item { json: item })
|
||||
} else {
|
||||
return Err(MizeError::new(32).format(vec![&format!("{:?}", id)]));
|
||||
}
|
||||
return Err(MizeError::new(11));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,470 +0,0 @@
|
||||
use derive_more::From;
|
||||
use futures_util::stream::select_all::Iter;
|
||||
use serde::de::Error;
|
||||
use serde_json::json;
|
||||
use serde::de::Visitor;
|
||||
use serde::de;
|
||||
|
||||
use std::time::Duration;
|
||||
//use std::panic::update_hook;
|
||||
use std::vec;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::server::itemstore;
|
||||
use crate::server::Mutexes;
|
||||
use crate::server::Peer;
|
||||
use crate::error;
|
||||
use crate::server::Client;
|
||||
use std::sync::Arc;
|
||||
use futures_util::stream::Collect;
|
||||
use tokio::sync::{Mutex, mpsc};
|
||||
use crate::server;
|
||||
use crate::error::MizeError;
|
||||
use crate::server::itemstore::Item;
|
||||
use crate::server::proto;
|
||||
use axum::extract::ws::CloseFrame;
|
||||
|
||||
use serde_json::Value as JsonValue;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
//###//===================================================
|
||||
//all the structs and enums
|
||||
#[derive(From, Debug, Clone)]
|
||||
pub enum MizeMessage {
|
||||
Json(JsonMessage),
|
||||
Bin(BinMessage),
|
||||
Pong(),
|
||||
Close((u16, String)),
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BinMessage {
|
||||
pub raw: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(From, Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ErrMessage {
|
||||
//pub cat: String,
|
||||
pub err: MizeError,
|
||||
}
|
||||
|
||||
//enum variant and a struct for every cmd a good idea???
|
||||
#[derive(From, Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "cmd")]
|
||||
pub enum JsonMessage {
|
||||
#[serde(rename="err")]
|
||||
ErrMsg(ErrMessage),
|
||||
#[serde(rename="item.get")]
|
||||
Get(GetItemMessage),
|
||||
#[serde(rename="item.get-sub")]
|
||||
GetSub(GetSubMessage),
|
||||
#[serde(rename="item.give")]
|
||||
Give(GiveItemMessage),
|
||||
#[serde(rename="item.create")]
|
||||
Create(CreateItemMessage),
|
||||
#[serde(rename="item.created-id")]
|
||||
CreatedId(CreatedIdMessage),
|
||||
#[serde(rename="item.delete")]
|
||||
Delete(DeleteItemMessage),
|
||||
#[serde(rename="item.sub")]
|
||||
Sub(SubItemMessage),
|
||||
#[serde(rename="item.unsub")]
|
||||
Unsub(UnsubItemMessage),
|
||||
#[serde(rename="item.update-req")]
|
||||
UpdateRequest(UpdateRequestMessage),
|
||||
#[serde(rename="item.update")]
|
||||
Update(UpdateMessage),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GetItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GetSubMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GiveItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
item: Item,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CreateItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
item: Item,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CreatedIdMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeleteItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SubItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UnsubItemMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UpdateRequestMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
#[serde(flatten)]
|
||||
delta: Delta,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UpdateMessage {
|
||||
//pub cat: String,
|
||||
//cmd: String,
|
||||
#[serde(flatten)]
|
||||
id: MizeId,
|
||||
#[serde(flatten)]
|
||||
delta: Delta,
|
||||
}
|
||||
|
||||
#[serde(from = "SerdeDelta")]
|
||||
#[serde(into = "SerdeDelta")]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||
pub struct Delta {
|
||||
pub delta: Vec<(Path, Option<JsonValue>)>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||
pub struct SerdeDelta {
|
||||
pub delta: Vec<SerdeDeltaEntry>,
|
||||
}
|
||||
|
||||
impl From<SerdeDelta> for Delta {
|
||||
fn from(serde: SerdeDelta) -> Delta {
|
||||
let mut delta = Delta {delta: Vec::new()};
|
||||
for SerdeDeltaEntry(path, json) in serde.delta {
|
||||
delta.delta.push((path, json));
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Delta> for SerdeDelta {
|
||||
fn from(delta: Delta) -> SerdeDelta {
|
||||
let mut serde = SerdeDelta {delta: Vec::new()};
|
||||
for (path, json) in delta.delta {
|
||||
serde.delta.push(SerdeDeltaEntry(path, json));
|
||||
}
|
||||
return serde;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Default)]
|
||||
pub struct SerdeDeltaEntry (
|
||||
pub Path,
|
||||
#[serde(default)]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub Option<JsonValue>,
|
||||
);
|
||||
|
||||
pub type Path = Vec<String>;
|
||||
|
||||
pub type Update = Vec<(MizeId, Delta)>;
|
||||
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, Hash, PartialEq)]
|
||||
pub struct MizeId {
|
||||
#[serde(rename="id")]
|
||||
main: String,
|
||||
}
|
||||
|
||||
pub enum MizeIdKind<'a>{
|
||||
Module{mod_name: &'a str, id: &'a str},
|
||||
Upstream(&'a server::Peer),
|
||||
Local(u64),
|
||||
}
|
||||
|
||||
impl MizeId {
|
||||
pub fn new(main: String) -> MizeId {
|
||||
MizeId { main }
|
||||
}
|
||||
|
||||
pub fn from_local(local: u64) -> MizeId {
|
||||
MizeId::new(format!("{}", local))
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
self.main.into_bytes()
|
||||
}
|
||||
|
||||
pub fn zero() -> MizeId {
|
||||
MizeId::new("0".to_owned())
|
||||
}
|
||||
|
||||
pub fn to_string(self) -> String {
|
||||
self.main
|
||||
}
|
||||
|
||||
pub fn new_local(local_part: &str) -> MizeId {
|
||||
MizeId { main: local_part.to_owned() }
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> Result<MizeIdKind, MizeError> {
|
||||
let first_char = match self.main.chars().nth(0) {
|
||||
Some(ch) => ch,
|
||||
None => {
|
||||
return Err(MizeError::new(11).extra_msg("Couldn't get the first char from a MizeId"));
|
||||
},
|
||||
};
|
||||
|
||||
if (first_char == '#'){
|
||||
let iter = self.main.chars();
|
||||
|
||||
//scip the #
|
||||
let mod_name_end = iter.enumerate().find(|&r| r.1 == '#' || r.1 == '/').ok_or(MizeError::new(11))?;
|
||||
|
||||
let mod_name = &self.main[0..mod_name_end.0];
|
||||
let id = &self.main[mod_name_end.0..];
|
||||
|
||||
return Ok(MizeIdKind::Module{ mod_name, id});
|
||||
|
||||
} else {
|
||||
let id: u64 = match self.main.parse(){
|
||||
Ok(num) => num,
|
||||
Err(_) => {
|
||||
return Err(MizeError::new(11).extra_msg("Couldn't parse a local id into an integer"))
|
||||
},
|
||||
};
|
||||
return Ok(MizeIdKind::Local(id));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Delta {
|
||||
pub fn new() -> Delta{
|
||||
Delta { delta: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn append(&mut self, path: Vec<&str>, json: JsonValue){
|
||||
let new_path: Vec<String> = path.into_iter().map(|e| e.to_owned()).collect();
|
||||
self.delta.push((new_path, Some(json)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//###//===================================================
|
||||
//From trait implementations, to be able to treat everything as a MizeMessage that can be
|
||||
|
||||
impl From<GiveItemMessage> for MizeMessage {
|
||||
fn from(give: GiveItemMessage) -> MizeMessage {
|
||||
let two: JsonMessage = give.into();
|
||||
return two.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MizeError> for MizeMessage {
|
||||
fn from(err: MizeError) -> MizeMessage {
|
||||
let hi: ErrMessage = err.into();
|
||||
let two: JsonMessage = hi.into();
|
||||
return two.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreatedIdMessage> for MizeMessage {
|
||||
fn from(give: CreatedIdMessage) -> MizeMessage {
|
||||
let two: JsonMessage = give.into();
|
||||
return two.into();
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UpdateMessage> for MizeMessage {
|
||||
fn from(give: UpdateMessage) -> MizeMessage {
|
||||
let two: JsonMessage = give.into();
|
||||
return two.into();
|
||||
}
|
||||
}
|
||||
|
||||
//###//===================================================
|
||||
// functions
|
||||
|
||||
pub async fn handle_json_msg(msg: JsonMessage, origin: Peer, mutexes: Mutexes) -> Result<(), MizeError>{
|
||||
|
||||
match msg {
|
||||
|
||||
JsonMessage::Get(msg) => {
|
||||
match msg.id.kind()? {
|
||||
//MizeId::Module { mod_name, id } => {
|
||||
//TODO: get type of module with mod_name .... and then either forward msg or call
|
||||
//module_get_code
|
||||
//},
|
||||
|
||||
MizeIdKind::Local(id) => {
|
||||
let itemstore = mutexes.itemstore.lock().await;
|
||||
let response = GiveItemMessage {
|
||||
id: msg.id,
|
||||
item: itemstore.get(MizeId::from_local(id)).await?,
|
||||
};
|
||||
origin.send(response).await;
|
||||
},
|
||||
|
||||
_ => {return Err(MizeError::new(11).extra_msg("id type is not implemented"));},
|
||||
};
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
|
||||
JsonMessage::GetSub(msg) => {
|
||||
|
||||
//sub to item
|
||||
let mut subs = mutexes.subs.lock().await;
|
||||
if let Some(mut vec_ids) = subs.get_mut(&msg.id) {
|
||||
vec_ids.push(origin.clone());
|
||||
} else {
|
||||
subs.insert(msg.id.clone(), vec![origin.clone()]);
|
||||
};
|
||||
|
||||
match msg.id.kind()? {
|
||||
//MizeId::Module { mod_name, id } => {
|
||||
//TODO: get type of module with mod_name .... and then either forward msg or call
|
||||
//module_get_code
|
||||
//},
|
||||
|
||||
MizeIdKind::Local(id) => {
|
||||
let itemstore = mutexes.itemstore.lock().await;
|
||||
let response = GiveItemMessage {
|
||||
id: msg.id,
|
||||
item: itemstore.get(MizeId::from_local(id)).await?,
|
||||
};
|
||||
origin.send(response).await;
|
||||
},
|
||||
|
||||
_ => {return Err(MizeError::new(11).extra_msg("id types not implemented"));},
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
||||
JsonMessage::UpdateRequest(mut msg) => {
|
||||
let update: Update = vec![(msg.id, msg.delta)];
|
||||
handle_update(update, origin, mutexes.clone()).await?;
|
||||
|
||||
// let subs = mutexes.subs.lock().await;
|
||||
|
||||
// for (id, delta) in new_update {
|
||||
//send that delta to every origin that is subbed the item
|
||||
// let peers = match subs.get(&id) {
|
||||
// Some(vec) => vec,
|
||||
// None => continue,
|
||||
// };
|
||||
// let message = UpdateMessage{id, delta};
|
||||
|
||||
// for peer in peers {
|
||||
//TODO: send should only take a reference
|
||||
// peer.send(message.clone()).await
|
||||
// }
|
||||
// }
|
||||
},
|
||||
|
||||
|
||||
JsonMessage::Create(msg) => {
|
||||
let itemstore = mutexes.itemstore.lock().await;
|
||||
let id = itemstore.create(msg.item, mutexes.clone(), origin.clone()).await?;
|
||||
let response = CreatedIdMessage {id};
|
||||
|
||||
origin.send(response).await;
|
||||
return Ok(());
|
||||
},
|
||||
|
||||
|
||||
JsonMessage::Delete(msg) => {
|
||||
match msg.id.kind()? {
|
||||
MizeIdKind::Local(id) => {
|
||||
let itemstore = mutexes.itemstore.lock().await;
|
||||
itemstore.delete(MizeId::from_local(id)).await?;
|
||||
return Ok(());
|
||||
},
|
||||
_ => {return Err(MizeError::new(11).extra_msg("deleteng non Local items not implemented yet"));}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_ => {
|
||||
return Err(MizeError::new(11).extra_msg("ItemMessage cmd not handeld"));
|
||||
},
|
||||
};
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
pub async fn handle_update(update: Update, origin: Peer, mutexes: Mutexes) -> Result<(), MizeError> {
|
||||
mutexes.update_tx.send((update, origin)).await.map_err(|err| MizeError::new(11).extra_msg(format!("From SendError: {}", err)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_thread(mut update_rx: mpsc::Receiver<(Update, Peer)>, mutexes: Mutexes) -> Result<(), MizeError> {
|
||||
while let Some((update, origin)) = update_rx.recv().await {
|
||||
println!("UPDATE on id: {:?}", update.iter().next().unwrap().0.main);
|
||||
//TODO: run update code from modules and types
|
||||
|
||||
let itemstore = mutexes.itemstore.lock().await;
|
||||
let subs = mutexes.subs.lock().await;
|
||||
|
||||
for (id, delta) in update {
|
||||
|
||||
//update the items in the itemstore
|
||||
if let MizeIdKind::Local(id) = id.kind()? {
|
||||
itemstore.update(MizeId::from_local(id), delta.clone()).await?;
|
||||
} else {
|
||||
return Err(MizeError::new(11).extra_msg("updates to non local items are not handeld yet"));
|
||||
}
|
||||
|
||||
//send a update msg to subbed clients
|
||||
let peers = match subs.get(&id) {
|
||||
Some(hi) => hi,
|
||||
None => break,
|
||||
};
|
||||
let msg = UpdateMessage{id, delta};
|
||||
for peer in peers {
|
||||
peer.send(msg.clone()).await;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
use std::io::{self, ErrorKind, SeekFrom};
|
||||
use std::collections::HashMap;
|
||||
use std::io::prelude::*;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use crate::error::MizeError;
|
||||
|
||||
pub struct Fields{
|
||||
key: u64,
|
||||
data: u64
|
||||
}
|
||||
|
||||
pub struct Index{
|
||||
commit_number: u64,
|
||||
//fields: Vec<Fields>
|
||||
}
|
||||
|
||||
pub fn import(args: Vec<String>){
|
||||
|
||||
}
|
||||
|
||||
pub fn update_item(id: u64, key: String, update_string: String){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user