flowex - railway flow-based programming with elixir genstage

52
Flowex - Flow-Based Programming with Elixir GenStage Elixir Club 5, Kyiv, January 28, 2017

Upload: anton-mishchuk

Post on 11-Apr-2017

79 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Flowex - Railway Flow-Based Programming with Elixir GenStage

Flowex - Flow-Based Programming with Elixir GenStage

Elixir Club 5, Kyiv, January 28, 2017

Page 2: Flowex - Railway Flow-Based Programming with Elixir GenStage

- Ruby developer at Matic Insurance- Elixir fan- Author and maintainer of

ESpec BDD test framework

github: antonmi

Hello!I am Anton Mishchuk

2

Page 3: Flowex - Railway Flow-Based Programming with Elixir GenStage

The problem

◎ There are some problems in “conventional programing”:

- code is procedural and sequential- parallelism is not native- hierarchical structure of program- visualisation is more about structure

◎ We need alternative approaches for building our programs to make software better!

3

Page 5: Flowex - Railway Flow-Based Programming with Elixir GenStage

The goal of the talk

◎ Discuss a special case of Flow-Based Programming: “Railway FBP” (R-FBP)

◎ Present Flowex library which helps to create R-FBP abstractions

◎ Show that Elixir GenStage is not only about data-processing but about software design

5

Page 6: Flowex - Railway Flow-Based Programming with Elixir GenStage

What will be about

◎ Flow-Based Programming (FBP)◎ Railway Oriented Programming (ROP)◎ Railway FBP◎ Flowex library

Lots of pictures!

6

Page 7: Flowex - Railway Flow-Based Programming with Elixir GenStage

1.Flow-Based Programming Basic concepts

7

Page 8: Flowex - Railway Flow-Based Programming with Elixir GenStage

“FBP - a programming paradigm

that defines applications as networks of "black box" processes,

which exchange data across predefined connections by

message passing

J. Paul Morrison, Flow-Based Programming, 2nd Edition 8

Page 9: Flowex - Railway Flow-Based Programming with Elixir GenStage

FBP diagram

A

B

D

C

IN 1

IN 1

IN 1

IN 2

IN 1

IN 2

OUT 1

OUT 2

OUT 1

OUT 1

OUT 1

9

Page 10: Flowex - Railway Flow-Based Programming with Elixir GenStage

Express a problem in terms of transforms on streams of data

http://www.jpaulmorrison.com/fbp/FBPnew.ppt

10

Page 11: Flowex - Railway Flow-Based Programming with Elixir GenStage

Design pros

◎ Independent and reusable components◎ Clean interfaces◎ Simple to reconfigure◎ Minimizes side-effects◎ Designer can sit at one “station”, or can

follow an item through system

http://www.jpaulmorrison.com/fbp/FBPnew.ppt

11

Page 12: Flowex - Railway Flow-Based Programming with Elixir GenStage

“Native parallelism”

12

Page 13: Flowex - Railway Flow-Based Programming with Elixir GenStage

2.Railway Oriented Programming Design pattern

13

Page 14: Flowex - Railway Flow-Based Programming with Elixir GenStage

Express a problem in terms of sequence of functions calls

request |> validate_request|> get_user|> update_db_from_request|> send_email|> return_http_message

14

Page 15: Flowex - Railway Flow-Based Programming with Elixir GenStage

Define common interface for successful and error cases

◎ For example use: {:ok, "data"} or {:error, "Failure reason"}

◎ Each function returns {:ok, "data"} or {:error, "Failure reason"}

◎ If function is called with {:error, "Failure reason"} it just bypasses it

15

Page 16: Flowex - Railway Flow-Based Programming with Elixir GenStage

Define interface to bypass errors

http://fsharpforfunandprofit.com/rop/16

Page 17: Flowex - Railway Flow-Based Programming with Elixir GenStage

So the program is a railway from input to output

http://fsharpforfunandprofit.com/rop/17

Page 18: Flowex - Railway Flow-Based Programming with Elixir GenStage

Elixir Plug is a good example!

◎ Each “plug” function receives and returns a “connection structure” %Plug.Conn{}

◎ %Plug.Conn{} contains:assigns, cookies, halted, host, method, params, resp_body, resp_cookies, status, and many other attributes

18

Page 19: Flowex - Railway Flow-Based Programming with Elixir GenStage

3.Railway FBP ROP + FBP

19

Page 20: Flowex - Railway Flow-Based Programming with Elixir GenStage

Let’s transform each part of “Railway” into FBP component!

20

Page 21: Flowex - Railway Flow-Based Programming with Elixir GenStage

Place each function into separate process

validate send_emailupdate_db

That is the idea!21

Page 22: Flowex - Railway Flow-Based Programming with Elixir GenStage

Why Elixir?

22

Page 23: Flowex - Railway Flow-Based Programming with Elixir GenStage

GenStage

◎ Easiest way to implement a chain of communicating processes

◎ Back-pressure mechanism

producer consumer

Subscribe

Ask

Events

23

Page 24: Flowex - Railway Flow-Based Programming with Elixir GenStage

Metaprogramming

◎ Simple way for sharing functionality◎ Ability to create expressive DSL

24

Page 25: Flowex - Railway Flow-Based Programming with Elixir GenStage

4.FlowexRailway FBP

25

Page 26: Flowex - Railway Flow-Based Programming with Elixir GenStage

Consider an example!

26

Page 27: Flowex - Railway Flow-Based Programming with Elixir GenStage

Calculate (number + 1) * 2 - 3

27

Page 28: Flowex - Railway Flow-Based Programming with Elixir GenStage

Note, the functions are cool!

◎ They have the same interface◎ They operate with predefined structWe can join them into pipeline:

28

Page 29: Flowex - Railway Flow-Based Programming with Elixir GenStage

Let’s add some Flowex magic!

29

Page 30: Flowex - Railway Flow-Based Programming with Elixir GenStage

… and rename the module to FunPipeline

30

Page 31: Flowex - Railway Flow-Based Programming with Elixir GenStage

“use Flowex.Pipeline”

◎ Adds ‘pipe’ macro which allows to mark functions “to be placed” into separate Genstage

◎ Defines ‘start’ and ‘stop’ functions for creating and destroying “Flowex pipelines”

◎ Defines ‘run’ function to perform calculations

31

Page 32: Flowex - Railway Flow-Based Programming with Elixir GenStage

Start FunPipeline!

32

Page 33: Flowex - Railway Flow-Based Programming with Elixir GenStage

FunPipeline instance

add_one minus_threemult_by_twoproducer consumer

Supervisor

Elixir GenStages

33

Page 34: Flowex - Railway Flow-Based Programming with Elixir GenStage

%Flowex.Pipeline{} struct

◎ module - the name of the module◎ in_name - unique name of 'producer'◎ out_name - unique name of 'consumer'◎ sup_pid - pid of the pipeline supervisor

34

Page 35: Flowex - Railway Flow-Based Programming with Elixir GenStage

Run calculations via “run”

Using FunPipeline.run/2 function

Note, ‘a’, ‘b’ and ‘c’ were set!35

Page 36: Flowex - Railway Flow-Based Programming with Elixir GenStage

Run calculations using Flowex.Client

Using Flowex.Client module

36

Page 37: Flowex - Railway Flow-Based Programming with Elixir GenStage

How it works in details

add_one

minus_three

mult_by_two

producer

consumer

Flowex.Client

%FunPipeline{number: 2}

%Flowex.IP{struct: %FunPipeline{number: 2}, ...}

number: 2

number: 2

number: 3

number: 6

number: 3number: 3

self()

%FunPipeline{number: 3}

37

Page 38: Flowex - Railway Flow-Based Programming with Elixir GenStage

What is sync and what is async?

ClientAsynchronouscommunicationself()

Synchronouscommunication

38

Page 39: Flowex - Railway Flow-Based Programming with Elixir GenStage

Is there no parallelism?

39

Page 40: Flowex - Railway Flow-Based Programming with Elixir GenStage

There can be a lot of clients!

Client

Client

Client

40

Page 41: Flowex - Railway Flow-Based Programming with Elixir GenStage

Bottlenecks.What if there is very slow process in the pipeline?

41

Page 42: Flowex - Railway Flow-Based Programming with Elixir GenStage

Just small changes in the code

42

Page 43: Flowex - Railway Flow-Based Programming with Elixir GenStage

And you get this

add_one

minus_three

mult_by_twoproducer consumer

mult_by_two

minus_three

mult_by_two

43

Page 44: Flowex - Railway Flow-Based Programming with Elixir GenStage

Reusable components with “module pipelines”

44

Page 45: Flowex - Railway Flow-Based Programming with Elixir GenStage

Module must implement just two functions

Like Elixir Plug module45

Page 46: Flowex - Railway Flow-Based Programming with Elixir GenStage

Pipeline module

46

Page 47: Flowex - Railway Flow-Based Programming with Elixir GenStage

Conclusion

47

Page 48: Flowex - Railway Flow-Based Programming with Elixir GenStage

Why it is cool!

48

Page 49: Flowex - Railway Flow-Based Programming with Elixir GenStage

It is easy to understand

◎ Pipelines explicitly define a structure of data will be processed

◎ Pipelines explicitly define a way the data will come

◎ Pipelines explicitly define a parallel executors structure

49

Page 50: Flowex - Railway Flow-Based Programming with Elixir GenStage

It is easy to maintain and reuse

◎ There is a predefined set of working processes (components) in a program

◎ Each component is isolated◎ Pipelines can (and should) reuse

components

50

Page 51: Flowex - Railway Flow-Based Programming with Elixir GenStage

It is about controlled parallelism

◎ One can controll number of clients supplying data to a pipeline

◎ One can control the number of processes available for each component

51

Page 52: Flowex - Railway Flow-Based Programming with Elixir GenStage

Thank you! Questions?

52

You can star the project here: https://github.com/antonmi/flowex