-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implements skip stage #2
Conversation
opus_opus_graph.dot
Outdated
@@ -0,0 +1,68 @@ | |||
digraph G { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this meant to be committed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I didn't know if it was meant to be commited since it was auto generated. I'll remove it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed!
defmodule Opus.Pipeline.Stage.SkipTest do | ||
use ExUnit.Case | ||
|
||
describe "when the stage returns false and there's no next stage" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add an example about what happens if there are multiple skips.
defmodule SomePipeline do
skip if: :skip?
skip if: :please_skip?
skip if: :should_it_skip_maybe?
step :some_step
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! I'll add it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added three more cases about multi skips, take a look
6fe99f3
to
7e3b93a
Compare
lib/opus/pipeline/stage/skip.ex
Outdated
|
||
def run({module, type, [if: func], opts} = stage, input) do | ||
case Stage.maybe_run({module, type, nil, opts |> put_in([:if], func)}, input) do | ||
ret when ret == :stage_skipped -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def run({module, type, [if: func], opts}, input) do
case Stage.maybe_run({module, type, nil, opts |> put_in([:if], func)}, input) do
:stage_skipped -> {:halt, :skipped}
_ -> {:cont, input}
end
end
- The guard is not needed here
- When the conditional returns false (and we don't skip) you can return
{:cont, input}
so that the pipeline continues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally, thanks for noticing! Just changed!
lib/opus/pipeline/stage.ex
Outdated
def maybe_run({module, :skip, name, %{if: {_m, _f, _a} = condition}}, input) do | ||
case Safe.apply(condition) do | ||
true -> | ||
skip_stage({module, name}, input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is tricky because in this case the whole pipeline is skipped, not just a single stage. I think we should use a different instrumentation event, something like pipeline_skipped
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ouch, really well noticed! Thanks again! Changed it, hope it's better now
7e3b93a
to
5dbde21
Compare
defmodule SingleSkipFalsePipeline do | ||
use Opus.Pipeline | ||
|
||
skip(if: :should_skip?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please mind to update the .formatter.exs file.
https://github.com/Zorbash/opus/blob/master/.formatter.exs#L11
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ups, changing!
defmodule SkipFalsePipeline do | ||
use Opus.Pipeline | ||
|
||
skip(if: :should_skip?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the user tries the following?
defmodule SomeMod do
skip # without an :if option
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(CompileError) test/opus/pipeline/stage/skip_test.exs:127: undefined function skip/0
Make sense, wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And, when a param other then "if" is given: eg: skip another: :value
(FunctionClauseError) no function clause matching in Opus.Pipeline.Stage.Skip.run/2
README.md
Outdated
|
||
This stage receives a `:if` option only, on which is expected to return a | ||
boolean value. If `true`, then the pipeline halts and Opus returns | ||
`{:ok, :skipped}`. If `false`, then the next stage is called with no side effect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the code I can see that if true
we skip, otherwise (with any other value) we don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I just change the docs to something like If anything else, then the next stage is called with no side effect.
or do you think that if no boolean
is returned, then Opus should raise an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just changed the description to: "If false
or any other value is returned (including non-boolean), then the next stage is called with no side effect."
Also implemented a new spec for this case.
Let me know if that makes sense!
@@ -24,6 +24,22 @@ defmodule Opus.Pipeline.Stage do | |||
when is_atom(fun), | |||
do: maybe_run({module, type, name, %{opts | if: {module, fun, [input]}}}, input) | |||
|
|||
def maybe_run({module, :skip, name, %{if: {_m, _f, _a} = condition}}, input) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some implied behaviour here I think. When _f
is nil which means that no :if
option is provided then we don't skip the pipeline, right? In that case it might be worth it raising a compile-time error since the skip definition will essentially be invalid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just mentioned about it above, but just to be clear, those are some tests I've tried:
- No param
defmodule SkipNoParamPipeline do
use Opus.Pipeline
skip
end
(CompileError) test/opus/pipeline/stage/skip_test.exs:127: undefined function skip/0
- Non-keyword param
defmodule SkipAnotherParamPipeline do
use Opus.Pipeline
skip :another
end
** (FunctionClauseError) no function clause matching in Opus.Pipeline.Stage.Skip.run/2
The following arguments were given to Opus.Pipeline.Stage.Skip.run/2:
# 1
{Opus.Pipeline.Stage.SkipTest.SkipAnotherParamPipeline, :skip, :another, %{stage_id: 24357}}
- Keyword param without
if
defmodule SkipAnotherValuePipeline do
use Opus.Pipeline
skip another: :value
end
** (FunctionClauseError) no function clause matching in Opus.Pipeline.Stage.Skip.run/2
The following arguments were given to Opus.Pipeline.Stage.Skip.run/2:
# 1
{Opus.Pipeline.Stage.SkipTest.SkipAnotherValuePipeline, :skip, [another: :value], %{stage_id: 24772}}
- Another keyword param and
if
defmodule SkipAnotherValueAndIfPipeline do
use Opus.Pipeline
skip if: :cond, another: :value
end
** (FunctionClauseError) no function clause matching in Opus.Pipeline.Stage.Skip.run/2
The following arguments were given to Opus.Pipeline.Stage.Skip.run/2:
# 1
{Opus.Pipeline.Stage.SkipTest.SkipAnotherValueAndIfPipeline, :skip, [if: :cond, another: :value], %{stage_id: 28804}}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But, feel free to recommend any refactoring or implementation about this situation!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To conclude this discussion, I think it's fine to merge it as is. Then I'll make an attempt to make the error message a bit more user-friendly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To conclude this discussion, I think it's fine to merge it as is. Then I'll make an attempt to make the error message a bit more user-friendly.
ab407e1
to
f2d4d97
Compare
Btw, sorry for the delay =/ |
README.md
Outdated
@@ -42,6 +42,7 @@ end | |||
defmodule ArithmeticPipeline do | |||
use Opus.Pipeline | |||
|
|||
skip if: greater_than_fifty? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
greater_than_fifty?
should be an Atom.
README.md
Outdated
@@ -112,6 +114,13 @@ This stage is to link with another Opus.Pipeline module. It calls | |||
`call/1` for the provided module. If the module is not an | |||
`Opus.Pipeline` it is ignored. | |||
|
|||
### Skip | |||
|
|||
This stage receives a `:if` option only, on which is expected to return a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rephrase to This stage expects
or This stage accepts
.
@rafaels88 Please make changes for and it's good to merge :-) |
The `:skip` stage makes the Pipeline halts when the given conditional returns `true`.
f2d4d97
to
6122547
Compare
@zorbash Changed! Thanks for the review! |
@rafaels88 Thanks for contributing, I'll update the changelog and releases it as |
It introduces a new stage
skip
and solve the issue #1 .Usage example: