lecture 4: elixir genserver processes - utelixir processes ›process is the cornerstone for...

12
MTAT.03.295 Agile Software Development Lecture 4: Elixir GenServer processes Luciano García-Bañuelos

Upload: others

Post on 20-May-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

MTAT.03.295Agile Software Development

Lecture 4: Elixir GenServer processes

Luciano García-Bañuelos

Page 2: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Elixir processes

› Process is the cornerstone for Elixir’s concurrency model– Provides also the means for building distributed and fault-

tolerant software

› In Elixir, all code runs inside processes– Run in isolation from each other

– Run concurrent to one another, without sharing any state

– Communicate with each other via message passing

Agile Software Development - Elixir processes 1

Page 3: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Not to confuse with

› Operating system processes

› Not even with threads

› Elixir processes are extremely lightweight

› HOW?– Each process maintains its own state => No need for

mutual exclusion mechanisms

– For the same reason other mechanisms such as garbage collection and instantiation is extremely fast.

Agile Software Development - Elixir processes 2

Page 4: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

First example: A stack

Agile Software Development - Elixir processes 3

defmodule Stack dodef create(), do: loop([])

defp loop(state) doreceive do

{:push, value} -> loop([value|state]){:pop} ->

IO.puts hd(state) loop(tl(state))

endend

end

> iex.bat –S mixiex(1)> pid = spawn(Stack, :create, [])iex(2)> send pid, {:push, 10}iex(3)> send pid, {:push, 15}iex(4)> send pid, {:push, 20}iex(5)> send pid, {:pop}

Page 5: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

GenServer

› Provides an high level abstraction for implementing the behavior of processes

› Relies in the same design principle as the previous example– Internally, it maintains a loop with tail recursion

– Uses also the message exchange mechanism (e.g. receive and send)

– Provides a error handling and other housekeeping operations (e.g. creation, stopping, hibernating, etc.)

Agile Software Development - Elixir processes 4

Page 6: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

A stack implementation using GenServer

Agile Software Development - Elixir processes 5

defmodule Stack douse GenServer

def handle_cast({:push, value}, state) do{:noreply, [value | state]}

enddef handle_call({:pop}, _from, state) do{:reply, hd(state), tl(state)}

endend > iex.bat –S mix

iex(1)> {:ok, pid} = GenServer.start_link(Stack,[])iex(2)> GenServer.cast(pid, {:push, 10})iex(3)> GenServer.cast({:push, 15})iex(4)> GenServer.cast({:push, 20})iex(5)> GenServer.call(pid, {:pop})

Page 7: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Let us improve the latter code

Agile Software Development - Elixir processes 6

defmodule Stack douse GenServer

def start_link, do: GenServer.start_link(Stack, [])def push(pid, value), do: GenServer.cast(pid, {:push, value})def pop(pid), do: GenServer.call(pid, {:pop})

def handle_cast({:push, value}, state) do{:noreply, [value | state]}

enddef handle_call({:pop}, _from, state) do{:reply, hd(state), tl(state)}

endend

> iex.bat –S mixiex(1)> {:ok, pid} = Stack.start_link()iex(2)> Stack.push(pid, 10)iex(3)> Stack.push(pid, 15)iex(4)> Stack.push(pid, 20)iex(5)> Stack.pop(pid)

Page 8: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Hands on time

› As a way of example, we are going to implement a GenServer that holds the state of a classic paper-and-pencil game: The Hangman

Agile Software Development - Elixir processes 7

Page 9: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

A short introduction to REST web services

› REST stands for Representational State Transfer– First described in 2000 by Roy Fielding in his Doctoral

Dissertation

› REST is an architecture style for designing networked applications– The World Wide Web itself uses a REST-based

architecture

› REST is not an standard nor a product

Agile Software Development - Elixir processes 8

Page 10: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Building blocks

Agile Software Development - Elixir processes 9

URI

HTTP

Hypermedia

Interaction model

Hyperlinks as a way for triggering processing

Interaction protocol

Methods: GET, POST, PUT, DELETE, etc.

Status codes: 200 OK, 404 Not found, etc.

Metadata: Location, Content format, etc.

Resource identifier

e.g. https://courses.cs.ut.ee/2017/asd

Page 11: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Example of a REST API (Hangman)

Verb URI Comments Input Output

POST /games Creates a new game (Header)

Location /games/:id

(Status code) 201

GET /games/:id Retrieve the current

state of a game

Game state as JSON

{"feedback": "h-ll-",

"state": "playing"}

POST /games/:id/guesses Submits a new guess

(a letter)

As JSON

{"guess": "a"}

(Status code) 201

Agile Software Development - Elixir processes 10

Page 12: Lecture 4: Elixir GenServer processes - utElixir processes ›Process is the cornerstone for Elixir’s concurrency model –Provides also the means for building distributed and fault-tolerant

Elixir’s Plug and Plug.Router

Agile Software Development - Elixir processes 11

defmodule GameRouter douse Plug.Router

plug :matchplug Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Poisonplug :dispatch

def start_link, do: Plug.Adapters.Cowboy.http(GameRouter, [])

post "/games" doid = UUID.uuid1(){:ok, _} = Game.start_link(String.to_atom(id))conn|> put_resp_header("Location", "/games/#{id}")|> send_resp(201, "Your game has been created")

end

end