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
- Data is assigned to:
-
Setter method (when
as:omitted):- Calls:
to_pipeline.input.source = from_pipeline.output - Used by operations with explicit source setters
- Default
onis:sourcewhenasis omitted
- Calls:
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
The per-method examples further down are written against that first
composer: a single reverse step from input to output.
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.
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/musa-dsl/series/series-composer.rb', line 319 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
337 338 339 340 |
# File 'lib/musa-dsl/series/series-composer.rb', line 337 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
587 588 589 590 591 592 593 594 595 |
# File 'lib/musa-dsl/series/series-composer.rb', line 587 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.
386 387 388 389 |
# File 'lib/musa-dsl/series/series-composer.rb', line 386 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.
426 427 428 429 430 431 |
# File 'lib/musa-dsl/series/series-composer.rb', line 426 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.
530 531 532 |
# File 'lib/musa-dsl/series/series-composer.rb', line 530 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
498 499 500 |
# File 'lib/musa-dsl/series/series-composer.rb', line 498 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.
556 557 558 |
# File 'lib/musa-dsl/series/series-composer.rb', line 556 def update(&block) @dsl.with &block end |