use crate::{
cli::show::{self, ApplyStyle},
runner::WorkflowReceiptInfo,
workflow::{self, IndexedResources},
};
use chrono::NaiveDateTime;
use faststr::FastStr;
use libipld::Cid;
use serde::{Deserialize, Serialize};
use std::{fmt, net::SocketAddr, sync::Arc};
use tabled::{
builder::Builder,
col,
settings::{object::Rows, Format, Modify},
Table, Tabled,
};
use super::{DynamicNodeInfo, StaticNodeInfo};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Tabled)]
pub struct AckWorkflow {
pub(crate) cid: Cid,
pub(crate) name: FastStr,
pub(crate) num_tasks: u32,
pub(crate) progress_count: u32,
#[tabled(skip)]
pub(crate) resources: IndexedResources,
#[tabled(skip)]
pub(crate) replayed_receipt_info: Vec<WorkflowReceiptInfo>,
pub(crate) timestamp: String,
}
impl fmt::Display for AckWorkflow {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"cid: {}, progress: {}/{}, timestamp: {}",
self.cid, self.progress_count, self.num_tasks, self.timestamp
)
}
}
impl AckWorkflow {
pub(crate) fn new(
workflow_info: Arc<workflow::Info>,
replayed_receipt_info: Vec<WorkflowReceiptInfo>,
name: FastStr,
timestamp: NaiveDateTime,
) -> Self {
Self {
cid: workflow_info.cid,
name,
num_tasks: workflow_info.num_tasks,
progress_count: workflow_info.progress_count,
resources: workflow_info.resources.clone(),
replayed_receipt_info,
timestamp: timestamp.format("%Y-%m-%d %H:%M:%S").to_string(),
}
}
}
impl show::ConsoleTable for AckWorkflow {
fn table(&self) -> show::Output {
show::Output::new(Table::new(vec![self]).to_string())
}
fn echo_table(&self) -> Result<(), std::io::Error> {
let table = self.table();
let mut resource_table = Table::new(
self.resources
.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>(),
);
resource_table
.with(Modify::new(Rows::first()).with(Format::content(|_s| "Resources".to_string())));
let mut receipt_table_builder = Builder::default();
receipt_table_builder.push_record([
"Replayed Receipt".to_string(),
"Invocation Ran".to_string(),
"Instruction".to_string(),
]);
for (cid, info) in &self.replayed_receipt_info {
if let Some((ran, instruction)) = info {
receipt_table_builder.push_record([
cid.to_string(),
ran.to_string(),
instruction.to_string(),
]);
}
}
if receipt_table_builder.count_records() == 1 {
receipt_table_builder.push_record([
"<none>".to_string(),
"".to_string(),
"".to_string(),
]);
};
let receipt_table = receipt_table_builder.build();
let tbl = col![table, resource_table, receipt_table].default_with_title("run");
tbl.echo()
}
}
#[derive(Debug, Tabled)]
pub(crate) struct Ping {
address: SocketAddr,
response: String,
}
impl Ping {
pub(crate) fn new(address: SocketAddr, response: String) -> Self {
Self { address, response }
}
}
impl show::ConsoleTable for Ping {
fn table(&self) -> show::Output {
Table::new(vec![&self]).default_with_title("ping/pong")
}
fn echo_table(&self) -> Result<(), std::io::Error> {
self.table().echo()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Tabled)]
pub struct AckNodeInfo {
static_info: StaticNodeInfo,
dyn_info: DynamicNodeInfo,
}
impl fmt::Display for AckNodeInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "")
}
}
impl AckNodeInfo {
pub(crate) fn new(static_info: StaticNodeInfo, dyn_info: DynamicNodeInfo) -> Self {
Self {
static_info,
dyn_info,
}
}
}
impl show::ConsoleTable for AckNodeInfo {
fn table(&self) -> show::Output {
show::Output::new(Table::new(vec![self]).to_string())
}
fn echo_table(&self) -> Result<(), std::io::Error> {
let static_info_table = Table::new(vec![&self.static_info]);
let mut listeners_table = Table::new(
self.dyn_info
.listeners
.iter()
.map(|v| v.to_string())
.collect::<Vec<String>>(),
);
let conns = self
.dyn_info
.connections
.iter()
.map(|(k, v)| vec![k.to_string(), v.to_string()])
.collect::<Vec<Vec<String>>>();
let mut conns_table_builder = tabled::builder::Builder::from_iter(conns);
if conns_table_builder.count_records() == 0 {
conns_table_builder.push_record([
"Connections".to_string(),
"".to_string(),
"".to_string(),
]);
conns_table_builder.push_record(["<none>".to_string(), "".to_string(), "".to_string()]);
} else {
conns_table_builder.insert_record(
0,
["Connections".to_string(), "".to_string(), "".to_string()],
);
}
listeners_table.with(
Modify::new(Rows::first()).with(Format::content(|_s| "Listen Addresses".to_string())),
);
let conns_table = conns_table_builder.build();
let tbl = col![static_info_table, listeners_table, conns_table].default_with_title("node");
tbl.echo()
}
}
#[derive(Debug, Tabled)]
pub struct Info {
version: String,
git_sha: String,
timestamp: String,
features: String,
}
impl Default for Info {
fn default() -> Self {
Self::new()
}
}
impl Info {
pub(crate) fn new() -> Self {
Self {
version: env!("CARGO_PKG_VERSION").to_string(),
git_sha: option_env!("VERGEN_GIT_SHA")
.unwrap_or("unknown")
.to_string(),
timestamp: option_env!("VERGEN_GIT_COMMIT_TIMESTAMP")
.unwrap_or("unknown")
.to_string(),
features: env!("VERGEN_CARGO_FEATURES").to_string(),
}
}
}
impl show::ConsoleTable for Info {
fn table(&self) -> show::Output {
Table::new(vec![&self]).default_with_title("info")
}
fn echo_table(&self) -> Result<(), std::io::Error> {
self.table().echo()
}
}