Skip to main content

spike/
spike.rs

1//! M0 spike: prove the RPC shapes the rest of tmprl is built on.
2//!
3//! Run against a local dev server:
4//!     temporal server start-dev
5//!     cargo run -p tmprl-client --example spike
6//!
7//! It deliberately exercises the four calls that M1 and M2 depend on:
8//!   - ListNamespaces          (namespace switcher)
9//!   - CountWorkflowExecutions (status counts in the list header)
10//!   - ListWorkflowExecutions  (the workflow table + its paging token)
11//!   - GetWorkflowExecutionHistory (history view; `wait_new_event` is follow mode)
12
13use temporalio_client::tonic::Request;
14use tmprl_client::{Conn, ProfileRef};
15
16// The generated protos live under temporalio_common, re-exported through the client's deps.
17use temporalio_common::protos::temporal::api::{
18    common::v1::WorkflowExecution,
19    enums::v1::HistoryEventFilterType,
20    workflowservice::v1::{
21        CountWorkflowExecutionsRequest, GetWorkflowExecutionHistoryRequest, ListNamespacesRequest,
22        ListWorkflowExecutionsRequest,
23    },
24};
25
26#[tokio::main]
27async fn main() -> anyhow::Result<()> {
28    let profile = ProfileRef {
29        name: std::env::args().nth(1),
30        config_file: None,
31    };
32
33    let conn = Conn::connect(&profile).await?;
34    println!(
35        "connected  profile={}  address={}  namespace={}",
36        conn.profile(),
37        conn.address(),
38        conn.namespace()
39    );
40
41    let mut wf = conn.wf();
42    let ns = wf
43        .list_namespaces(Request::new(ListNamespacesRequest {
44            page_size: 50,
45            ..Default::default()
46        }))
47        .await?
48        .into_inner();
49    println!("\nnamespaces ({}):", ns.namespaces.len());
50    for n in &ns.namespaces {
51        if let Some(info) = &n.namespace_info {
52            println!("  - {}", info.name);
53        }
54    }
55
56    let count = wf
57        .count_workflow_executions(Request::new(CountWorkflowExecutionsRequest {
58            namespace: conn.namespace().to_string(),
59            query: String::new(),
60        }))
61        .await?
62        .into_inner();
63    println!(
64        "\ntotal workflows in `{}`: {}",
65        conn.namespace(),
66        count.count
67    );
68
69    let list = wf
70        .list_workflow_executions(Request::new(ListWorkflowExecutionsRequest {
71            namespace: conn.namespace().to_string(),
72            page_size: 10,
73            query: String::new(),
74            ..Default::default()
75        }))
76        .await?
77        .into_inner();
78
79    println!("\nworkflows ({} shown):", list.executions.len());
80    let mut first: Option<WorkflowExecution> = None;
81    for e in &list.executions {
82        let exec = e.execution.clone().unwrap_or_default();
83        println!(
84            "  {:<10} {:<28} {}",
85            format!("{:?}", e.status()),
86            e.r#type.as_ref().map(|t| t.name.as_str()).unwrap_or("?"),
87            exec.workflow_id
88        );
89        first.get_or_insert(exec);
90    }
91    println!("  next_page_token: {} bytes", list.next_page_token.len());
92
93    if let Some(exec) = first {
94        let hist = wf
95            .get_workflow_execution_history(Request::new(GetWorkflowExecutionHistoryRequest {
96                namespace: conn.namespace().to_string(),
97                execution: Some(exec.clone()),
98                maximum_page_size: 100,
99                // `wait_new_event: true` is what turns this into `tail -f`. Left false
100                // here so the spike terminates.
101                wait_new_event: false,
102                history_event_filter_type: HistoryEventFilterType::AllEvent as i32,
103                ..Default::default()
104            }))
105            .await?
106            .into_inner();
107
108        let events = hist.history.map(|h| h.events).unwrap_or_default();
109        println!(
110            "\nhistory of {} ({} events):",
111            exec.workflow_id,
112            events.len()
113        );
114        for ev in events.iter().take(15) {
115            println!("  {:>4}  {:?}", ev.event_id, ev.event_type());
116        }
117    }
118
119    Ok(())
120}