Skip to main content

gear_node_wrapper/
node.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4//! Gear protocol node wrapper
5use crate::{Log, NodeInstance, utils};
6use anyhow::Result;
7use std::{
8    env,
9    path::Path,
10    process::{Command, Stdio},
11};
12
13const GEAR_BINARY: &str = "gear";
14const DEFAULT_ARGS: [&str; 4] = ["--dev", "--tmp", "--no-hardware-benchmarks", "--rpc-port"];
15
16/// Gear protocol node wrapper
17pub struct Node {
18    /// Node command
19    command: Command,
20    /// The rpc port of the node if any
21    port: Option<u16>,
22    /// How many logs should the log holder stores
23    logs: Option<usize>,
24}
25
26impl Node {
27    /// Create a new from gear command that found
28    /// in the current system.
29    pub fn new() -> Result<Self> {
30        Self::from_path(which::which(GEAR_BINARY)?)
31    }
32
33    /// Create a new node from path
34    pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {
35        Ok(Self {
36            command: Command::new(path.as_ref()),
37            port: None,
38            logs: None,
39        })
40    }
41
42    /// Append argument to the node
43    ///
44    /// see also [`Node::args`]
45    pub fn arg(&mut self, arg: &str) -> &mut Self {
46        self.command.arg(arg);
47        self
48    }
49
50    /// Append arguments to the node
51    ///
52    /// NOTE: argument `--dev` is managed by [`Node::spawn`] and could not be removed, if
53    /// you are about to run a production node, please run the node binary directly.
54    pub fn args(&mut self, args: &[&str]) -> &mut Self {
55        self.command.args(args);
56        self
57    }
58
59    /// Sets the rpc port and returns self.
60    pub fn rpc_port(&mut self, port: u16) -> &mut Self {
61        self.port = Some(port);
62        self
63    }
64
65    /// The log holder stores 256 lines of matched logs
66    /// by default, here in this function we receive a limit
67    /// of the logs and resize the logger on spawning.
68    pub fn logs(&mut self, limit: usize) -> &mut Self {
69        self.logs = Some(limit);
70        self
71    }
72
73    /// Spawn the node
74    pub fn spawn(&mut self) -> Result<NodeInstance> {
75        let port = self.port.unwrap_or(utils::pick()).to_string();
76        let mut args = DEFAULT_ARGS.to_vec();
77        args.push(&port);
78
79        let mut process = self
80            .command
81            .env(
82                "RUST_LOG",
83                env::var_os("GEAR_NODE_WRAPPER_LOG")
84                    .or_else(|| env::var_os("RUST_LOG"))
85                    .unwrap_or_default(),
86            )
87            .args(args)
88            .stderr(Stdio::piped())
89            .stdout(Stdio::piped())
90            .spawn()?;
91
92        let address = format!("{}:{port}", utils::LOCALHOST).parse()?;
93        let mut log = Log::new(self.logs);
94        log.spawn(&mut process)?;
95        Ok(NodeInstance {
96            address,
97            log,
98            process,
99        })
100    }
101}