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