Skip to content

Instantly share code, notes, and snippets.

@SLIB53
Created October 17, 2016 03:43
Show Gist options
  • Save SLIB53/4e4eb8b96a7c16112c4a1889ece5ecd7 to your computer and use it in GitHub Desktop.
Save SLIB53/4e4eb8b96a7c16112c4a1889ece5ecd7 to your computer and use it in GitHub Desktop.
This is an example of something like a linear data flow machine. The demo illustrates how to clearly implement a sequence of linear steps so that each step is is similarly handled. This pattern is useful for orchestrating a high level steps, such as a sequence of calls to other services in a "serverless" application.
% This is an example of something like a linear data flow machine. The demo
% illustrates how to clearly implement a sequence of linear steps so that each
% step is is similarly handled. This pattern is useful for orchestrating a high
% level steps, such as a sequence of calls to other services in a "serverless"
% application.
-module(data_sequence).
-export([demo/0]).
demo() ->
DemoSequence = [
{<<"Step 1">>, fun ok_demo_step/1},
{<<"Step 2">>, fun error_demo_step/1}
],
execute(DemoSequence, [], fun demo_error_effects/3, fun demo_crash_effects/3).
demo_error_effects({StepName, _StepFun} = _Step, _Buffer, {Error, Reason}) ->
io:format("Step>~p failed! Error>~p Reason>~p Discontinuing sequence...~n",
[StepName, Error, Reason]),
ok.
demo_crash_effects({StepName, _StepFun} = _Step, _Buffer, {Error, Reason}) ->
io:format("Step>~p crashed! Error>~p Reason>~p Discontinuing sequence...~n",
[StepName, Error, Reason]),
ok.
%%------------------------------------------------------------------------------
%% Steps
%%------------------------------------------------------------------------------
ok_demo_step(Buffer) ->
io:format("Pretending to do work...~n"),
timer:sleep(3000),
io:format("Did so much work.~n"),
{ok, Buffer}.
error_demo_step(_Buffer) ->
io:format("Doing some bad work...~n"),
not_a_real_module:f().
%%------------------------------------------------------------------------------
%% Data Sequencer
%%------------------------------------------------------------------------------
execute(Sequence, Input, ErrorEffectsCallback, CrashEffectsCallback) ->
SequenceNames = [Name || {Name, _} <- Sequence],
io:format("Running sequence:~p ...~n~n",
[SequenceNames]),
execution_handler(Sequence, Input, ErrorEffectsCallback, CrashEffectsCallback).
execution_handler([], Buffer, _ErrorEffectsCallback, _CrashEffectsCallback) ->
{ok, Buffer};
execution_handler([{StepName, StepFun} = Step | RemainingSteps],
Buffer,
ErrorEffectsCallback,
CrashEffectsCallback) ->
try
io:format("Running step ~p ...~n", [StepName]),
case apply(StepFun, [Buffer]) of
{ok, NewBuffer} ->
io:format("Completed step: ~p.~n~n", [StepName]),
execution_handler(RemainingSteps,
NewBuffer,
ErrorEffectsCallback,
CrashEffectsCallback);
{error, _} = E ->
apply(ErrorEffectsCallback, [Step, Buffer, E]),
{error, Buffer}
end
catch
Error:Reason ->
apply(CrashEffectsCallback, [Step, Buffer, {Error, Reason}]),
{error, Buffer}
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment