reactive programming with elixir and rethinkdb › static › upload › media › ...reactive...
TRANSCRIPT
![Page 1: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/1.jpg)
Reactive Programming with Elixir and RethinkDBPeter Hamilton
Erlang Factory 2016
![Page 2: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/2.jpg)
Let’s Build Something!
![Page 3: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/3.jpg)
Which character do people tweet most?
The first tweet had 6 uses of ’t'
![Page 4: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/4.jpg)
Data Transformations
Raw Tweet Analyzed Tweet
Dashboard DataDashboard
Analyzer
Aggregator
Publisher
![Page 5: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/5.jpg)
Elixir Stream
tweet_stream |> Stream.map(&analyze_tweet/1) |> Stream.scan(initial_dashboard, &update_dashboard/2) |> Stream.each(&broadcast/1) |> Stream.run
Problems?
![Page 6: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/6.jpg)
RethinkDBThe open-source database
for the realtime web
![Page 7: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/7.jpg)
ReQLtable(“people”) |> filter(%{name: “John”})
table(“people”) |> filter(lambda fn (person) -‐> person[:age] > count(person[:name]) end)
table(“people”) |> merge(lambda fn (person) -‐> if (person[:age] < 13) do %{name: “PRIVATE”} else %{} end end)
![Page 8: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/8.jpg)
More ReQL# Get all posts, include author
table(“posts”) |> eq_join(“author_id”, table(“people”)) |> zip
# Get people and any posts they might have written
table(“people”) |> merge(lambda fn (person) -‐> posts = table(“posts”) |> filter(%{author_id: person[:id]}) |> coerce_to(:array) %{posts: posts} end)
![Page 9: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/9.jpg)
Even More ReQL# Count posts per author
table(“posts”) |> group(“author_id”) |> count
# Word count per author
table(“posts”) |> group(“author_id”) |> map(lambda &(count(&1[:post])) |> sum
![Page 10: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/10.jpg)
The Most ReQL# Get counts of frequent/occasional authors (including staff)
table(“people”) |> group(lambda fn (person) -‐> post_count = table(“posts”) |> filter(%{author_id: person[:id]}) |> count (post_count < 20) |> coerce_to(:string) end) |> map(lambda fn (author) -‐> 1 + count(author[:staff]) end) |> sum |> ungroup |> map(&values(&1)) |> coerce_to(:object) |> map(lambda fn (obj) -‐> %{frequent: obj[“true”], occasional: obj[“false”]} end)
![Page 12: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/12.jpg)
Let’s Use RethinkDB!
![Page 13: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/13.jpg)
Elixir Stream
tweet_stream |> Stream.map(&analyze_tweet/1) |> Stream.scan(initial_dashboard, &update_dashboard/2) |> Stream.each(&broadcast/1) |> Stream.run
Our Original
![Page 14: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/14.jpg)
Restructure with RethinkDBRethinkDB
Tweet Streamer Tweet Analyzer Tweet Aggregator
Dashboard Publisher
![Page 15: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/15.jpg)
RethinkDB.ChangefeedOTP Behaviour
use RethinkDB.Changefeed
Define the query, database and initial state
init(opts) :: {:subscribe, query, db, state} | {:stop, reason}
Process updates
handle_update(update, state) :: {:next, state} | {:stop, reason, state}
Plus GenServer callbacks
![Page 16: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/16.jpg)
Tweet Streamer
def start_link(topic) do ExTwitter.stream_filter(track: topic) |> Stream.each(fn el -‐> table("tweets") |> insert(%{text: el.text, state: “RAW"}) |> run end) |> StreamRunner.start_linkend
![Page 17: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/17.jpg)
Tweet Analyzer (Part 1)
def init(_opts) do query = table("tweets") |> filter(%{state: "RAW"}) |> changes(include_initial: true) {:subscribe, query, DB, nil}end
![Page 18: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/18.jpg)
Tweet Analyzer (Part 2)def handle_update(data, _state) do Enum.each(fn %{“new_val” => el, “old_val” => nil} -‐> most_used_char = get_most_used_char(el) table(“tweets”) |> get(el[“id”]) |> update(lambda fn (tweet) -‐> if (tweet[“state”] == “RAW”) do %{state: “PROCESSED”, most_used_char: most_used_char} else %{} end end) |> run end) {:next, nil}end
![Page 19: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/19.jpg)
Tweet Aggregator (Part 1)
def init(_opts) do query = table("tweets") |> filter(%{state: "PROCESSED"}) |> changes(include_initial: true) {:subscribe, query, DB, nil}end
![Page 20: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/20.jpg)
Tweet Aggregator (Part 2)
def handle_update(data, _state) do Enum.each(data, fn %{“new_val” => el, “old_val” => nil} -‐> update_tweet_state(“PROCESSED”, “RECORDED”) char = el[“most_used_char”] table(“dashboard”) |> get(“character_dashboard”) |> update(lambda fn (dashboard) -‐> %{char => default(dashboard[char], 0) +1} end) |> run end) {:next, nil}end
![Page 21: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/21.jpg)
Dashboard Publisher (Part 1)
def init(_opts) do query = table("dashboards") |> get(“character_dashboard”) |> changes(include_initial: true, squash: true) {:subscribe, query, DB, nil}end
![Page 22: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/22.jpg)
Dashboard Publisher (Part 2)
def handle_update(%{"new_val" => val}, _state) do process_dashboard(val) |> publish_dashboard {:next, nil}end
![Page 23: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/23.jpg)
Is it better?
Pros
![Page 24: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/24.jpg)
Is it better?
Cons
![Page 25: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/25.jpg)
Rethinking Your Designs
![Page 26: Reactive Programming with Elixir and RethinkDB › static › upload › media › ...Reactive Programming with Elixir and RethinkDB Peter Hamilton Erlang Factory 2016 Let’s Build](https://reader036.vdocuments.us/reader036/viewer/2022081400/5f0f61367e708231d443deed/html5/thumbnails/26.jpg)
Thank you!
Please reach out with any questions!
github: hamiltop/rethinkdb-elixir
slack: #rethinkdb on elixir-lang
email: [email protected]
twitter: hamiltop
Special thanks to Annie Ruygt at RethinkDB for the artwork!