///|
fn asset_index(assets : Array[AssetRef], key : String) -> Int? {
let mut result : Int? = None
for i, asset in assets {
if result is None && asset_ref_key(asset) == key {
result = Some(i)
}
}
result
}
///|
fn validate_assets(assets : Array[AssetRef]) -> Unit raise ModelError {
for i in 0.. id.value
Component(id) => id.value
}
if value == "" {
let field = match assets[i] {
Service(_) => "service_id"
Component(_) => "component_id"
}
raise ModelError::EmptyField(field)
}
for j in 0.. (Array[Array[Int]], Array[Int]) raise ModelError {
validate_assets(assets)
let adjacency : Array[Array[Int]] = []
let indegree : Array[Int] = []
for _ in 0.. index
None => raise ModelError::MissingAsset(dependency_key)
}
let dependent_index = match asset_index(assets, dependent_key) {
Some(index) => index
None => raise ModelError::MissingAsset(dependent_key)
}
for existing in adjacency[dependency_index] {
if existing == dependent_index {
raise ModelError::DuplicateDependency(
"\{dependency_key} -> \{dependent_key}",
)
}
}
adjacency[dependency_index].push(dependent_index)
indegree[dependent_index] = indegree[dependent_index] + 1
}
(adjacency, indegree)
}
///|
fn detect_cycle(
node : Int,
assets : Array[AssetRef],
adjacency : Array[Array[Int]],
state : Array[Int],
) -> Unit raise ModelError {
if state[node] == 1 {
raise ModelError::DependencyCycle(asset_ref_key(assets[node]))
}
if state[node] == 2 {
()
} else {
state[node] = 1
for dependent in adjacency[node] {
detect_cycle(dependent, assets, adjacency, state)
}
state[node] = 2
}
}
///|
fn ensure_acyclic(
assets : Array[AssetRef],
adjacency : Array[Array[Int]],
) -> Unit raise ModelError {
let state : Array[Int] = []
for _ in 0.. Array[AssetRef] raise ModelError {
let (adjacency, indegree) = build_adjacency(assets, dependencies)
ensure_acyclic(assets, adjacency)
let ready : Array[Int] = []
for i in 0.. Unit raise ModelError {
let _ = dependency_order(assets, dependencies)
}