- Fix a bug in Ruby 3.2:
NoMethodError: undefined method
[]' for nil`. Thanks @tiagotex for finding the problem and solution. This bug only occurs when compacting the memory using GC, which is only introduced with Ruby 3.2.
- Allow passing custom
:flow_options
toTesting#assert_invoke
.
- Allow overriding
Activity.call
.
- Remove
Activity#[]
. Please useactivity.to_h[:config]
. - Change
Activity#to_h[:nodes]
. This is now aSchema::Nodes
"hash" that is keyed by task that points toNodes::Attributes
data structures (a replacement forActivity::NodeAttributes
). This decision reduces logic and improves performance: it turned out that most of the time an introspect lookup queries for a task, not ID. - Introduce
Activity::Introspect.Nodes()
as a consistent and fast interface for introspection and removeActivity::Introspect::TaskMap
. - Remove
Activity::NodeAttributes
. - Move
Introspect::Graph
totrailblazer-developer
. It's a data structure very specific to rendering, which is not a part of pure runtime behavior.Activity::Introspect.Graph()
is now deprecated. TaskWrap.container_activity_for
now accepts:id
for setting an ID for the containered activity to anything other thannil
.- Re-add
:nodes
to the container activity hash as this provides a consistent way for treating allActivity
s. - Remove
Activity::Config
. This immutable hash interface was used in one place, only, and can easily be replaced withconfig.merge()
. - Add
Introspect::Render
. Please consider this private.
-
Remove
Intermediate.call
, this is now done throughIntermediate::Compiler
. -
Introduce
Intermediate::Compiler
which is simplified and is 10% faster. -
A terminus ("end event") in
Schema::Intermediate
no longer has outputs but an empty array. Thestop_event: true
option is still required to mark theTaskRef
as a terminus. -
Schema::Intermediate
now keeps a map{<terminus ID> => :semantic}
instead of the flat termini ID list and one default start event instead of an array. This looks as follows.Schema::Intermediate.new( { # ... Intermediate::TaskRef("End.success", stop_event: true) => [Inter::Out(:success, nil)] }, ["End.success"], [:a] # start
Now becomes
Schema::Intermediate.new( { # ... Intermediate::TaskRef("End.success", stop_event: true) => [] }, {"End.success" => :success}, :a # start
-
In line with the change in
Intermediate
, theImplemention
terminiTask
s now don't have outputs anymore.implementation = { # ... "End.success" => Schema::Implementation::Task(Activity::End.new(semantic: :success), [], []) # No need for outputs here. }
- Introduce
Extension.WrapStatic()
as a consistent interface for creating wrap_static extensions exposing the friendly interface. - Deprecate
Extension(merge: ...)
since we haveExtension.WrapStatic
now. - Better deprecation warnings for extensions using
Insert
and not the friendly interface.
- Rename
Circuit::Run
toCircuit::Runner
for consistency withTaskWrap::Runner
. - Add
:flat_activity
keyword argument toTesting.nested_activity
, so you can inject any activity for:D
. Also, allow to change:D
's ID with the:d_id
option. - Introduce
Deprecate.warn
to have consistent deprecation warnings across all gems. - Introduce
Activity.call
as a top-level entry point and abstraction forTaskWrap.invoke
.
-
Remove the
:wrap_static
keyword argument forTaskWrap.invoke
and replace it with:container_activity
. -
Make
TaskWrap.initial_wrap_static
returnINITIAL_TASK_WRAP
instead of recompiling it for every#invoke
. -
Introduce
TaskWrap.container_activity_for
to build "host activities" that are used to provide a wrap_static to the actually run activity. This is also used in theEach()
macro and other places. -
Allow
append: nil
for friendly interface.TaskWrap.Extension([method(:add_1), id: "user.add_1", append: nil])`.
This appends the step to the end of the pipeline.
- Add
Introspect.find_path
to retrieve aGraph::Node
and its hosting activity from a deeply nested graph. Note that this method is still considered private. - Add
Introspect::TaskMap
as a slim interface for introspectingActivity
instances. Note thatGraph
might get moved todeveloper
as it is very specific to rendering circuits.
- Rename
Activity::TaskBuilder.Binary()
toActivity::Circuit::TaskAdapter.for_step()
. It returns aTaskAdapter
instance, which is a bit more descriptive than aTask
instance. - Add
Circuit.Step(callable_with_step_interface)
which accepts a step-interface callable and, when called, returns its result and thectx
. This is great for deciders in macros where you don't want the step's result on thectx
. - Add
TaskWrap::Pipeline::TaskBuilder
.
- Remove
Pipeline.insert_before
and friends. Pipeline is now altered using ADDS mechanics, just as we do it with theSequence
in thetrailblazer-activity-dsl-linear
gem. Pipeline::Merge
is nowTaskWrap::Extension
. The "pre-friendly interface" you used to leverage for creating taskWrap (tw) extensions is now deprecated and you will see warnings. See https://trailblazer.to/2.1/docs/activity.html#activity-taskwrap-extension- Replace
TaskWrap::Extension()
withTaskWrap::Extension.WrapStatic()
as a consistent interface for creating tW extensions at compile-time. - Remove
Insert.find
. - Rename
Activity::State::Config
toActivity::Config
. - Move
VariableMapping
to thetrailblazer-activity-dsl-linear
gem. - Move
Pipeline.prepend
to thetrailblazer-activity-linear-dsl
gem. - Add
Testing#assert_call
as a consistent test implementation. (0.14.0.beta2)
- Removed
TaskWrap::Inject::Defaults
. This is now implemented throughdsl
's:inject
option. - Removed
TaskWrap::VariableMapping.Extension
. - Renamed private
TaskWrap::VariableMapping.merge_for
to.merge_instructions_for
as there's no {Merge} instance, yet. - Extract invocation logic in
TaskBuilder::Task
intoTask#call_option
. - Add
TaskWrap::Pipeline::prepend
.
- Use extracted
trailblazer-option
.
- Allow injecting
:wrap_static
intoTaskWrap.invoke
.
- Support for Ruby 3.0.
- Bug fix:
:output
filter fromTaskWrap::VariableMapping
wasn't returning the correctflow_options
. If the wrapped task changed itsflow_options
, the original one was still returned from the taskWrap run, not the updated one.
- Introduce the
config_wrap:
option inIntermediate.call(intermediate, implementation, config_merge: {})
to allow injecting data into the activity's:config
field.
- Allow
Testing.def_task
&Testing.def_tasks
to return custom signals
- Upgrading
trailblazer-context
version 🥁
- Internal warning fixes.
- Support for Ruby 2.7. Most warnings are gone.
- Update IllegalSignalError exception for more clarity
- Require
developer
>= 0.0.7. - Move
Activity::Introspect
back to this very gem. - This is hopefully the last release before 2.1.0.
- Move some test helpers to
Activity::Testing
to export them to other gems - Remove introspection modules, it'll also be part of the
Dev
tools now. - Remove tracing modules, it'll be part of the
Dev
tools now.
Unreleased.
Unreleased.
- Use
context-0.9.1
.
- Change API of
Input
/Output
filters. Instead of calling them withoriginal_ctx, circuit_options
they're now called with the complete (original!) circuit interface. This simplifies calling and provides all circuit arguments to the filter which can then filter-out what is not needed.:input
is now called with((original_ctx, flow_options), circuit_options)
:output
is now called with(new_ctx, (original_ctx, flow_options), circuit_options)
- Update
Present
to renderDeveloper.wtf?
for given activity fearlessly
- Use
Context.for
to create contexts.
- Fix
Present
so it works with Ruby <= 2.3.
- Remove
hirb
gem dependency.
- Separate the DSL from the runtime code. The latter sits in this gem.
- Separate the runtime {Activity} from its compilation, which happens through {Intermediate} (the structure) and {Implementation} (the runtime implementation) now.
- Introduce {Pipeline} which is a simpler and much fast type of activity, mostly for the taskWrap.
- When recording DSL calls, use the
object_id
as key, so cloned methods are considered as different recordings.
- Alias
Trace.call
toTrace.invoke
for consistency. - Allow injecting your own stack into
Trace.invoke
. This enables us to provide tracing even when there's an exception (due to, well, mutability). - Minor changes in
Trace::Present
so that "unfinished" stacks can also be rendered. Trace::Present.tree
is now private and superseded byPresent.call
.
- Remove
DSL::Helper
, "helper" methods now sit directly in theDSL
namespace.
- Allow all
Option
types for input/output.
- Make
:input
and:output
standard options of the DSL to create variable mappings.
- The
:task
option inCircuit::call
is now named:start_task
for consistency. - Removed the
:argumenter
option forActivity::call
. Instead, anActivity
passes itself via the:activity
option. - Removed the
:extension
option. Instead, any option from the DSL thatis_a?(DSL::Extension)
will be processed inadd_task!
. - Replace argumenters with
TaskWrap::invoke
. This simplifies the wholecall
process, and moves all initialization of args to the top. - Added
Introspect::Graph::find
. - Removed
Introspect::Enumerator
in favor of theGraph
API.
- Introducing
Introspect::Enumerator
and removingIntrospect.find
.Enumerator
containsEnumerable
and exposes all necessary utility methods.
-
In Path(), allow referencing an existing task, instead of creating an end event. This avoids having to use two
Output() => ..
and is much cleaner.Path( end_id: :find_model) do .. end
- In
Path()
, we removed the#path
method in favor of a cleanertask
DSL method. We now use the default plus_polessuccess
andfailure
everywhere for consistency. This means that atask
has two outputs, and if you referencedOutput(:success)
, that would be only one of them. We're planning to havepass
back which has onesuccess
plus_pole, only. This change makes the DSL wiring behavior much more consistent. - Changed
TaskBuilder::Builder.()
to a functionTaskBuilder::Builder()
.
- Include all end events without outgoing connections into
Activity.outputs
. In earlier versions, we were filtering out end events without incoming connections, which reduces the number of outputs, but might not represent the desired interface of an activity. - Add
_end
toRailway
andFastTrack
. - Move
Builder::FastTrack::PassFast
and:::FailFast
toActivity::FastTrack
since those are signals and unrelated to builders.
- Rename
Nested()
toSubprocess
and move the original one to theoperation
gem. - Add merging:
Activity.merge!
now allows to compose an activity by merging another. - Enforce using
Output(..) => Track(:success)
instead of just the track color:success
. This allow having IDs both symbols and strings.
- Make
:outputs
the canonical way to define outputs, and not:plus_poles
. The latter is computed by the DSL if not passed. - Allow injecting
inspect
implementations intoIntrospect
methods. - Add
Nested
. - Add
TaskBuilder::Task#to_s
.
End
is not aStruct
so we can maintain more state, and are immutable.
- Remove
decompose
and replace it with a betterto_h
. End
doesn't have a redundant@name
anymore but only a semantic.
- We now use the "Module Subclass" pattern, and activities aren't classes anymore but modules.
- In the
TaskWrap
, rename:result_direction
to:return_signal
and:result_args
to:return_args
,
- Allow passing a
:normalizer
to the DSL. - Builders don't have to provide
keywords
as we can filter them automatically.
- Remove
Activity#end_events
.
- Restructure all
Wrap
-specific tasks. - Remove
Hash::Immutable
, we will use thehamster
gem instead.
-
The
Activity#call
API is nowsignal, options, _ignored_circuit_options = Activity.( options, **circuit_options )
The third return value, which is typically the
circuit_options
, is ignored and for all task calls in thisActivity
, an identical, unchangeable set ofcircuit_options
is passed to. This dramatically reduces unintended behavior with the task_wrap, tracing, etc. and usually simplifies tasks.The new API allows using bare
Activity
instances as tasks without any clumsy nesting work, making nesting very simple.A typical task will look as follows.
->( (options, flow_options), **circuit_args ) do [ signal, [options, flow_options], *this_will_be_ignored ] end
A task can only emit a signal and "options" (whatever data structure that may be), and can not change the
circuit_options
which usually contain activity-wide "global" configuration.
Nested
now isSubprocess
because it literally does nothing else but calling a process (or activity).
Nested
now uses kw args forstart_at
and the newcall
option. The latter allows to set the called method on the nested activity, e.g.__call
.
- Introduce
Activity#outputs
and ditch#end_events
.
- Consistent return values for all graph operations:
node, edge
. Edge
now always gets an id.#connect_for!
always throws away the old edge, fixing a bug where graph and circuit would look different.- Internal simplifications for
Graph
alteration methods.
- Fix loading order.
- In
Activity::Before
, allow specifying what predecessing tasks to connect to the new_task via the:predecessors
option, and without knowing the direction. This will be the new preferred style inTrailblazer:::Sequence
where we can always assume directions are limited toRight
andLeft
(e.g., with nested activities, this changes to a colorful selection of directions).
- Temporarily allow injecting a
to_hash
transformer into aContainerChain
. This allows to ignore certain container types such asDry::Container
in the KW transformation. Note that this is a temp fix and will be replaced with proper pattern matching.
- Introduce
Context::ContainerChain
to eventually replace the heavy-weightSkill
object. - Fix a bug in
Option
where wrong args were passed when used withoutflow_options
.
- Fix
Context#[]
, it returnednil
when it should returnfalse
.
- Make
Trailblazer::Option
andTrailblazer::Option::KW
a mix of lambda and object so it's easily extendable.
- It is now
Trailblazer::Args
.
Wrapped
is nowWrap
. Also, a consistentAlterations
interface allows tweaking here.
- The
Wrapped::Runner
now appliesAlterations
to each task'sCircuit
. This means you can inject:task_alterations
intoCircuit#call
, which will then be merged into the task's original circuit, and then run. While this might sound like crazy talk, this allows any kind of external injection (tracing, input/output contracts, step dependency injections, ...) for specific or all tasks of any circuit.
- Simpler tracing with
Stack
. - Added
Context
. - Simplified
Circuit#call
.
- Make the first argument to
#Activity
(@name
) always a Hash where:id
is a reserved key for the name of the circuit.
- Make
flow_options
an immutable data structure just asoptions
. It now needs to be returned from a#call
.
- First release into an unsuspecting world. 🚀