Finagle & Clojure
by Alexey Kachayev for #FinagleCon 2015
Finagle & Clojure by Alexey Kachayev for #FinagleCon 2015 About - - PowerPoint PPT Presentation
Finagle & Clojure by Alexey Kachayev for #FinagleCon 2015 About Me Alexey Kachayev, @kachayev CTO at Attendify.com Almost-all-day-coding-kind-of-CTO Active open source contributor Attendify Use Case Detailed Event
by Alexey Kachayev for #FinagleCon 2015
Detailed Event information. Private event community and social network. A fully featured event app with essential content.
$ ¡lein ¡new ¡finagle-‑clojure ¡schedule ¡ $ ¡tree ¡-‑L ¡2 ¡ . ¡ ¡schedule ¡ ¡ ¡ ¡ ¡ ¡README.md ¡ ¡ ¡ ¡ ¡ ¡project.clj ¡ ¡ ¡ ¡ ¡ ¡schedule-‑client ¡ ¡ ¡ ¡ ¡ ¡schedule-‑core ¡ ¡ ¡ ¡ ¡ ¡schedule-‑service
namespace ¡java ¡schedule.thrift ¡ struct ¡SessionRequest ¡{ ¡ ¡ ¡1: ¡string ¡id ¡ } ¡ struct ¡Session ¡{ ¡ ¡ ¡1: ¡string ¡id ¡ ¡ ¡2: ¡string ¡title ¡ ¡ ¡3: ¡string ¡speaker ¡ } ¡ service ¡Schedule ¡{ ¡ ¡ ¡ ¡ ¡Session ¡fetchSession(1: ¡SessionRequest ¡req) ¡ }
(ns ¡schedule.service ¡ ¡ ¡(:import ¡[schedule.thrift ¡Schedule ¡Session]) ¡ ¡ ¡(:require ¡[finagle-‑clojure.futures ¡:as ¡f] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡[finagle-‑clojure.thrift ¡:as ¡thrift]) ¡ ¡ ¡(:gen-‑class)) ¡ (defn ¡make-‑service ¡ ¡ ¡[] ¡ ¡ ¡(thrift/service ¡Schedule ¡ ¡ ¡ ¡ ¡(fetchSession ¡[req] ¡ ¡ ¡ ¡ ¡ ¡ ¡(let ¡[id ¡(.id ¡req)] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(f/value ¡(Session. ¡id ¡"Clojure" ¡"Alexey")))))) ¡ (defn ¡-‑main ¡ ¡ ¡[& ¡args] ¡ ¡ ¡(f/await ¡(thrift/serve ¡":9999" ¡(make-‑service))))
(ns ¡schedule.client ¡ ¡ ¡(:import ¡[schedule.thrift ¡Schedule]) ¡ ¡ ¡(:require ¡[finagle-‑clojure.futures ¡:as ¡f] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡[finagle-‑clojure.thrift ¡:as ¡thrift])) ¡ (defn ¡make-‑client ¡ ¡ ¡[address] ¡ ¡ ¡(thrift/client ¡address ¡Schedule)) ¡ (defn ¡session-‑title ¡[client ¡id] ¡ ¡ ¡(-‑> ¡(.fetchSession ¡client ¡(SessionRequest. ¡id)) ¡ ¡ ¡ ¡ ¡ ¡ ¡(f/map ¡[v] ¡(.title ¡v))))
(defn ¡speaker-‑name ¡[client ¡session-‑id] ¡ ¡ ¡(-‑> ¡(.fetchSession ¡client ¡(SessionRequest. ¡session-‑id)) ¡ ¡ ¡ ¡ ¡ ¡ ¡(f/flatmap ¡[v] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(let ¡[speaker-‑id ¡(.speaker ¡v) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡req ¡(SpeakerRequest. ¡speaker-‑id)] ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(-‑> ¡(.fetchSpeaker ¡client ¡req) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(f/map ¡[v] ¡(.firstName ¡v))))))) ¡ (defn ¡-‑main ¡[& ¡args] ¡ ¡ ¡(let ¡[c ¡(make-‑client ¡"localhost:9999")] ¡ ¡ ¡ ¡ ¡(println ¡(f/await ¡(session-‑title ¡c ¡"42"))) ¡ ¡ ¡ ¡ ¡(println ¡(f/await ¡(speaker-‑name ¡c ¡"42")))))
builders
(-‑> ¡(builder-‑server/builder) ¡ ¡ ¡ ¡ ¡(builder-‑server/codec ¡http-‑codec/http) ¡ ¡ ¡ ¡ ¡(builder-‑server/bind-‑to ¡3000) ¡ ¡ ¡ ¡ ¡(builder-‑server/named ¡“test”) ¡ ¡ ¡ ¡ ¡(builder-‑server/build ¡hello-‑world)) (new-‑server ¡hello-‑world ¡{:codec ¡http-‑codec/http ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:tls ¡nil ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:max-‑request-‑size ¡200 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:max-‑response-‑size ¡400 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:bind-‑to ¡3000 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:name ¡:test})
(-‑> ¡(builder-‑server/builder) ¡ ¡ ¡ ¡ ¡(builder-‑server/codec ¡http-‑codec/http) ¡ ¡ ¡ ¡ ¡(builder-‑server/bind-‑to ¡3000) ¡ ¡ ¡ ¡ ¡(builder-‑server/named ¡“test”) ¡ ¡ ¡ ¡ ¡(builder-‑server/build ¡hello-‑world)) (new-‑server ¡hello-‑world ¡{:codec ¡http-‑codec/http ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:tls ¡nil ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:max-‑request-‑size ¡200 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:max-‑response-‑size ¡400 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:bind-‑to ¡3000 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡:name ¡:test})
(def ¡req ¡(SessionRequest. ¡"42")) ¡ (def ¡f1 ¡(.fetchSession ¡client ¡req)) ¡ (def ¡d4 ¡(d/deferred)) ¡ (f/on-‑success ¡f1 ¡[v] ¡(d/success! ¡d4 ¡v)) ¡ (f/on-‑failure ¡f1 ¡[v] ¡(d/error! ¡d4 ¡v)) ¡ user> ¡@d4 ¡ user> ¡#object[Session[…]] ¡ user> ¡@(d/chain ¡d4 ¡#(.title ¡%)) ¡ user> ¡"Finagle ¡& ¡Clojure"
(defn ¡future-‑>deferred ¡[sf] ¡ ¡ ¡(let ¡[d1 ¡(d/deferred)] ¡ ¡ ¡ ¡ ¡(f/on-‑success ¡sf ¡[v] ¡(d/success! ¡d1 ¡v)) ¡ ¡ ¡ ¡ ¡(f/on-‑failure ¡sf ¡[v] ¡(d/error! ¡d1 ¡v)) ¡ ¡ ¡ ¡ ¡d1)) ¡ (defn ¡fetch-‑session ¡[c ¡id] ¡ ¡ ¡(f-‑>d ¡(.fetchSession ¡c ¡(SessionRequest. ¡id)))) ¡ (defn ¡fetch-‑speaker ¡[c ¡id] ¡ ¡ ¡(f-‑>d ¡(.fetchSpeaker ¡c ¡(SpeakerRequest. ¡id))))
(defn ¡speaker-‑name ¡[c ¡session] ¡ ¡ ¡(let-‑flow ¡[session ¡(fetch-‑session ¡c ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sid ¡(.speaker ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker ¡(fetch-‑speaker ¡c ¡sid)] ¡ ¡ ¡ ¡ ¡(str ¡(.firstName ¡speaker) ¡" ¡" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(.lastName ¡speaker)))) ¡ user> ¡(speaker-‑name ¡client ¡"42") ¡ user> ¡#object[Deferred] ¡ user> ¡@(speaker-‑name ¡client ¡"42") ¡ user> ¡"Alexey ¡Kachayev"
(defn ¡speaker-‑name ¡[c ¡session] ¡ ¡ ¡(let-‑flow ¡[session ¡(fetch-‑session ¡c ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡sid ¡(.speaker ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker ¡(fetch-‑speaker ¡c ¡sid)] ¡ ¡ ¡ ¡ ¡(str ¡(.firstName ¡speaker) ¡" ¡" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(.lastName ¡speaker))))
values deferreds
programming and communication”
(defn ¡future-‑>chan ¡[sf] ¡ ¡ ¡(let ¡[c1 ¡(a/chan ¡1)] ¡ ¡ ¡ ¡ ¡(f/on-‑success ¡sf ¡[v] ¡(a/put! ¡c1 ¡v)) ¡ ¡ ¡ ¡ ¡(f/on-‑failure ¡sf ¡[v] ¡(a/put! ¡c1 ¡(e/left ¡v))) ¡ ¡ ¡ ¡ ¡c1)) ¡ (defn ¡fetch-‑session ¡[c ¡id] ¡ ¡ ¡(f-‑>c ¡(.fetchSession ¡c ¡(SessionRequest. ¡id)))) ¡ (defn ¡fetch-‑speaker ¡[c ¡id] ¡ ¡ ¡(f-‑>c ¡(.fetchSpeaker ¡c ¡(SpeakerRequest. ¡id))))
(defn ¡speaker-‑name ¡[c ¡session-‑id] ¡ ¡ ¡(go ¡ ¡ ¡ ¡ ¡(let ¡[session ¡(<! ¡(fetch-‑session ¡c ¡session-‑id)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker-‑id ¡(.speaker ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker ¡(<! ¡(fetch-‑speaker ¡c ¡speaker-‑id))] ¡ ¡ ¡ ¡ ¡ ¡ ¡(str ¡(.firstName ¡speaker) ¡" ¡" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(.lastName ¡speaker))))) ¡ user> ¡(speaker-‑name ¡client ¡"42") ¡ user> ¡#object[ManyToManyChannel] ¡ user> ¡(<!! ¡(speaker-‑name ¡client ¡"42")) ¡ user> ¡"Alexey ¡Kachayev"
(defn ¡speaker-‑name ¡[c ¡session-‑id] ¡ ¡ ¡(go ¡ ¡ ¡ ¡ ¡(let ¡[session ¡(<! ¡(fetch-‑session ¡c ¡session-‑id)) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker-‑id ¡(.speaker ¡session) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡speaker ¡(<! ¡(fetch-‑speaker ¡c ¡speaker-‑id))] ¡ ¡ ¡ ¡ ¡ ¡ ¡(str ¡(.firstName ¡speaker) ¡" ¡" ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡(.lastName ¡speaker))))) ¡
state machine
(:import ¡[com.twitter.util ¡Promise]) ¡ (defn ¡propagate-‑to ¡[promise ¡value] ¡ ¡ ¡(if ¡(e/left? ¡value) ¡ ¡ ¡ ¡ ¡(.setException ¡promise ¡(e/left-‑value ¡value)) ¡ ¡ ¡ ¡ ¡(.setValue ¡promise ¡(e/right-‑value ¡value)))) ¡ (defn ¡chan-‑>future ¡[c] ¡ ¡ ¡(let ¡[promise ¡(Promise.)] ¡ ¡ ¡ ¡ ¡(a/take! ¡c ¡(partial ¡propagate-‑to ¡promise)) ¡ ¡ ¡ ¡ ¡promise))
(:import ¡[com.twitter.util ¡Promise]) ¡ (defn ¡propagate-‑to ¡[promise ¡value] ¡ ¡ ¡(if ¡(e/left? ¡value) ¡ ¡ ¡ ¡ ¡(.setException ¡promise ¡(e/left-‑value ¡value)) ¡ ¡ ¡ ¡ ¡(.setValue ¡promise ¡(e/right-‑value ¡value)))) ¡ (defn ¡chan-‑>future ¡[c] ¡ ¡ ¡(let ¡[promise ¡(Promise.)] ¡ ¡ ¡ ¡ ¡(a/take! ¡c ¡(partial ¡propagate-‑to ¡promise)) ¡ ¡ ¡ ¡ ¡promise))
core.async
{:id ¡42 ¡ ¡:title ¡"Finagle ¡& ¡Clojure" ¡ ¡:tracks ¡["Libraries" ¡"Practice"] ¡ ¡:tags ¡#{"Finagle" ¡"Clojure"} ¡ ¡:speaker ¡{:name ¡"Alexey ¡Kachayev"} ¡ ¡:at ¡#inst ¡"2015-‑08-‑13T14:30:00" ¡ ¡:duration ¡#duration ¡"10s"}
{:id ¡42 ¡ ¡:title ¡"Finagle ¡& ¡Clojure" ¡ ¡:tracks ¡["Libraries" ¡"Practice"] ¡ ¡:tags ¡#{"Finagle" ¡"Clojure"} ¡ ¡:speaker ¡{:name ¡"Alexey ¡Kachayev"} ¡ ¡:at ¡#inst ¡"2015-‑08-‑13T14:30:00" ¡ ¡:duration ¡#duration ¡"10s"}
tags
ecosystem
Questions?