features: app engine #1
@ -91,6 +91,20 @@ DEFINE FIELD max_ports_per_app ON TABLE app_node TYPE int;
|
|||||||
DEFINE FIELD price ON TABLE app_node TYPE int;
|
DEFINE FIELD price ON TABLE app_node TYPE int;
|
||||||
DEFINE FIELD offline_minutes ON TABLE app_node TYPE int;
|
DEFINE FIELD offline_minutes ON TABLE app_node TYPE int;
|
||||||
|
|
||||||
|
DEFINE TABLE new_app_req Type RELATION FROM account to app_node SCHEMAFULL;
|
||||||
|
DEFINE FIELD app_name ON TABLE new_app_req TYPE string;
|
||||||
|
DEFINE FIELD package_url ON TABLE new_app_req TYPE string;
|
||||||
|
DEFINE FIELD mr_enclave ON TABLE new_app_req TYPE string;
|
||||||
|
DEFINE FIELD hratls_pubkey ON TABLE new_app_req TYPE string;
|
||||||
|
DEFINE FIELD ports ON TABLE new_app_req TYPE array<int>;
|
||||||
|
DEFINE FIELD memory_mb ON TABLE new_app_req TYPE int;
|
||||||
|
DEFINE FIELD vcpu ON TABLE new_app_req TYPE int;
|
||||||
|
DEFINE FIELD disk_mb ON TABLE new_app_req TYPE int;
|
||||||
|
DEFINE FIELD locked_nano ON TABLE new_app_req TYPE int;
|
||||||
|
DEFINE FIELD price_per_unit ON TABLE new_app_req TYPE int;
|
||||||
|
DEFINE FIELD error ON TABLE new_app_req TYPE string;
|
||||||
|
DEFINE FIELD created_at ON TABLE new_app_req TYPE datetime;
|
||||||
|
|
||||||
DEFINE TABLE active_app TYPE RELATION FROM account TO app_node SCHEMAFULL;
|
DEFINE TABLE active_app TYPE RELATION FROM account TO app_node SCHEMAFULL;
|
||||||
DEFINE FIELD app_name ON TABLE active_app TYPE string;
|
DEFINE FIELD app_name ON TABLE active_app TYPE string;
|
||||||
DEFINE FIELD mapped_ports ON TABLE active_app TYPE array<[int, int]>;
|
DEFINE FIELD mapped_ports ON TABLE active_app TYPE array<[int, int]>;
|
||||||
|
@ -33,6 +33,8 @@ pub const VM_CONTRACT: &str = "vm_contract";
|
|||||||
|
|
||||||
pub const ACTIVE_APP: &str = "active_app";
|
pub const ACTIVE_APP: &str = "active_app";
|
||||||
pub const APP_NODE: &str = "app_node";
|
pub const APP_NODE: &str = "app_node";
|
||||||
|
pub const NEW_APP_REQ: &str = "new_app_req";
|
||||||
|
pub const DELETED_APP: &str = "deleted_app";
|
||||||
|
|
||||||
pub const ID_ALPHABET: [char; 62] = [
|
pub const ID_ALPHABET: [char; 62] = [
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||||
|
@ -34,6 +34,44 @@ impl AppNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum AppDaemonMsg {
|
||||||
|
Create(NewAppReq),
|
||||||
|
Delete(DeletedApp),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NewAppReq> for AppDaemonMsg {
|
||||||
|
fn from(value: NewAppReq) -> Self {
|
||||||
|
Self::Create(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DeletedApp> for AppDaemonMsg {
|
||||||
|
fn from(value: DeletedApp) -> Self {
|
||||||
|
Self::Delete(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct NewAppReq {
|
||||||
|
pub id: RecordId,
|
||||||
|
#[serde(rename = "in")]
|
||||||
|
pub admin: RecordId,
|
||||||
|
#[serde(rename = "out")]
|
||||||
|
pub app_node: RecordId,
|
||||||
|
pub app_name: String,
|
||||||
|
pub package_url: String,
|
||||||
|
pub mr_enclave: String,
|
||||||
|
pub hratls_pubkey: String,
|
||||||
|
pub ports: Vec<u32>,
|
||||||
|
pub memory_mb: u32,
|
||||||
|
pub vcpu: u32,
|
||||||
|
pub disk_mb: u32,
|
||||||
|
pub locked_nano: u64,
|
||||||
|
pub price_per_unit: u64,
|
||||||
|
pub error: String,
|
||||||
|
pub created_at: Datetime,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct AppNodeWithReports {
|
pub struct AppNodeWithReports {
|
||||||
pub id: RecordId,
|
pub id: RecordId,
|
||||||
@ -138,3 +176,25 @@ impl From<&old_brain::BrainData> for Vec<AppNode> {
|
|||||||
nodes
|
nodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct DeletedApp {
|
||||||
|
pub id: RecordId,
|
||||||
|
#[serde(rename = "in")]
|
||||||
|
pub admin: RecordId,
|
||||||
|
#[serde(rename = "out")]
|
||||||
|
pub app_node: RecordId,
|
||||||
|
pub app_name: String,
|
||||||
|
pub mapped_ports: Vec<(u64, u64)>,
|
||||||
|
pub host_ipv4: String,
|
||||||
|
pub vcpus: u64,
|
||||||
|
pub memory_mb: u64,
|
||||||
|
pub disk_size_gb: u64,
|
||||||
|
pub created_at: Datetime,
|
||||||
|
pub price_per_unit: u64,
|
||||||
|
pub locked_nano: u64,
|
||||||
|
pub collected_at: Datetime,
|
||||||
|
pub mr_enclave: String,
|
||||||
|
pub package_url: String,
|
||||||
|
pub hratls_pubkey: String,
|
||||||
|
}
|
||||||
|
@ -2,7 +2,7 @@ pub mod app;
|
|||||||
pub mod general;
|
pub mod general;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
|
||||||
use crate::constants::{DELETED_VM, NEW_VM_REQ, UPDATE_VM_REQ};
|
use crate::constants::{APP_NODE, DELETED_APP, DELETED_VM, NEW_APP_REQ, NEW_VM_REQ, UPDATE_VM_REQ};
|
||||||
use crate::old_brain;
|
use crate::old_brain;
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -24,6 +24,10 @@ pub enum Error {
|
|||||||
TimeOut(#[from] tokio::time::error::Elapsed),
|
TimeOut(#[from] tokio::time::error::Elapsed),
|
||||||
#[error("Failed to create account")]
|
#[error("Failed to create account")]
|
||||||
FailedToCreateDBEntry,
|
FailedToCreateDBEntry,
|
||||||
|
#[error("Unknown Table: {0}")]
|
||||||
|
UnknownTable(String),
|
||||||
|
#[error("Daemon channel got closed: {0}")]
|
||||||
|
AppDaemonConnection(#[from] tokio::sync::mpsc::error::SendError<AppDaemonMsg>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@ -95,9 +99,9 @@ pub async fn live_vmnode_msgs<
|
|||||||
t if t == std::any::type_name::<crate::db::vm::NewVmReq>() => NEW_VM_REQ.to_string(),
|
t if t == std::any::type_name::<crate::db::vm::NewVmReq>() => NEW_VM_REQ.to_string(),
|
||||||
t if t == std::any::type_name::<crate::db::vm::UpdateVmReq>() => UPDATE_VM_REQ.to_string(),
|
t if t == std::any::type_name::<crate::db::vm::UpdateVmReq>() => UPDATE_VM_REQ.to_string(),
|
||||||
t if t == std::any::type_name::<crate::db::vm::DeletedVm>() => DELETED_VM.to_string(),
|
t if t == std::any::type_name::<crate::db::vm::DeletedVm>() => DELETED_VM.to_string(),
|
||||||
wat => {
|
t => {
|
||||||
log::error!("listen_for_node: T has type {wat}");
|
log::error!("live_vmnode_msgs type {t} not supported",);
|
||||||
String::from("wat")
|
return Err(Error::UnknownTable(t.to_string()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let mut resp =
|
let mut resp =
|
||||||
@ -119,3 +123,43 @@ pub async fn live_vmnode_msgs<
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn live_appnode_msgs<
|
||||||
|
T: std::fmt::Debug + Into<app::AppDaemonMsg> + std::marker::Unpin + for<'de> Deserialize<'de>,
|
||||||
|
>(
|
||||||
|
db: &Surreal<Client>,
|
||||||
|
node_pubkey: &str,
|
||||||
|
tx: Sender<app::AppDaemonMsg>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let table_name = match std::any::type_name::<T>() {
|
||||||
|
t if t == std::any::type_name::<crate::db::app::NewAppReq>() => NEW_APP_REQ.to_string(),
|
||||||
|
t if t == std::any::type_name::<crate::db::app::DeletedApp>() => DELETED_APP.to_string(),
|
||||||
|
t => {
|
||||||
|
log::error!("live_appnode_msgs type {t} not supported",);
|
||||||
|
return Err(Error::UnknownTable(t.to_string()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut query_resp = db
|
||||||
|
.query(format!("live select * from {table_name} where out = {APP_NODE}:{node_pubkey};"))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let mut live_stream = query_resp.stream::<Notification<T>>(0)?;
|
||||||
|
while let Some(result) = live_stream.next().await {
|
||||||
|
match result {
|
||||||
|
Ok(notification) => {
|
||||||
|
log::debug!("Got notification for node {node_pubkey}: {notification:?}");
|
||||||
|
if notification.action == surrealdb::Action::Create {
|
||||||
|
tx.send(notification.data.into()).await?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"live_vmnode_msgs for {table_name} DB stream failed for {node_pubkey}: {e}"
|
||||||
|
);
|
||||||
|
return Err(Error::from(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -89,7 +89,26 @@ impl BrainAppDaemon for AppDaemonServer {
|
|||||||
|
|
||||||
info!("App Daemon {} connected to receive brain messages", pubkey);
|
info!("App Daemon {} connected to receive brain messages", pubkey);
|
||||||
|
|
||||||
todo!()
|
let (tx, rx) = mpsc::channel(6);
|
||||||
|
{
|
||||||
|
let db = self.db.clone();
|
||||||
|
let pubkey = pubkey.clone();
|
||||||
|
let tx = tx.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = db::live_appnode_msgs::<db::NewAppReq>(&db, &pubkey, tx).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let db = self.db.clone();
|
||||||
|
let pubkey = pubkey.clone();
|
||||||
|
let tx = tx.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = db::live_appnode_msgs::<db::DeletedApp>(&db, &pubkey, tx).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let resp_stream = ReceiverStream::new(rx).map(|msg| Ok(msg.into()));
|
||||||
|
Ok(Response::new(Box::pin(resp_stream)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn daemon_messages(
|
async fn daemon_messages(
|
||||||
|
@ -285,3 +285,47 @@ impl From<db::ActiveAppWithNode> for AppContract {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<db::NewAppReq> for NewAppReq {
|
||||||
|
fn from(value: db::NewAppReq) -> Self {
|
||||||
|
let resource = AppResource {
|
||||||
|
vcpu: value.vcpu,
|
||||||
|
memory_mb: value.memory_mb,
|
||||||
|
disk_mb: value.disk_mb,
|
||||||
|
ports: value.ports,
|
||||||
|
};
|
||||||
|
let mr_enclave = Some(hex::decode(value.mr_enclave).unwrap_or_default());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
package_url: value.package_url,
|
||||||
|
node_pubkey: value.app_node.key().to_string(),
|
||||||
|
resource: Some(resource),
|
||||||
|
uuid: value.id.key().to_string(),
|
||||||
|
admin_pubkey: value.admin.key().to_string(),
|
||||||
|
price_per_unit: value.price_per_unit,
|
||||||
|
locked_nano: value.locked_nano,
|
||||||
|
hratls_pubkey: value.hratls_pubkey,
|
||||||
|
public_package_mr_enclave: mr_enclave,
|
||||||
|
app_name: value.app_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<db::DeletedApp> for DelAppReq {
|
||||||
|
fn from(value: db::DeletedApp) -> Self {
|
||||||
|
Self { uuid: value.id.key().to_string(), admin_pubkey: value.admin.key().to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<db::AppDaemonMsg> for BrainMessageApp {
|
||||||
|
fn from(value: db::AppDaemonMsg) -> Self {
|
||||||
|
match value {
|
||||||
|
db::AppDaemonMsg::Create(new_app_req) => {
|
||||||
|
BrainMessageApp { msg: Some(brain_message_app::Msg::NewAppReq(new_app_req.into())) }
|
||||||
|
}
|
||||||
|
db::AppDaemonMsg::Delete(del_app_req) => BrainMessageApp {
|
||||||
|
msg: Some(brain_message_app::Msg::DeleteAppReq(del_app_req.into())),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user