Class: Musa::Series::Composer::Composer
- Defined in:
- lib/musa-dsl/series/series-composer.rb
Overview
Multi-input/output serie transformation pipeline system.
Composer enables building complex transformation graphs with multiple named inputs, outputs, and intermediate processing stages. It provides a declarative DSL for defining pipelines and routing data between them, similar to modular synthesis patch routing.
Architecture
The Composer system consists of:
- Pipelines: Named transformation stages that process series
- Routes: Connections between pipelines specifying data flow
- Inputs: Named entry points (automatically proxied and buffered)
- Outputs: Named exit points for consuming results
- DSL Context: method_missing-based interface for pipeline definition
Pipeline Definition
Pipelines are defined using method calls in the DSL block. Each pipeline consists of:
- Constructor (optional): Series constructor like
S,H, etc. - Operations (one or more): Transformations like
reverse,skip, etc.
Routing System
Routes connect pipelines using the route method:
route from_pipeline, to: to_pipeline, on: :source, as: :key
Routing modes:
- Hash assignment (when
as:provided):
- Data is assigned to:
to_pipeline.input[on][as] = from_pipeline.output - Used by operations accepting hash inputs (e.g.,
Hconstructor) - Default
onis:sourceswhenasis provided
- Setter method (when
as:omitted):
- Calls:
to_pipeline.input.source = from_pipeline.output - Used by operations with explicit source setters
- Default
onis:sourcewhenasis omitted
Commit System
Composer uses two-phase initialization:
- Definition phase: Routes and pipelines are declared
- Commit phase: All connections are resolved and finalized
Key behaviors:
- Routes can be defined in any order (order-independent)
- Output access is blocked until
commit!is called - Commit resolves all routes and sets up buffering
auto_commit: true(default) commits automatically after DSL block
DSL Context
The DSL uses method_missing to enable natural pipeline definition:
- Named access:
input,output, pipeline names return symbols - Pipeline creation:
name arg1, arg2, ...creates pipeline - Operation symbols: Series operations return as symbols for parsing
- Constructor symbols: Series constructors return as symbols for parsing
Class Method Summary collapse
Instance Method Summary collapse
-
#commit! ⇒ void
Finalizes composer by resolving all routes and connections.
-
#initialize(input: nil, inputs: [:input], outputs: [:output], auto_commit: nil, &block) ⇒ Composer
constructor
A new instance of Composer.
-
#input(name = nil) ⇒ ProxySerie
Accesses named input proxy for dynamic source assignment.
-
#output(name = nil) ⇒ Serie
Accesses named output series for consumption.
-
#pipeline(name, *elements) ⇒ void
Defines named pipeline with transformation operations.
-
#route(from, to:, on: nil, as: nil) ⇒ void
Defines routing connection between pipelines.
-
#update { ... } ⇒ void
Updates composer with additional DSL block.
Constructor Details
#initialize(input: nil, inputs: [:input], outputs: [:output], auto_commit: nil, &block) ⇒ Composer
Returns a new instance of Composer.
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/musa-dsl/series/series-composer.rb', line 288 def initialize(input: nil, inputs: [:input], outputs: [:output], auto_commit: nil, &block) auto_commit = true if auto_commit.nil? inputs = case inputs when Array inputs.collect { |_| [_, nil] }.to_h when nil {} when Hash inputs else raise ArgumentError, "inputs: expected a Hash with input names and source series { name: serie, ... } or an Array with names [name, ...] but received #{inputs}" end inputs[:input] = input if input @pipelines = {} def @pipelines.[]=(name, pipeline) pipeline_to_add = @commited ? pipeline.commit! : pipeline super(name, pipeline_to_add) end @dsl = DSLContext.new(@pipelines) @inputs = {} @outputs = {} inputs.keys&.each do |input| p = Musa::Series::Constructors.PROXY(inputs[input]) @inputs[input] = @pipelines[input] = Pipeline.new(input, input: p, output: p.buffered, pipelines: @pipelines) @dsl.define_singleton_method(input) { input } end outputs&.each do |output| p = Musa::Series::Constructors.PROXY() @outputs[output] = @pipelines[output] = Pipeline.new(output, is_output: true, input: p, output: p, pipelines: @pipelines) @dsl.define_singleton_method(output) { output } end @dsl.with &block if block commit! if auto_commit end |
Class Method Details
.[]=(name, pipeline) ⇒ Object
306 307 308 309 |
# File 'lib/musa-dsl/series/series-composer.rb', line 306 def @pipelines.[]=(name, pipeline) pipeline_to_add = @commited ? pipeline.commit! : pipeline super(name, pipeline_to_add) end |
Instance Method Details
#commit! ⇒ void
This method returns an undefined value.
Finalizes composer by resolving all routes and connections.
Commits the composer, resolving all route connections and setting up buffering. Must be called before accessing outputs. Cannot be called twice on same composer instance.
The commit process:
- Recursively commits all output pipelines
- Each pipeline commits its input routes
- Connects all sources through buffers
- Sets committed flag enabling output access
533 534 535 536 537 538 539 540 541 |
# File 'lib/musa-dsl/series/series-composer.rb', line 533 def commit! raise 'Already commited' if @commited @outputs.each_value do |pipeline| pipeline.commit! end @commited = true end |
#input(name = nil) ⇒ ProxySerie
Accesses named input proxy for dynamic source assignment.
Returns the proxy series for the specified input, allowing dynamic
assignment of source series after composer creation. Used with
auto_commit: false to set sources before manual commit.
355 356 357 358 |
# File 'lib/musa-dsl/series/series-composer.rb', line 355 def input(name = nil) name ||= :input @inputs[name].input end |
#output(name = nil) ⇒ Serie
Accesses named output series for consumption.
Returns the output series for the specified output. Can only be
called after commit! has been invoked. Raises error if composer
is not committed.
380 381 382 383 384 385 |
# File 'lib/musa-dsl/series/series-composer.rb', line 380 def output(name = nil) raise "Can't access output if the Composer is uncommited. Call '.commit' first." unless @commited name ||= :output @outputs[name].output end |
#pipeline(name, *elements) ⇒ void
This method returns an undefined value.
Defines named pipeline with transformation operations.
Creates a pipeline from constructor and/or operations. This method is typically called implicitly through the DSL's method_missing, but can be called directly for dynamic pipeline creation.
484 485 486 |
# File 'lib/musa-dsl/series/series-composer.rb', line 484 def pipeline(name, *elements) @dsl.pipeline(name, elements) end |
#route(from, to:, on: nil, as: nil) ⇒ void
This method returns an undefined value.
Defines routing connection between pipelines.
Creates data flow route from source pipeline to destination pipeline.
The routing behavior depends on whether as: parameter is provided.
With as: parameter (Hash routing):
- Assigns to hash:
to_pipeline.input[on][as] = from_pipeline.output - Default
onis:sources - Used by operations accepting hash inputs (e.g.,
Hconstructor)
Without as: parameter (Setter routing):
- Calls setter:
to_pipeline.input.source = from_pipeline.output - Default
onis:source - Used by operations with explicit source setter methods
452 453 454 |
# File 'lib/musa-dsl/series/series-composer.rb', line 452 def route(from, to:, on: nil, as: nil) @dsl.route(from, to: to, on: on, as: as) end |
#update { ... } ⇒ void
This method returns an undefined value.
Updates composer with additional DSL block.
Allows dynamic modification of composer after creation by executing additional DSL block in the composer's DSL context. Useful for progressive pipeline construction.
504 505 506 |
# File 'lib/musa-dsl/series/series-composer.rb', line 504 def update(&block) @dsl.with &block end |