use std::collections::HashSet;
use anyhow::{Result, bail};
use crate::model::*;
pub fn validate(svc: &ServiceModel) -> Result<()> {
no_name_collisions(svc)?;
workflows_have_task_queue(svc)?;
signals_return_empty(svc)?;
refs_resolve(svc)?;
Ok(())
}
fn workflows_have_task_queue(svc: &ServiceModel) -> Result<()> {
for w in &svc.workflows {
if svc.resolved_task_queue(w).is_empty() {
bail!(
"{}.{}: workflow {:?} has no task_queue. Set option (temporal.v1.workflow) = {{ task_queue: \"...\" }} on the rpc, or option (temporal.v1.service) = {{ task_queue: \"...\" }} on the service.",
svc.package,
svc.service,
w.rpc_method
);
}
}
Ok(())
}
fn no_name_collisions(svc: &ServiceModel) -> Result<()> {
let entries = svc
.workflows
.iter()
.map(|w| {
(
w.registered_name.as_deref().unwrap_or(&w.rpc_method),
"workflow",
)
})
.chain(
svc.signals
.iter()
.map(|s| (s.registered_name.as_str(), "signal")),
)
.chain(
svc.queries
.iter()
.map(|q| (q.registered_name.as_str(), "query")),
)
.chain(
svc.updates
.iter()
.map(|u| (u.registered_name.as_str(), "update")),
)
.chain(
svc.activities
.iter()
.map(|a| (a.registered_name.as_str(), "activity")),
);
let mut seen: HashSet<&str> = HashSet::new();
for (name, kind) in entries {
if !seen.insert(name) {
bail!(
"{}.{}: name {:?} ({}) collides with another method registered name",
svc.package,
svc.service,
name,
kind
);
}
}
Ok(())
}
fn signals_return_empty(svc: &ServiceModel) -> Result<()> {
for s in &svc.signals {
if !s.output_type.is_empty {
bail!(
"{}.{}: signal rpc {:?} must return google.protobuf.Empty, got {}",
svc.package,
svc.service,
s.rpc_method,
s.output_type.full_name
);
}
}
Ok(())
}
fn refs_resolve(svc: &ServiceModel) -> Result<()> {
let signal_methods: HashSet<&str> = svc.signals.iter().map(|s| s.rpc_method.as_str()).collect();
let query_methods: HashSet<&str> = svc.queries.iter().map(|q| q.rpc_method.as_str()).collect();
let update_methods: HashSet<&str> = svc.updates.iter().map(|u| u.rpc_method.as_str()).collect();
for w in &svc.workflows {
for r in &w.attached_signals {
if !signal_methods.contains(r.method.as_str()) {
bail!(
"{}.{}: workflow {:?} references unknown signal ref {:?}",
svc.package,
svc.service,
w.rpc_method,
r.method
);
}
}
for r in &w.attached_queries {
if !query_methods.contains(r.method.as_str()) {
bail!(
"{}.{}: workflow {:?} references unknown query ref {:?}",
svc.package,
svc.service,
w.rpc_method,
r.method
);
}
}
for r in &w.attached_updates {
if !update_methods.contains(r.method.as_str()) {
bail!(
"{}.{}: workflow {:?} references unknown update ref {:?}",
svc.package,
svc.service,
w.rpc_method,
r.method
);
}
}
}
Ok(())
}