fn __schedule_list(value: any) {
if type_of(value) == "list" {
return value
}
return []
}
fn __schedule_string(value: any, fallback: string = "") {
if type_of(value) == "string" {
return value
}
return fallback
}
fn __schedule_int(value: any, fallback: any = nil) {
if type_of(value) == "int" {
return value
}
return fallback
}
fn __schedule_contains(values: any, value: any) {
return contains(__schedule_list(values), value)
}
fn __schedule_incoming_edges(graph: dict, node_id: any) {
let incoming = []
for edge in __schedule_list(graph?.edges) {
if edge?.to == node_id {
incoming = incoming.appending(edge)
}
}
return incoming
}
fn __schedule_required_inputs(node: dict, incoming_count: int) {
const explicit = __schedule_int(node?.join_policy?.min_completed)
if explicit != nil {
return explicit
}
const strategy = __schedule_string(node?.join_policy?.strategy, "all")
if node?.join_policy?.require_all_inputs || strategy == "all" {
return incoming_count
}
return 1
}
/**
* workflow_join_readiness.
*
* @effects: []
* @errors: []
* @api_stability: experimental
*/
pub fn workflow_join_readiness(config: dict? = nil) {
const node_id = __schedule_string(config?.node_id, "")
const {node = {}, graph = {}} = config ?? {}
const completed_nodes = __schedule_list(config?.completed_nodes)
const incoming = __schedule_incoming_edges(graph, node_id)
const required = __schedule_required_inputs(node, len(incoming))
let completed_inputs = 0
for edge in incoming {
if __schedule_contains(completed_nodes, edge?.from) {
completed_inputs = completed_inputs + 1
}
}
return {
ready: completed_inputs >= required,
required: required,
completed_inputs: completed_inputs,
}
}
fn __schedule_branch_matches(left: any, right: any) {
if left == nil && right == nil {
return true
}
return left == right
}
/**
* workflow_next_edges.
*
* @effects: []
* @errors: []
* @api_stability: experimental
*/
pub fn workflow_next_edges(config: any = nil) {
const graph = config?.graph ?? {}
const current = __schedule_string(config?.current, "")
const branch = config?.branch
let exact = []
let default_edges = []
for edge in __schedule_list(graph?.edges) {
if edge?.from != current {
continue
}
if __schedule_branch_matches(edge?.branch, branch) {
exact = exact.appending(edge)
}
if edge?.branch == nil {
default_edges = default_edges.appending(edge)
}
}
if len(exact) > 0 || branch == nil {
return exact
}
return default_edges
}