demo_feed_publisher/
main.rs1mod authority;
9mod cadence;
10mod envelope;
11mod graph;
12mod jcs;
13
14use std::env;
15use std::path::PathBuf;
16use std::process::ExitCode;
17use std::thread;
18
19use authority::{FeedAuthority, FileGenerationStore};
20use cadence::{CadenceEngine, SNAPSHOT_PERIOD, TICK_INTERVAL};
21use envelope::{ComponentId, FrameEnvelopeCodec};
22use graph::GraphViewState;
23use liminal_sdk::PushClient;
24
25const DEFAULT_ADDRESS: &str = "127.0.0.1:9000";
26const DEFAULT_CHANNEL: &str = "frame.demo.graph-view";
27const DEFAULT_COMPONENT_ID: &str = "graph-view-demo";
28const DEFAULT_GENERATION_FILE: &str = ".liminal-demo-feed-generation";
29
30#[derive(Debug, thiserror::Error)]
31enum AppError {
32 #[error("configuration variable {name} is not valid Unicode: {source}")]
33 Configuration {
34 name: &'static str,
35 source: env::VarError,
36 },
37 #[error(transparent)]
38 Authority(#[from] authority::AuthorityError),
39 #[error(transparent)]
40 Contract(#[from] envelope::EnvelopeError),
41 #[error(transparent)]
42 Graph(#[from] graph::GraphError),
43 #[error("failed to connect demo publisher: {0}")]
44 Connect(liminal_sdk::SdkError),
45 #[error(transparent)]
46 Cadence(#[from] cadence::CadenceError),
47}
48
49fn configured(name: &'static str, default: &str) -> Result<String, AppError> {
50 match env::var(name) {
51 Ok(value) => Ok(value),
52 Err(env::VarError::NotPresent) => Ok(default.to_owned()),
53 Err(source) => Err(AppError::Configuration { name, source }),
54 }
55}
56
57fn run() -> Result<(), AppError> {
58 let address = configured("LIMINAL_ADDRESS", DEFAULT_ADDRESS)?;
59 let channel = configured("LIMINAL_DEMO_CHANNEL", DEFAULT_CHANNEL)?;
60 let component_id = ComponentId::new(&configured(
61 "LIMINAL_DEMO_COMPONENT_ID",
62 DEFAULT_COMPONENT_ID,
63 )?)?;
64 let generation_file = PathBuf::from(configured(
65 "LIMINAL_DEMO_GENERATION_FILE",
66 DEFAULT_GENERATION_FILE,
67 )?);
68
69 let authority = FeedAuthority::start(FileGenerationStore::new(generation_file))?;
70
71 let client = PushClient::connect(&address).map_err(AppError::Connect)?;
75 let writer = client.writer_handle();
76 let mut cadence = CadenceEngine::new(
77 channel,
78 component_id,
79 authority,
80 FrameEnvelopeCodec,
81 GraphViewState::new()?,
82 writer,
83 SNAPSHOT_PERIOD,
84 )?;
85
86 cadence.emit_initial_snapshot()?;
87 loop {
88 thread::sleep(TICK_INTERVAL);
91 cadence.emit_tick()?;
92 }
93}
94
95fn main() -> ExitCode {
96 match run() {
97 Ok(()) => ExitCode::SUCCESS,
98 Err(error) => {
99 eprintln!("demo feed publisher failed: {error}");
100 ExitCode::FAILURE
101 }
102 }
103}