App contract payment
implement online/offline status updates add timer to charge app contract modified app_node in schema
This commit is contained in:
parent
ee1b12f85f
commit
dcacd7b6b0
@ -13,7 +13,7 @@ server="$1"
|
||||
}
|
||||
|
||||
[[ "$server" == "testnet" ]] && server="root@prod-brain-1"
|
||||
[[ "$server" == "staging" ]] && server="brain-staging"
|
||||
[[ "$server" == "staging" ]] && server="root@brain-staging"
|
||||
|
||||
cargo build --release --bin brain
|
||||
ssh $server systemctl stop detee-brain.service
|
||||
|
@ -31,7 +31,8 @@ pub struct AppNode {
|
||||
pub avail_ports: u32,
|
||||
pub max_ports_per_app: u32,
|
||||
pub price: u64,
|
||||
pub offline_minutes: u64,
|
||||
pub connected_at: Datetime,
|
||||
pub disconnected_at: Datetime,
|
||||
}
|
||||
|
||||
impl AppNode {
|
||||
@ -41,6 +42,18 @@ impl AppNode {
|
||||
let app_node: Option<AppNode> = db.upsert(app_node_id.clone()).content(self).await?;
|
||||
app_node.ok_or(Error::FailedToCreateDBEntry(format!("{APP_NODE}:{app_node_id}")))
|
||||
}
|
||||
|
||||
pub async fn set_online(db: &Surreal<Client>, app_node_id: &str) -> Result<(), Error> {
|
||||
db.query(format!("UPDATE {APP_NODE}:{app_node_id} SET connected_at = time::now();"))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn set_offline(db: &Surreal<Client>, app_node_id: &str) -> Result<(), Error> {
|
||||
db.query(format!("UPDATE {APP_NODE}:{app_node_id} SET disconnected_at = time::now();"))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AppDaemonMsg {
|
||||
@ -634,7 +647,8 @@ impl From<&old_brain::BrainData> for Vec<AppNode> {
|
||||
avail_ports: old_node.avail_no_of_port,
|
||||
max_ports_per_app: old_node.max_ports_per_app,
|
||||
price: old_node.price,
|
||||
offline_minutes: old_node.offline_minutes,
|
||||
disconnected_at: Datetime::default(),
|
||||
connected_at: Datetime::default(),
|
||||
});
|
||||
}
|
||||
nodes
|
||||
|
@ -57,7 +57,8 @@ impl BrainAppDaemon for AppDaemonServer {
|
||||
avail_storage_gbs: 0,
|
||||
avail_ports: 0,
|
||||
max_ports_per_app: 0,
|
||||
offline_minutes: 0,
|
||||
disconnected_at: surrealdb::sql::Datetime::default(),
|
||||
connected_at: surrealdb::sql::Datetime::default(),
|
||||
};
|
||||
|
||||
app_node.register(&self.db).await?;
|
||||
@ -89,6 +90,7 @@ impl BrainAppDaemon for AppDaemonServer {
|
||||
)?;
|
||||
|
||||
info!("App Daemon {} connected to receive brain messages", pubkey);
|
||||
let _ = db::AppNode::set_online(&self.db, &pubkey).await;
|
||||
|
||||
let (tx, rx) = mpsc::channel(6);
|
||||
{
|
||||
@ -162,7 +164,8 @@ impl BrainAppDaemon for AppDaemonServer {
|
||||
},
|
||||
|
||||
Err(e) => {
|
||||
log::warn!("App Daemon Disconnected: {e:?}")
|
||||
log::warn!("App Daemon Disconnected: {e:?}");
|
||||
let _ = db::AppNode::set_offline(&self.db, &pubkey).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,7 +94,8 @@ DEFINE FIELD avail_storage_gbs ON TABLE app_node TYPE int;
|
||||
DEFINE FIELD avail_ports ON TABLE app_node TYPE int;
|
||||
DEFINE FIELD max_ports_per_app 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 connected_at ON TABLE app_node TYPE datetime;
|
||||
DEFINE FIELD disconnected_at ON TABLE app_node TYPE datetime;
|
||||
|
||||
DEFINE TABLE new_app_req Type RELATION FROM account to app_node SCHEMAFULL;
|
||||
DEFINE FIELD app_name ON TABLE new_app_req TYPE string;
|
||||
|
@ -30,4 +30,32 @@ FOR $contract IN (select * from active_vm fetch out) {
|
||||
};
|
||||
};
|
||||
|
||||
-- TODO: implement for active_app
|
||||
FOR $app_contract IN (select * from active_app fetch out) {
|
||||
LET $operator = (select * from $app_contract.out.operator)[0];
|
||||
LET $node_is_online = $app_contract.out.collected_at > $app_contract.out.disconnected_at;
|
||||
LET $price_per_minute = fn::app_price_per_minute($app_contract.id);
|
||||
LET $amount_due = (time::now() - $app_contract.collected_at).mins() * $price_per_minute;
|
||||
LET $amount_paid = IF $amount_due > $app_contract.locked_nano {
|
||||
$app_contract.locked_nano
|
||||
} ELSE {
|
||||
$amount_due
|
||||
};
|
||||
LET $escrow_multiplier = IF $operator.escrow < 5_000_000_000_000 { 1 } ELSE { 5 };
|
||||
IF $node_is_online {
|
||||
UPDATE $operator.id SET balance += $amount_paid * $escrow_multiplier;
|
||||
UPDTE $app_contract.id SET
|
||||
locked_nano -= $amount_paid,
|
||||
collected_at = time::now();
|
||||
} ELSE {
|
||||
LET $compensation = IF $amount_due > $operator.escrow {
|
||||
$operator.escrow
|
||||
} ELSE {
|
||||
$amount_due
|
||||
};
|
||||
UPDATE $operator.id SET escrow -= $compensation;
|
||||
UPDATE $app_contract.in SET balance += $compensation;
|
||||
};
|
||||
IF $amount_paid >= $app_contract.locked_nano {
|
||||
fn::delete_app($app_contract.id);
|
||||
}
|
||||
}
|
@ -93,6 +93,7 @@ async fn test_app_creation() {
|
||||
db.select::<Option<db::ActiveApp>>((ACTIVE_APP, new_app_resp.uuid)).await.unwrap();
|
||||
assert!(active_app.is_some());
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
let acc_db: db::Account = db.select((ACCOUNT, key.pubkey.clone())).await.unwrap().unwrap();
|
||||
assert_eq!(acc_db.balance, airdrop_amount * TOKEN_DECIMAL - (locking_nano + 100));
|
||||
assert_eq!(acc_db.tmp_locked, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user