use crate::error::SandboxErrorCode;
use crate::network::Sandbox;
use crate::result::Result;
use async_process::Child;
use portpicker::pick_unused_port;
use tracing::info;
use near_sandbox_utils as sandbox;
pub struct SandboxServer {
pub(crate) rpc_port: u16,
pub(crate) net_port: u16,
process: Option<Child>,
}
impl SandboxServer {
pub fn new(rpc_port: u16, net_port: u16) -> Self {
Self {
rpc_port,
net_port,
process: None,
}
}
pub async fn start(&mut self) -> Result<()> {
if self.process.is_some() {
return Err(SandboxErrorCode::AlreadyStarted.into());
}
info!(target: "workspaces", "Starting up sandbox at localhost:{}", self.rpc_port);
let home_dir = Sandbox::home_dir(self.rpc_port);
supress_sandbox_logs_if_required();
let _ = std::fs::remove_dir_all(&home_dir);
let output = sandbox::init(&home_dir)
.map_err(|e| SandboxErrorCode::InitFailure.custom(e))?
.output()
.await
.map_err(|e| SandboxErrorCode::InitFailure.custom(e))?;
info!(target: "workspaces", "sandbox init: {:?}", output);
let child = sandbox::run(&home_dir, self.rpc_port, self.net_port)
.map_err(|e| SandboxErrorCode::RunFailure.custom(e))?;
info!(target: "workspaces", "Started sandbox: pid={:?}", child.id());
self.process = Some(child);
Ok(())
}
pub fn rpc_addr(&self) -> String {
format!("http://localhost:{}", self.rpc_port)
}
}
impl Default for SandboxServer {
fn default() -> Self {
let rpc_port = pick_unused_port().expect("no ports free");
let net_port = pick_unused_port().expect("no ports free");
Self::new(rpc_port, net_port)
}
}
impl Drop for SandboxServer {
fn drop(&mut self) {
if self.process.is_none() {
return;
}
let child = self.process.as_mut().unwrap();
info!(
target: "workspaces",
"Cleaning up sandbox: port={}, pid={}",
self.rpc_port,
child.id()
);
child
.kill()
.map_err(|e| format!("Could not cleanup sandbox due to: {:?}", e))
.unwrap();
}
}
fn supress_sandbox_logs_if_required() {
if let Ok(val) = std::env::var("NEAR_ENABLE_SANDBOX_LOG") {
if val != "0" {
return;
}
}
std::env::set_var("NEAR_SANDBOX_LOG", "near=error,stats=error,network=error");
}