Wednesday, March 20, 2013 Introducing Pedestal Who: Relevance - - PowerPoint PPT Presentation

wednesday march 20 2013 introducing pedestal
SMART_READER_LITE
LIVE PREVIEW

Wednesday, March 20, 2013 Introducing Pedestal Who: Relevance - - PowerPoint PPT Presentation

Wednesday, March 20, 2013 Introducing Pedestal Who: Relevance What: alpha release, open source libs Where: Clojure/West When: Now Why, How... 2 Wednesday, March 20, 2013 Goal Use clojure end-to-end to build rich


slide-1
SLIDE 1

Wednesday, March 20, 2013

slide-2
SLIDE 2

Introducing Pedestal

  • Who: Relevance
  • What: alpha release, open source libs
  • Where: Clojure/West
  • When: Now
  • Why, How...

2

Wednesday, March 20, 2013

slide-3
SLIDE 3

Goal

  • Use clojure end-to-end to build rich

interactive collaborative Web applications and services that scale

3

Wednesday, March 20, 2013

slide-4
SLIDE 4

Archetype

App App Service Service Datomic Storage Service Datomic Transactor 4

Wednesday, March 20, 2013

slide-5
SLIDE 5

Problems

  • Services notifying apps
  • Building complex UIs in browser

5

Wednesday, March 20, 2013

slide-6
SLIDE 6

Service Plumbing

  • Interceptor mechanism
  • Long polling, server-sent events
  • Routing, url generation

6

Wednesday, March 20, 2013

slide-7
SLIDE 7

Ring Middlewares

  • Chained fns bound to thread’s stack

A B C

7

Wednesday, March 20, 2013

slide-8
SLIDE 8
  • Maps of fns not bound to thread’s stack

A B C enter leave enter leave enter leave

Interceptors

8

Wednesday, March 20, 2013

slide-9
SLIDE 9

A B C enter leave enter leave enter leave pause resume

  • Can pause/resume across threads
  • Supports bindings and error propagation

Pause/Resume

9

Wednesday, March 20, 2013

slide-10
SLIDE 10

Ring Compatibility

  • As compatible as possible
  • Same request/response maps
  • Core middlewares refactored and accepted
  • Interceptor versions provided
  • Easy to port existing code

10

Wednesday, March 20, 2013

slide-11
SLIDE 11

Notifications

  • Thread management enables long polling
  • Park request as needed
  • Also, server-sent-events
  • Built on low-level streaming API

11

Wednesday, March 20, 2013

slide-12
SLIDE 12

Routes and URLs

(defn hello-world [req] (ring/response (map inc [1 2 3])) (defroutes routes [[[“/hello-world” {:get hello-world}]]]) (def url-for (routes/url-for-routes routes)) (url-for ::hello-world) ;;=> “/hello-world”

ring handler fn native edn serialization routes as data make urls from routes

12

Wednesday, March 20, 2013

slide-13
SLIDE 13

Problems

  • Services notifying apps
  • Building complex UIs in browser

13

Wednesday, March 20, 2013

slide-14
SLIDE 14

3 Simple Steps

  • Event handler affects state
  • Figure out what changed
  • Update DOM

14

Wednesday, March 20, 2013

slide-15
SLIDE 15

What to compare?

  • JS: event, old OR new state, DOM
  • CLJS: event, old AND new state, DOM
  • Can remove DOM from equation!

15

Wednesday, March 20, 2013

slide-16
SLIDE 16

Browser Process View App Messages Changes DOM

App vs. View

  • App: behavior
  • View: presentation

16

Wednesday, March 20, 2013

slide-17
SLIDE 17

App Model

  • Encapsulate behavior and state
  • Input: messages
  • Output: app tree deltas
  • Implemented as pure functions
  • Fns wired up declaratively

17

Wednesday, March 20, 2013

slide-18
SLIDE 18

Messages

{msg/topic :count-transform msg/type :inc :key :a}

  • Map with topic and type
  • Other keys as needed
  • Used for input to app
  • Used to control aspects
  • f engine

18

Wednesday, March 20, 2013

slide-19
SLIDE 19

App Tree Deltas

[:node-create [:a :b :c] :map] [:node-destroy [:a :b :c]] [:value [:a :b :c] {:count 2}] [:attr [:a :b :c] :active true] [:transform-enable [:a :b :c] :send-info [{msg/topic :some-model msg/type :send-name (msg/param :name) {}}]] [:transform-disable [:a :b :c] :send-info]

  • p

path args

19

Wednesday, March 20, 2013

slide-20
SLIDE 20

App Tree is Logical

  • Consumer may or may not realize (portions
  • f) tree as real structure

:a :e :d :c :b

{

:value 42 :attributes {:disabled true} :transforms {:change [{:node :e}]}

20

Wednesday, March 20, 2013

slide-21
SLIDE 21

Transform

  • Fn that modifies state
  • Message, state input
  • Last output state kept
  • Only changes flow

App

Transform

Input Queue App Model Queue

State

21

Wednesday, March 20, 2013

slide-22
SLIDE 22

App Input Queue App Model Queue

count- transform State

Transform

(defn count-transform [t-state message] (condp = (msg/type message) msg/init (:value message) :inc (inc (or t-state 0)) t-state)) (put-message (:input-queue app) {msg/topic :count-transform msg/type :inc} ([:value [:io.pedestal.app/view-count-transform] 10 11])

22

Wednesday, March 20, 2013

slide-23
SLIDE 23

Transform output

;; message input... {msg/topic :count-transform msg/type :inc} ;; deltas output... ([:value [:io.pedestal.app/view-count-transform] 10 11]) ;; message input... {msg/topic :count-transform msg/type :inc} ;; deltas output... ([:value [:io.pedestal.app/view-count-transform] 11 12]) ...

23

Wednesday, March 20, 2013

slide-24
SLIDE 24

App Input Queue App Model Queue

count- transform State

More State

(defn count-transform [t-state message] (condp = (msg/type message) msg/init (:value message) :inc (update-in (or t-state {}) (:key message) inc) t-state)) (put-message (:input-queue app) {msg/topic :count-transform msg/type :inc :key :a} ([:value [:io.pedestal.app/view-count-transform] {:a 10 :b 9} {:a 11 :b 9}])

24

Wednesday, March 20, 2013

slide-25
SLIDE 25

Affecting Parts of State

;; put a message in... {msg/topic :count-transform msg/type :inc :key :a} ;; get deltas out... ([:value [:io.pedestal.app/view-count-transform] {:a 10 :b 9} {:a 11 :b 9}]) ;; put a message in... {msg/topic :count-transform msg/type :inc :key :b} ;; get deltas out... ([:value [:io.pedestal.app/view-count-transform] {:a 11 :b 9} {:a 11 :b 10}]) ...

25

Wednesday, March 20, 2013

slide-26
SLIDE 26

App Input Queue App Model Queue

Transform

Combine Combine

Combine

  • Fn that merges or splits

state(s)

  • Transform and/or

combine state(s) input

  • Engine keeps last output
  • Only changes flow

26

Wednesday, March 20, 2013

slide-27
SLIDE 27

App Input Queue App Model Queue

count- transform

a- combine b- combine

Combine

(defn a-combine [c-state t-name t-old-val t-new-val] (:a t-new-val)) (defn b-combine [c-state t-name t-old-val t-new-val] (:b t-new-val)) ([:value [:a-combine] 10 11]) {msg/topic :count-transform msg/type :inc :key :a}

27

Wednesday, March 20, 2013

slide-28
SLIDE 28

App Input Queue App Model Queue

count- transform

a- combine b- combine

Combine

(defn a-combine [c-state t-name t-old-val t-new-val] (:a t-new-val)) (defn b-combine [c-state t-name t-old-val t-new-val] (:b t-new-val)) ([:value [:b-combine] 9 10]) {msg/topic :count-transform msg/type :inc :key :b}

28

Wednesday, March 20, 2013

slide-29
SLIDE 29

App Input Queue App Model Queue

count- transform

a- combine b- combine total- combine

Combine

(defn a-combine [c-state t-name t-old-val t-new-val] (:a t-new-val)) (defn b-combine [c-state t-name t-old-val t-new-val] (:b t-new-val)) (defn total-combine [c-state inputs] (apply + (map :new (vals inputs)))) ([:value [:b-combine] 10 11] [:value [:total-combine] 21 22]) {msg/topic :count-transform msg/type :inc :key :b}

29

Wednesday, March 20, 2013

slide-30
SLIDE 30

App Input Queue App Model Queue

Transform

Combine Combine Emit

Emit

  • Fn that converts state(s)

to tree deltas

  • Overrides default tree

mapping

30

Wednesday, March 20, 2013

slide-31
SLIDE 31

App Input Queue App Model Queue

count- transform

a- combine b- combine counter- emit

Emit

(defn counter-emit ([inputs] [{:counter {:a {:value 0} :b {:value 0}}}]) ([inputs changed-inputs] (concat [] (when (changed-inputs :a-combine) [[:value [:counter :a] (-> inputs :a-view :new)]]) (when (changed-inputs :b-combine) [[:value [:counter :b] (-> inputs :b-view :new)]])))) ([:value [:counter :b] 11 12]) {msg/topic :count-transform msg/type :inc :key :b}

31

Wednesday, March 20, 2013

slide-32
SLIDE 32
  • Effect fn
  • transform or

combine state input

  • msgs for services
  • utput
  • queued after flow
  • Continue fn
  • combine state input
  • msgs for transforms
  • utput
  • sent during flow

Messages in a flow

32

Wednesday, March 20, 2013

slide-33
SLIDE 33

Transform Effect Combine Continue Emit Message Source Services View

All the pieces...

33

Wednesday, March 20, 2013

slide-34
SLIDE 34

...put together

App

combine combine combine combine combine trans- form 1 emit trans- form 2 effect emit emit services App Model Queue Input Queue continue Output Queue services

View

34

Wednesday, March 20, 2013

slide-35
SLIDE 35

Focus

  • Focus filters deltas
  • by name
  • by path
  • Set by consumer
  • defaults to all
  • Helpful “navigtion”

35

App App Model Queue

Emit

Focus

:a :b :f :g :c :d :e :h :i :j

Emit

Wednesday, March 20, 2013

slide-36
SLIDE 36

Benefits of data flow

  • Write small pure fns
  • No big comparator
  • Let engine track state changes
  • Only the necessary fns get called
  • Projects all the way out to consumer

36

Wednesday, March 20, 2013

slide-37
SLIDE 37

Making an App

App Input Queue

count- transform

a- b-

(def counter-dataflow {:transform {:count-transform {:init {:a 0 :b 0} :fn transform-count}} :combine {:a-combine {:fn a-combine :inputs #{:count-transform}} :b-combine {:fn b-combine :inputs #{:count-transform}}} :emit {:counter-emit {:fn counter-emit :inputs #{:a-combine :b-combine}}}}) (def app (app/build counter-dataflow))

37

Wednesday, March 20, 2013

slide-38
SLIDE 38

Consuming App Output

  • App produces logical tree deltas
  • Provide a fn to consume them

(defn console-renderer [out] (fn [deltas input-queue] (binding [*out* out] (doseq [d deltas] (println d))))) (def app-model (render/consume-app-model app (console-renderer *out*))) (app/begin app)

38

Wednesday, March 20, 2013

slide-39
SLIDE 39

View Model

  • Encapsulate presentation logic and state
  • Input: deltas from logical app tree
  • Output: messages
  • Implemented as fn(s) that
  • update UI
  • handle events

39

Wednesday, March 20, 2013

slide-40
SLIDE 40

Push Renderers

  • Map tree deltas

to fns

  • Maintain

structure for portion(s) of tree in focus

(def render-config [[:node-create [] render-page] [:value [:counter :a] render-a-view] [:value [:counter :b] render-b-view]]) (def app-model (render/consume-app-model app (push/renderer render-config)))

  • p

path fn

40

Wednesday, March 20, 2013

slide-41
SLIDE 41

Simple render fns

(defn render-page [renderer [op path old-value new-value] input-queue] (dom/append! (dom/by-id "content") "<h1 id=\"a\">a</h1>") (dom/append! (dom/by-id "content") "<h1 id=\"b\">b</h1>")) (defn render-a-view [renderer [op path old-value new-value] input-queue] (dom/set-text! (dom/by-id "a") (str "a: " new-value))) (defn render-b-view [renderer [op path old-value new-value] input-queue] (dom/set-text! (dom/by-id "b") (str "b: " new-value)))

41

Wednesday, March 20, 2013

slide-42
SLIDE 42

Result!

42

Wednesday, March 20, 2013

slide-43
SLIDE 43

Problems

  • Services notifying apps
  • Building complex UIs in browser

43

Wednesday, March 20, 2013

slide-44
SLIDE 44

App / View Benefits

  • Clean separation of concerns
  • Build, test app outside browser
  • Generic data renderer can drive app before

UI is ready

  • Record/playback changes to build, test,

debug rendering code

44

Wednesday, March 20, 2013

slide-45
SLIDE 45

Getting Started

  • Run chat sample, look at app and service

code

  • lein new pedestal-service my-service
  • lein new pedestal-app my-app

45

Wednesday, March 20, 2013

slide-46
SLIDE 46

Thanks!

  • http://pedestal.io
  • http://thinkrelevance.com

46

Wednesday, March 20, 2013