igniter 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE.txt +21 -0
- data/README.md +264 -0
- data/docs/API_V2.md +242 -0
- data/docs/ARCHITECTURE_V2.md +317 -0
- data/docs/EXECUTION_MODEL_V2.md +245 -0
- data/docs/IGNITER_CONCEPTS.md +81 -0
- data/examples/README.md +77 -0
- data/examples/basic_pricing.rb +27 -0
- data/examples/composition.rb +39 -0
- data/examples/diagnostics.rb +28 -0
- data/lib/igniter/compiler/compiled_graph.rb +78 -0
- data/lib/igniter/compiler/graph_compiler.rb +60 -0
- data/lib/igniter/compiler/validator.rb +205 -0
- data/lib/igniter/compiler.rb +10 -0
- data/lib/igniter/contract.rb +117 -0
- data/lib/igniter/diagnostics/report.rb +174 -0
- data/lib/igniter/diagnostics.rb +8 -0
- data/lib/igniter/dsl/contract_builder.rb +95 -0
- data/lib/igniter/dsl.rb +8 -0
- data/lib/igniter/errors.rb +53 -0
- data/lib/igniter/events/bus.rb +39 -0
- data/lib/igniter/events/event.rb +53 -0
- data/lib/igniter/events.rb +9 -0
- data/lib/igniter/extensions/auditing/timeline.rb +99 -0
- data/lib/igniter/extensions/auditing.rb +10 -0
- data/lib/igniter/extensions/introspection/graph_formatter.rb +73 -0
- data/lib/igniter/extensions/introspection/runtime_formatter.rb +102 -0
- data/lib/igniter/extensions/introspection.rb +11 -0
- data/lib/igniter/extensions/reactive/engine.rb +36 -0
- data/lib/igniter/extensions/reactive/matcher.rb +21 -0
- data/lib/igniter/extensions/reactive/reaction.rb +17 -0
- data/lib/igniter/extensions/reactive.rb +12 -0
- data/lib/igniter/extensions.rb +10 -0
- data/lib/igniter/model/composition_node.rb +22 -0
- data/lib/igniter/model/compute_node.rb +21 -0
- data/lib/igniter/model/graph.rb +15 -0
- data/lib/igniter/model/input_node.rb +27 -0
- data/lib/igniter/model/node.rb +22 -0
- data/lib/igniter/model/output_node.rb +21 -0
- data/lib/igniter/model.rb +13 -0
- data/lib/igniter/runtime/cache.rb +58 -0
- data/lib/igniter/runtime/execution.rb +142 -0
- data/lib/igniter/runtime/input_validator.rb +145 -0
- data/lib/igniter/runtime/invalidator.rb +52 -0
- data/lib/igniter/runtime/node_state.rb +31 -0
- data/lib/igniter/runtime/resolver.rb +114 -0
- data/lib/igniter/runtime/result.rb +105 -0
- data/lib/igniter/runtime.rb +14 -0
- data/lib/igniter/version.rb +5 -0
- data/lib/igniter.rb +20 -0
- data/sig/igniter.rbs +4 -0
- metadata +126 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Igniter
|
|
4
|
+
module Runtime
|
|
5
|
+
class InputValidator
|
|
6
|
+
SUPPORTED_TYPES = {
|
|
7
|
+
integer: Integer,
|
|
8
|
+
float: Float,
|
|
9
|
+
numeric: Numeric,
|
|
10
|
+
string: String,
|
|
11
|
+
boolean: :boolean,
|
|
12
|
+
array: Array,
|
|
13
|
+
hash: Hash,
|
|
14
|
+
symbol: Symbol
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
def initialize(compiled_graph)
|
|
18
|
+
@compiled_graph = compiled_graph
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def normalize_initial_inputs(raw_inputs)
|
|
22
|
+
inputs = symbolize_keys(raw_inputs)
|
|
23
|
+
|
|
24
|
+
validate_unknown_inputs!(inputs)
|
|
25
|
+
apply_defaults(inputs)
|
|
26
|
+
validate_known_inputs!(inputs)
|
|
27
|
+
|
|
28
|
+
inputs
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def validate_update!(name, value)
|
|
32
|
+
input_node = fetch_input_node(name)
|
|
33
|
+
validate_required!(input_node, value)
|
|
34
|
+
validate_type!(input_node, value)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def fetch_value!(name, inputs)
|
|
38
|
+
input_node = fetch_input_node(name)
|
|
39
|
+
value = inputs.fetch(name.to_sym) { missing_value!(input_node) }
|
|
40
|
+
|
|
41
|
+
validate_required!(input_node, value)
|
|
42
|
+
validate_type!(input_node, value)
|
|
43
|
+
value
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def input_nodes
|
|
49
|
+
@input_nodes ||= @compiled_graph.nodes.select { |node| node.kind == :input }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def input_nodes_by_name
|
|
53
|
+
@input_nodes_by_name ||= input_nodes.each_with_object({}) { |node, memo| memo[node.name] = node }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def fetch_input_node(name)
|
|
57
|
+
input_nodes_by_name.fetch(name.to_sym)
|
|
58
|
+
rescue KeyError
|
|
59
|
+
raise InputError.new("Unknown input: #{name}", context: { graph: @compiled_graph.name, node_name: name.to_sym })
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def validate_unknown_inputs!(inputs)
|
|
63
|
+
unknown = inputs.keys - input_nodes_by_name.keys
|
|
64
|
+
return if unknown.empty?
|
|
65
|
+
|
|
66
|
+
raise InputError.new(
|
|
67
|
+
"Unknown inputs: #{unknown.sort.join(', ')}",
|
|
68
|
+
context: { graph: @compiled_graph.name }
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def apply_defaults(inputs)
|
|
73
|
+
input_nodes.each do |node|
|
|
74
|
+
next if inputs.key?(node.name)
|
|
75
|
+
next unless node.default?
|
|
76
|
+
|
|
77
|
+
inputs[node.name] = node.default
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def validate_known_inputs!(inputs)
|
|
82
|
+
inputs.each do |name, value|
|
|
83
|
+
input_node = fetch_input_node(name)
|
|
84
|
+
validate_required!(input_node, value)
|
|
85
|
+
validate_type!(input_node, value)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def missing_value!(input_node)
|
|
90
|
+
return input_node.default if input_node.default?
|
|
91
|
+
return nil unless input_node.required?
|
|
92
|
+
|
|
93
|
+
raise input_error(input_node, "Missing required input: #{input_node.name}")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def validate_required!(input_node, value)
|
|
97
|
+
return unless input_node.required?
|
|
98
|
+
return unless value.nil?
|
|
99
|
+
|
|
100
|
+
raise input_error(input_node, "Input '#{input_node.name}' is required")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def validate_type!(input_node, value)
|
|
104
|
+
return if value.nil?
|
|
105
|
+
return unless input_node.type
|
|
106
|
+
|
|
107
|
+
unless supported_type?(input_node.type)
|
|
108
|
+
raise input_error(input_node, "Unsupported input type '#{input_node.type}' for '#{input_node.name}'")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
return if type_match?(input_node.type, value)
|
|
112
|
+
|
|
113
|
+
raise input_error(input_node, "Input '#{input_node.name}' must be of type #{input_node.type}, got #{value.class}")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def supported_type?(type)
|
|
117
|
+
SUPPORTED_TYPES.key?(type.to_sym)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def type_match?(type, value)
|
|
121
|
+
matcher = SUPPORTED_TYPES.fetch(type.to_sym)
|
|
122
|
+
return value == true || value == false if matcher == :boolean
|
|
123
|
+
|
|
124
|
+
value.is_a?(matcher)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def symbolize_keys(hash)
|
|
128
|
+
hash.each_with_object({}) { |(key, value), memo| memo[key.to_sym] = value }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def input_error(input_node, message)
|
|
132
|
+
InputError.new(
|
|
133
|
+
message,
|
|
134
|
+
context: {
|
|
135
|
+
graph: @compiled_graph.name,
|
|
136
|
+
node_id: input_node.id,
|
|
137
|
+
node_name: input_node.name,
|
|
138
|
+
node_path: input_node.path,
|
|
139
|
+
source_location: input_node.source_location
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Igniter
|
|
4
|
+
module Runtime
|
|
5
|
+
class Invalidator
|
|
6
|
+
def initialize(execution)
|
|
7
|
+
@execution = execution
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def invalidate_from(node_name)
|
|
11
|
+
queue = @execution.compiled_graph.dependents.fetch(node_name.to_sym, []).dup
|
|
12
|
+
seen = {}
|
|
13
|
+
|
|
14
|
+
until queue.empty?
|
|
15
|
+
dependent_name = queue.shift
|
|
16
|
+
next if seen[dependent_name]
|
|
17
|
+
|
|
18
|
+
seen[dependent_name] = true
|
|
19
|
+
dependent_node = @execution.compiled_graph.fetch_node(dependent_name)
|
|
20
|
+
stale_state = @execution.cache.stale!(dependent_node, invalidated_by: node_name.to_sym)
|
|
21
|
+
|
|
22
|
+
if stale_state
|
|
23
|
+
@execution.events.emit(
|
|
24
|
+
:node_invalidated,
|
|
25
|
+
node: dependent_node,
|
|
26
|
+
status: :stale,
|
|
27
|
+
payload: { cause: node_name.to_sym }
|
|
28
|
+
)
|
|
29
|
+
emit_output_invalidations_for(dependent_node.name, node_name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
queue.concat(@execution.compiled_graph.dependents.fetch(dependent_name, []))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def emit_output_invalidations_for(source_name, cause_name)
|
|
39
|
+
@execution.compiled_graph.outputs.each do |output_node|
|
|
40
|
+
next unless output_node.source == source_name.to_sym
|
|
41
|
+
|
|
42
|
+
@execution.events.emit(
|
|
43
|
+
:node_invalidated,
|
|
44
|
+
node: output_node,
|
|
45
|
+
status: :stale,
|
|
46
|
+
payload: { cause: cause_name.to_sym }
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Igniter
|
|
4
|
+
module Runtime
|
|
5
|
+
class NodeState
|
|
6
|
+
attr_reader :node, :status, :value, :error, :version, :resolved_at, :invalidated_by
|
|
7
|
+
|
|
8
|
+
def initialize(node:, status:, value: nil, error: nil, version: nil, resolved_at: Time.now.utc, invalidated_by: nil)
|
|
9
|
+
@node = node
|
|
10
|
+
@status = status
|
|
11
|
+
@value = value
|
|
12
|
+
@error = error
|
|
13
|
+
@version = version
|
|
14
|
+
@resolved_at = resolved_at
|
|
15
|
+
@invalidated_by = invalidated_by
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def stale?
|
|
19
|
+
status == :stale
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def succeeded?
|
|
23
|
+
status == :succeeded
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def failed?
|
|
27
|
+
status == :failed
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Igniter
|
|
4
|
+
module Runtime
|
|
5
|
+
class Resolver
|
|
6
|
+
def initialize(execution)
|
|
7
|
+
@execution = execution
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def resolve(node_name)
|
|
11
|
+
node = @execution.compiled_graph.fetch_node(node_name)
|
|
12
|
+
cached = @execution.cache.fetch(node.name)
|
|
13
|
+
return cached if cached && !cached.stale?
|
|
14
|
+
|
|
15
|
+
@execution.events.emit(:node_started, node: node, status: :running)
|
|
16
|
+
|
|
17
|
+
state = case node.kind
|
|
18
|
+
when :input
|
|
19
|
+
resolve_input(node)
|
|
20
|
+
when :compute
|
|
21
|
+
resolve_compute(node)
|
|
22
|
+
when :composition
|
|
23
|
+
resolve_composition(node)
|
|
24
|
+
else
|
|
25
|
+
raise ResolutionError, "Unsupported node kind: #{node.kind}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@execution.cache.write(state)
|
|
29
|
+
@execution.events.emit(
|
|
30
|
+
state.failed? ? :node_failed : :node_succeeded,
|
|
31
|
+
node: node,
|
|
32
|
+
status: state.status,
|
|
33
|
+
payload: success_payload(node, state)
|
|
34
|
+
)
|
|
35
|
+
state
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
state = NodeState.new(node: node, status: :failed, error: normalize_error(e, node))
|
|
38
|
+
@execution.cache.write(state)
|
|
39
|
+
@execution.events.emit(:node_failed, node: node, status: :failed, payload: { error: state.error.message })
|
|
40
|
+
state
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def resolve_input(node)
|
|
46
|
+
NodeState.new(node: node, status: :succeeded, value: @execution.fetch_input!(node.name))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def resolve_compute(node)
|
|
50
|
+
dependencies = node.dependencies.each_with_object({}) do |dependency_name, memo|
|
|
51
|
+
dependency_state = resolve(dependency_name)
|
|
52
|
+
raise dependency_state.error if dependency_state.failed?
|
|
53
|
+
|
|
54
|
+
memo[dependency_name] = dependency_state.value
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
value = call_compute(node.callable, dependencies)
|
|
58
|
+
NodeState.new(node: node, status: :succeeded, value: value)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def call_compute(callable, dependencies)
|
|
62
|
+
case callable
|
|
63
|
+
when Proc
|
|
64
|
+
callable.call(**dependencies)
|
|
65
|
+
when Symbol, String
|
|
66
|
+
@execution.contract_instance.public_send(callable.to_sym, **dependencies)
|
|
67
|
+
else
|
|
68
|
+
raise ResolutionError, "Unsupported callable: #{callable.class}"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def resolve_composition(node)
|
|
73
|
+
child_inputs = node.input_mapping.each_with_object({}) do |(child_input_name, dependency_name), memo|
|
|
74
|
+
dependency_state = resolve(dependency_name)
|
|
75
|
+
raise dependency_state.error if dependency_state.failed?
|
|
76
|
+
|
|
77
|
+
memo[child_input_name] = dependency_state.value
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
child_contract = node.contract_class.new(child_inputs)
|
|
81
|
+
child_contract.resolve_all
|
|
82
|
+
child_error = child_contract.result.errors.values.first
|
|
83
|
+
raise child_error if child_error
|
|
84
|
+
|
|
85
|
+
NodeState.new(node: node, status: :succeeded, value: child_contract.result)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def success_payload(node, state)
|
|
89
|
+
return {} unless node.kind == :composition
|
|
90
|
+
return {} unless state.value.is_a?(Igniter::Runtime::Result)
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
child_execution_id: state.value.execution.events.execution_id,
|
|
94
|
+
child_graph: state.value.execution.compiled_graph.name
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def normalize_error(error, node)
|
|
99
|
+
return error if error.is_a?(Igniter::Error)
|
|
100
|
+
|
|
101
|
+
ResolutionError.new(
|
|
102
|
+
error.message,
|
|
103
|
+
context: {
|
|
104
|
+
graph: @execution.compiled_graph.name,
|
|
105
|
+
node_id: node.id,
|
|
106
|
+
node_name: node.name,
|
|
107
|
+
node_path: node.path,
|
|
108
|
+
source_location: node.source_location
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Igniter
|
|
4
|
+
module Runtime
|
|
5
|
+
class Result
|
|
6
|
+
attr_reader :execution
|
|
7
|
+
|
|
8
|
+
def initialize(execution)
|
|
9
|
+
@execution = execution
|
|
10
|
+
define_output_readers!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_h
|
|
14
|
+
@execution.compiled_graph.outputs.each_with_object({}) do |output_node, memo|
|
|
15
|
+
memo[output_node.name] = serialize_output_value(public_send(output_node.name))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def success?
|
|
20
|
+
@execution.resolve_all
|
|
21
|
+
!failed?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def failed?
|
|
25
|
+
@execution.resolve_all
|
|
26
|
+
@execution.cache.values.any?(&:failed?)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def errors
|
|
30
|
+
@execution.resolve_all
|
|
31
|
+
@execution.cache.values.each_with_object({}) do |state, memo|
|
|
32
|
+
next unless state.failed?
|
|
33
|
+
|
|
34
|
+
memo[state.node.name] = state.error
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def states
|
|
39
|
+
@execution.resolve_all
|
|
40
|
+
@execution.states
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def explain(output_name)
|
|
44
|
+
@execution.resolve_output(output_name)
|
|
45
|
+
@execution.explain_output(output_name)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def as_json(*)
|
|
49
|
+
@execution.resolve_all
|
|
50
|
+
|
|
51
|
+
{
|
|
52
|
+
graph: @execution.compiled_graph.name,
|
|
53
|
+
execution_id: @execution.events.execution_id,
|
|
54
|
+
outputs: to_h,
|
|
55
|
+
success: !failed?,
|
|
56
|
+
failed: failed?,
|
|
57
|
+
errors: serialize_errors(errors),
|
|
58
|
+
states: states
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def define_output_readers!
|
|
65
|
+
@execution.compiled_graph.outputs.each do |output_node|
|
|
66
|
+
define_singleton_method(output_node.name) do
|
|
67
|
+
@execution.resolve_output(output_node.name)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def serialize_value(value)
|
|
73
|
+
case value
|
|
74
|
+
when Result
|
|
75
|
+
value.as_json
|
|
76
|
+
when Array
|
|
77
|
+
value.map { |item| serialize_value(item) }
|
|
78
|
+
else
|
|
79
|
+
value
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def serialize_output_value(value)
|
|
84
|
+
case value
|
|
85
|
+
when Result
|
|
86
|
+
value.to_h
|
|
87
|
+
when Array
|
|
88
|
+
value.map { |item| serialize_output_value(item) }
|
|
89
|
+
else
|
|
90
|
+
value
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def serialize_errors(error_hash)
|
|
95
|
+
error_hash.each_with_object({}) do |(node_name, error), memo|
|
|
96
|
+
memo[node_name] = {
|
|
97
|
+
type: error.class.name,
|
|
98
|
+
message: error.message,
|
|
99
|
+
context: error.respond_to?(:context) ? error.context : {}
|
|
100
|
+
}
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "runtime/node_state"
|
|
4
|
+
require_relative "runtime/cache"
|
|
5
|
+
require_relative "runtime/input_validator"
|
|
6
|
+
require_relative "runtime/resolver"
|
|
7
|
+
require_relative "runtime/invalidator"
|
|
8
|
+
require_relative "runtime/result"
|
|
9
|
+
require_relative "runtime/execution"
|
|
10
|
+
|
|
11
|
+
module Igniter
|
|
12
|
+
module Runtime
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/igniter.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "igniter/version"
|
|
4
|
+
require_relative "igniter/errors"
|
|
5
|
+
require_relative "igniter/model"
|
|
6
|
+
require_relative "igniter/compiler"
|
|
7
|
+
require_relative "igniter/events"
|
|
8
|
+
require_relative "igniter/runtime"
|
|
9
|
+
require_relative "igniter/dsl"
|
|
10
|
+
require_relative "igniter/extensions"
|
|
11
|
+
require_relative "igniter/diagnostics"
|
|
12
|
+
require_relative "igniter/contract"
|
|
13
|
+
|
|
14
|
+
module Igniter
|
|
15
|
+
class << self
|
|
16
|
+
def compile(&block)
|
|
17
|
+
DSL::ContractBuilder.compile(&block)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/sig/igniter.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: igniter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Alexander
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rake
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '13.0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '13.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rspec
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '3.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '3.0'
|
|
40
|
+
description: Igniter provides a contract DSL, graph compiler, runtime execution engine,
|
|
41
|
+
auditing, reactivity, and introspection for business logic expressed as dependency
|
|
42
|
+
graphs.
|
|
43
|
+
email:
|
|
44
|
+
- alexander.s.fokin@gmail.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- CHANGELOG.md
|
|
50
|
+
- LICENSE.txt
|
|
51
|
+
- README.md
|
|
52
|
+
- docs/API_V2.md
|
|
53
|
+
- docs/ARCHITECTURE_V2.md
|
|
54
|
+
- docs/EXECUTION_MODEL_V2.md
|
|
55
|
+
- docs/IGNITER_CONCEPTS.md
|
|
56
|
+
- examples/README.md
|
|
57
|
+
- examples/basic_pricing.rb
|
|
58
|
+
- examples/composition.rb
|
|
59
|
+
- examples/diagnostics.rb
|
|
60
|
+
- lib/igniter.rb
|
|
61
|
+
- lib/igniter/compiler.rb
|
|
62
|
+
- lib/igniter/compiler/compiled_graph.rb
|
|
63
|
+
- lib/igniter/compiler/graph_compiler.rb
|
|
64
|
+
- lib/igniter/compiler/validator.rb
|
|
65
|
+
- lib/igniter/contract.rb
|
|
66
|
+
- lib/igniter/diagnostics.rb
|
|
67
|
+
- lib/igniter/diagnostics/report.rb
|
|
68
|
+
- lib/igniter/dsl.rb
|
|
69
|
+
- lib/igniter/dsl/contract_builder.rb
|
|
70
|
+
- lib/igniter/errors.rb
|
|
71
|
+
- lib/igniter/events.rb
|
|
72
|
+
- lib/igniter/events/bus.rb
|
|
73
|
+
- lib/igniter/events/event.rb
|
|
74
|
+
- lib/igniter/extensions.rb
|
|
75
|
+
- lib/igniter/extensions/auditing.rb
|
|
76
|
+
- lib/igniter/extensions/auditing/timeline.rb
|
|
77
|
+
- lib/igniter/extensions/introspection.rb
|
|
78
|
+
- lib/igniter/extensions/introspection/graph_formatter.rb
|
|
79
|
+
- lib/igniter/extensions/introspection/runtime_formatter.rb
|
|
80
|
+
- lib/igniter/extensions/reactive.rb
|
|
81
|
+
- lib/igniter/extensions/reactive/engine.rb
|
|
82
|
+
- lib/igniter/extensions/reactive/matcher.rb
|
|
83
|
+
- lib/igniter/extensions/reactive/reaction.rb
|
|
84
|
+
- lib/igniter/model.rb
|
|
85
|
+
- lib/igniter/model/composition_node.rb
|
|
86
|
+
- lib/igniter/model/compute_node.rb
|
|
87
|
+
- lib/igniter/model/graph.rb
|
|
88
|
+
- lib/igniter/model/input_node.rb
|
|
89
|
+
- lib/igniter/model/node.rb
|
|
90
|
+
- lib/igniter/model/output_node.rb
|
|
91
|
+
- lib/igniter/runtime.rb
|
|
92
|
+
- lib/igniter/runtime/cache.rb
|
|
93
|
+
- lib/igniter/runtime/execution.rb
|
|
94
|
+
- lib/igniter/runtime/input_validator.rb
|
|
95
|
+
- lib/igniter/runtime/invalidator.rb
|
|
96
|
+
- lib/igniter/runtime/node_state.rb
|
|
97
|
+
- lib/igniter/runtime/resolver.rb
|
|
98
|
+
- lib/igniter/runtime/result.rb
|
|
99
|
+
- lib/igniter/version.rb
|
|
100
|
+
- sig/igniter.rbs
|
|
101
|
+
homepage: https://github.com/alexander-s-f/igniter
|
|
102
|
+
licenses:
|
|
103
|
+
- MIT
|
|
104
|
+
metadata:
|
|
105
|
+
rubygems_mfa_required: 'true'
|
|
106
|
+
homepage_uri: https://github.com/alexander-s-f/igniter
|
|
107
|
+
source_code_uri: https://github.com/alexander-s-f/igniter
|
|
108
|
+
changelog_uri: https://github.com/alexander-s-f/igniter/blob/main/CHANGELOG.md
|
|
109
|
+
rdoc_options: []
|
|
110
|
+
require_paths:
|
|
111
|
+
- lib
|
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 3.1.0
|
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - ">="
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '0'
|
|
122
|
+
requirements: []
|
|
123
|
+
rubygems_version: 3.6.9
|
|
124
|
+
specification_version: 4
|
|
125
|
+
summary: Declarative dependency-graph runtime for business logic
|
|
126
|
+
test_files: []
|