-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The `:skip` stage makes the Pipeline halts when the given conditional returns `true`.
- Loading branch information
Showing
8 changed files
with
226 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
defmodule Opus.Pipeline.Stage.Skip do | ||
@moduledoc ~S""" | ||
The skip stage is meant to halt the pipeline with no error if the given condition is true. | ||
This stage must be called with an `if` option, in order to decide if the pipeline is going to be | ||
halted or not. | ||
When the given conditional is `true`, the pipeline will return {:ok, :skipped} and all the following | ||
steps will be skipped. | ||
``` | ||
defmodule CreateUserPipeline do | ||
use Opus.Pipeline | ||
skip if: :user_exists? | ||
step :persist_user | ||
end | ||
``` | ||
In this example, if the `user_exists?` implementation returns `true`, then the next step `persist_user` | ||
is not going to be called. If `false` or any other value, then Opus will keep following to the next stages. | ||
""" | ||
|
||
alias Opus.Pipeline.Stage | ||
|
||
@behaviour Stage | ||
|
||
def run({module, type, [if: func], opts}, input) do | ||
case Stage.maybe_run({module, type, nil, opts |> put_in([:if], func)}, input) do | ||
:pipeline_skipped -> {:halt, :skipped} | ||
_ -> {:cont, input} | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
defmodule Opus.Pipeline.Stage.SkipTest do | ||
use ExUnit.Case | ||
|
||
describe "when the stage returns false and there's no next stage" do | ||
defmodule SingleSkipFalsePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :should_skip? | ||
|
||
def should_skip?(_), do: false | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: SingleSkipFalsePipeline}} | ||
end | ||
|
||
test "returns a success tuple with the original input", %{subject: subject} do | ||
assert {:ok, 1} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when the stage returns false and there's another next stage" do | ||
defmodule SkipFalsePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :should_skip? | ||
step :sum_10, with: &(&1 + 10) | ||
|
||
def should_skip?(_), do: false | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: SkipFalsePipeline}} | ||
end | ||
|
||
test "returns a success tuple with the expected final pipeline data", %{subject: subject} do | ||
assert {:ok, 11} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when the stage returns true" do | ||
defmodule SkipTruePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :should_skip? | ||
step :shouldnt_be_called, with: fn _ -> raise "Shoudn't raise" end | ||
|
||
def should_skip?(_), do: true | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: SkipTruePipeline}} | ||
end | ||
|
||
test "returns a success tuple with :skipped as the second value", %{subject: subject} do | ||
assert {:ok, :skipped} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when more than one skip stage is added to the pipeline and the first skip returns true" do | ||
defmodule MultiSkipFirstTruePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :hope_it_skips | ||
skip if: :not_gonna_skip | ||
step :shouldnt_be_called, with: fn _ -> raise "Shoudn't raise" end | ||
|
||
def hope_it_skips(_), do: true | ||
def not_gonna_skip(_), do: false | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: MultiSkipFirstTruePipeline}} | ||
end | ||
|
||
test "returns a success tuple with :skipped as the second value", %{subject: subject} do | ||
assert {:ok, :skipped} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when more than one skip stage is added to the pipeline and the second skip returns true" do | ||
defmodule MultiSkipSecondTruePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :not_gonna_skip | ||
skip if: :hope_it_skips | ||
step :shouldnt_be_called, with: fn _ -> raise "Shoudn't raise" end | ||
|
||
def hope_it_skips(_), do: true | ||
def not_gonna_skip(_), do: false | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: MultiSkipSecondTruePipeline}} | ||
end | ||
|
||
test "returns a success tuple with :skipped as the second value", %{subject: subject} do | ||
assert {:ok, :skipped} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when more than one skip stage is added to the pipeline and all them return false" do | ||
defmodule MultiSkipFalsePipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :not_gonna_skip | ||
skip if: :not_gonna_skip_also | ||
step :sum_10, with: &(&1 + 10) | ||
|
||
def not_gonna_skip(_), do: false | ||
def not_gonna_skip_also(_), do: false | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: MultiSkipFalsePipeline}} | ||
end | ||
|
||
test "returns a success tuple with the expected final pipeline data", %{subject: subject} do | ||
assert {:ok, 11} = subject.call(1) | ||
end | ||
end | ||
|
||
describe "when the stage returns anything other than 'true' (boolean) and there's another next stage" do | ||
defmodule SkipFalseNonBooleanPipeline do | ||
use Opus.Pipeline | ||
|
||
skip if: :should_skip? | ||
step :sum_10, with: &(&1 + 10) | ||
|
||
def should_skip?(_), do: 'anything_else' | ||
end | ||
|
||
setup do | ||
{:ok, %{subject: SkipFalseNonBooleanPipeline}} | ||
end | ||
|
||
test "returns a success tuple as if the skip stage has returned false and next stage is called", | ||
%{subject: subject} do | ||
assert {:ok, 11} = subject.call(1) | ||
end | ||
end | ||
end |