Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SpreeConf DC 2013: Introducing the Spree Integrator

SpreeConf DC 2013: Introducing the Spree Integrator

A detailed look at the first Spree Integrator release.

Brian Quinn

May 21, 2013
Tweet

More Decks by Brian Quinn

Other Decks in Technology

Transcript

  1. Spree Integrator

    View full-size slide

  2. Brian Quinn
    CTO & Co-founder of Spree Commerce, Inc.
    github.com/bdq
    twitter.com/briandq

    View full-size slide

  3. What is the integrator?

    View full-size slide

  4. x x x
    x
    x x
    x
    x
    x

    View full-size slide

  5. x x x
    x
    x x
    x
    x
    x
    x

    View full-size slide

  6. x x x
    x
    x x
    x
    x
    x
    x x

    View full-size slide

  7. x x x
    x
    x x
    x
    x
    x
    x x

    View full-size slide

  8. x x x x
    x
    x x
    x
    x
    x
    x x

    View full-size slide

  9. bingo!
    x x x x
    x
    x x
    x
    x
    x
    x x

    View full-size slide

  10. “Messaging System”

    View full-size slide

  11. Code name: Augury

    View full-size slide

  12. TM & © Wizards of the Coast

    View full-size slide

  13. Integrator
    Overview

    View full-size slide

  14. Spree Store Integrator
    Overview

    View full-size slide

  15. Spree Store Integrator
    Overview

    View full-size slide

  16. Spree Store Integrator
    Mandrill
    NetSuite
    Shipwire
    Custom
    Overview

    View full-size slide

  17. Spree Store Integrator
    Mandrill
    NetSuite
    Shipwire
    Custom
    SendGrid
    Xero
    Amazon
    Custom
    So
    Ne
    E
    Cu
    Overview

    View full-size slide

  18. Orders Products
    Users
    Overview

    View full-size slide

  19. Orders Products
    Users
    Payments
    Shipments
    Overview

    View full-size slide

  20. Orders Products
    Users
    Stock
    Payments
    Shipments
    Overview

    View full-size slide

  21. My Spree Store
    ✔ Mandrill for transactional emails
    ✔ Shipwire for drop shipping
    ✔ Netsuite for accounting
    ✔ MixPanel for analytics

    View full-size slide

  22. Spree Integrator
    Mandrill
    Endpoint
    Overview

    View full-size slide

  23. Spree Integrator
    orders updated since (timestamp)
    Mandrill
    Endpoint
    Overview

    View full-size slide

  24. Spree Integrator
    orders updated since (timestamp)
    updated orders
    Mandrill
    Endpoint
    Overview

    View full-size slide

  25. Spree Integrator
    orders updated since (timestamp)
    updated orders
    Mandrill
    Endpoint
    detect new orders
    Overview

    View full-size slide

  26. Spree Integrator
    orders updated since (timestamp)
    updated orders
    Mandrill
    Endpoint
    send order confirmation email
    detect new orders
    Overview
    confirmation

    View full-size slide

  27. Spree Integrator
    orders updated since (timestamp)
    updated orders
    confirmation
    Overview

    View full-size slide

  28. Spree Integrator
    orders updated since (timestamp)
    updated orders
    send shipment to fulfillment
    detect ready shipments
    confirmation
    Overview
    Shipwire
    Endpoint

    View full-size slide

  29. Spree Integrator
    Shipwire
    Endpoint
    Overview

    View full-size slide

  30. Spree Integrator
    poll for shipments (bookmark)
    Shipwire
    Endpoint
    Overview

    View full-size slide

  31. Spree Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    Overview

    View full-size slide

  32. Spree Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    update shipment state + tracking
    Overview

    View full-size slide

  33. Spree Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    update shipment state + tracking
    confirmation
    Overview

    View full-size slide

  34. Overview
    Spree Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    update shipment state + tracking
    confirmation

    View full-size slide

  35. Overview
    Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    + tracking
    Mandrill
    Endpoint

    View full-size slide

  36. Overview
    Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    + tracking
    Mandrill
    Endpoint

    View full-size slide

  37. Overview
    Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    + tracking
    Mandrill
    Endpoint
    send shipment notification email

    View full-size slide

  38. Overview
    Integrator
    poll for shipments (bookmark)
    new shipments
    Shipwire
    Endpoint
    + tracking
    Mandrill
    Endpoint
    send shipment notification email
    confirmation

    View full-size slide

  39. order:new
    send order
    confirmation
    email

    View full-size slide

  40. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)

    View full-size slide

  41. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment

    View full-size slide

  42. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order

    View full-size slide

  43. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order
    update accounts
    with order

    View full-size slide

  44. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order
    update accounts
    with order
    subscribe customer
    to mailing list

    View full-size slide

  45. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order
    update accounts
    with order
    subscribe customer
    to mailing list
    watch for
    fulfillment
    notifications

    View full-size slide

  46. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order
    update accounts
    with order
    subscribe customer
    to mailing list
    watch for
    fulfillment
    notifications
    decrease
    stock
    levels

    View full-size slide

  47. order:new
    send order
    confirmation
    email
    capture
    payment
    (if stock available)
    send shipment
    to fulfillment
    update analytics
    with order
    update accounts
    with order
    subscribe customer
    to mailing list
    watch for
    fulfillment
    notifications
    send shipment
    notification
    email
    decrease
    stock
    levels

    View full-size slide

  48. Message Flow

    View full-size slide

  49. MSG
    Message Flow

    View full-size slide

  50. MSG
    Incoming
    Queue
    Message Flow

    View full-size slide

  51. MSG
    Incoming
    Queue Router
    Message Flow

    View full-size slide

  52. MSG
    Incoming
    Queue Router
    Message Flow

    View full-size slide

  53. MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Message Flow

    View full-size slide

  54. MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue
    Message Flow

    View full-size slide

  55. order:new
    Message Flow
    MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue

    View full-size slide

  56. order:new
    1 x order:new
    Message Flow
    MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue

    View full-size slide

  57. order:new
    1 x order:new
    order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow
    MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue

    View full-size slide

  58. order:new
    1 x order:new
    order:new
    - Mandrill
    - NetSuite
    - MixPanel
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow
    MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue

    View full-size slide

  59. Accepted
    Queue
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  60. Accepted
    Queue Dispatcher
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  61. Accepted
    Queue Dispatcher
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  62. Accepted
    Queue Dispatcher
    Mandrill
    order:new
    1
    MixPanel
    order:new
    3
    NetSuite
    order:new 2
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  63. Accepted
    Queue Dispatcher
    Mandrill
    order:new
    1
    MixPanel
    order:new
    3
    NetSuite
    order:new 2
    200: success
    200: success
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  64. Accepted
    Queue Dispatcher
    Mandrill
    order:new
    1
    MixPanel
    order:new
    3
    NetSuite
    order:new 2
    200: success
    200: success
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  65. Accepted
    Queue Dispatcher
    Mandrill
    order:new
    1
    MixPanel
    order:new
    3
    NetSuite
    order:new 2
    200: success
    200: success
    500: fail!
    3 x order:new
    - Mandrill
    - NetSuite
    - MixPanel
    Message Flow

    View full-size slide

  66. Accepted
    Queue Dispatcher NetSuite
    1 x order:new
    - NetSuite
    Message Flow

    View full-size slide

  67. Accepted
    Queue Dispatcher NetSuite
    order:new 2
    500: fail!
    1 x order:new
    - NetSuite
    order:new 2
    500: fail!
    order:new 2
    500: fail!
    order:new 2
    200: success
    Message Flow

    View full-size slide

  68. Accepted
    Queue Dispatcher NetSuite
    order:new 2
    500: fail!
    1 x order:new
    - NetSuite
    order:new 2
    500: fail!
    order:new 2
    500: fail!
    order:new 2
    200: success
    Message Flow

    View full-size slide

  69. Pull
    Spree - orders, products, users, stock transfers

    View full-size slide

  70. Pull
    Spree - orders, products, users, stock transfers
    3rd Parties - shipments, payments, purchase orders

    View full-size slide

  71. order
    Have we
    seen this
    order
    before?

    View full-size slide

  72. order
    Have we
    seen this
    order
    before?
    no: push
    message
    order:new

    View full-size slide

  73. order
    Have we
    seen this
    order
    before?
    yes Generate diff
    no: push
    message
    order:new

    View full-size slide

  74. order
    Have we
    seen this
    order
    before?
    yes Generate diff
    no: push
    message
    order:new
    Order has
    really
    changed?

    View full-size slide

  75. order
    Have we
    seen this
    order
    before?
    yes Generate diff
    yes: push
    message
    order:updated
    no: push
    message
    order:new
    Order has
    really
    changed?

    View full-size slide

  76. Why pull not push?

    View full-size slide

  77. Why pull not push?
    •Less dependencies on the client side.

    View full-size slide

  78. Why pull not push?
    •Less dependencies on the client side.
    •We can poll new collections easier.

    View full-size slide

  79. Why pull not push?
    •Less dependencies on the client side.
    •We can poll new collections easier.
    •We control the rate of flow.

    View full-size slide

  80. Why pull not push?
    •Less dependencies on the client side.
    •We can poll new collections easier.
    •We control the rate of flow.
    •Nobody has needed push yet.

    View full-size slide

  81. Order V1
    parent: null
    new
    Versioning

    View full-size slide

  82. Order V1
    parent: null
    new
    send order
    confirmation
    email
    Versioning

    View full-size slide

  83. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    send order
    confirmation
    email
    Versioning

    View full-size slide

  84. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    send order
    confirmation
    email
    capture
    payment
    Versioning

    View full-size slide

  85. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    Order V3
    parent: V2
    update
    send order
    confirmation
    email
    capture
    payment
    Versioning

    View full-size slide

  86. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    Order V3
    parent: V2
    update
    send order
    confirmation
    email
    capture
    payment
    send
    shipment to
    fulfillment
    Versioning

    View full-size slide

  87. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    Order V3
    parent: V2
    update update
    Order V4
    parent: V3
    send order
    confirmation
    email
    capture
    payment
    send
    shipment to
    fulfillment
    Versioning

    View full-size slide

  88. Order V1
    parent: null
    Order V2
    parent: V1
    update
    new
    Order V3
    parent: V2
    update update
    Order V4
    parent: V3
    send order
    confirmation
    email
    capture
    payment
    send
    shipment to
    fulfillment
    send
    shipment
    confirmation
    Versioning

    View full-size slide

  89. Versioning
    Implying events

    View full-size slide

  90. Order V1
    state: complete
    Versioning

    View full-size slide

  91. Order V1
    state: complete
    Versioning
    update
    Order V2
    state: canceled

    View full-size slide

  92. Order V1
    state: complete
    Versioning
    update
    Order V2
    state: canceled
    push
    message
    order:update

    View full-size slide

  93. Order V1
    state: complete
    Versioning
    update
    Order V2
    state: canceled
    order:canceled
    push
    message
    order:update

    View full-size slide

  94. Asynchronous

    View full-size slide

  95. Messages (8)

    View full-size slide

  96. Messages (10)

    View full-size slide

  97. Architecture

    View full-size slide

  98. Consumers
    Internal

    View full-size slide

  99. Consumers
    Internal
    External

    View full-size slide

  100. Consumers
    Internal
    External (endpoints)

    View full-size slide

  101. Core
    Fully Managed SaaS

    View full-size slide

  102. Endpoints
    SaaS & Self-managed

    View full-size slide

  103. Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue
    Architecture

    View full-size slide

  104. Managed
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue
    Architecture

    View full-size slide

  105. Accepted
    Queue Dispatcher
    Mandrill
    MixPanel
    NetSuite
    Architecture

    View full-size slide

  106. Managed
    Accepted
    Queue Dispatcher
    Mandrill
    MixPanel
    NetSuite
    Architecture

    View full-size slide

  107. Managed
    Self hosted
    Architecture
    Accepted
    Queue Dispatcher
    Mandrill
    NetSuite
    MixPanel

    View full-size slide

  108. Self hosted
    Managed
    Architecture
    Accepted
    Queue Dispatcher
    Mandrill
    MixPanel
    NetSuite

    View full-size slide

  109. Message Basics

    View full-size slide

  110. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": {
    5 "id": 15913,
    6 "amount": "129.57",
    7 "state": "pending",
    8 "payment_method": {
    9 "id": 931422127,
    10 "name": "Credit Card",
    11 "environment": "production"
    12 }
    13 }
    14 }
    15 }
    Message: Overview

    View full-size slide

  111. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": {
    5 "id": 15913,
    6 "amount": "129.57",
    7 "state": "pending",
    8 "payment_method": {
    9 "id": 931422127,
    10 "name": "Credit Card",
    11 "environment": "production"
    12 }
    13 }
    14 }
    15 }
    Message: Overview

    View full-size slide

  112. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": {
    5 "id": 15913,
    6 "amount": "129.57",
    7 "state": "pending",
    8 "payment_method": {
    9 "id": 931422127,
    10 "name": "Credit Card",
    11 "environment": "production"
    12 }
    13 }
    14 }
    15 }
    Message: Overview

    View full-size slide

  113. Order New order:new
    Order Updated order:updated
    Order Cancelled order:cancelled

    View full-size slide

  114. Order New order:new
    Order Updated order:updated
    Order Cancelled order:cancelled
    Shipment Confirmation shipment:confirmation
    Shipment Ready shipment:ready
    Shipment Rejected shipment:rejected

    View full-size slide

  115. Order New order:new
    Order Updated order:updated
    Order Cancelled order:cancelled
    Payment Ready payment:ready
    Shipment Confirmation shipment:confirmation
    Shipment Ready shipment:ready
    Payment Captured payment:captured
    Shipment Rejected shipment:rejected
    Payment Declined payment:declined

    View full-size slide

  116. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": { ... },
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 ...
    9 },
    10 "current": {
    11 "number": "R123123123",
    12 ...
    13 },
    14 }
    15 }
    16 }
    Message: Payload

    View full-size slide

  117. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": { ... },
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 ...
    9 },
    10 "current": {
    11 "number": "R123123123",
    12 ...
    13 },
    14 }
    15 }
    16 }
    Message: Payload

    View full-size slide

  118. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": { ... },
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 ...
    9 },
    10 "current": {
    11 "number": "R123123123",
    12 ...
    13 },
    14 }
    15 }
    16 }
    Message: Payload

    View full-size slide

  119. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": { ... },
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 ...
    9 },
    10 "current": {
    11 "number": "R123123123",
    12 ...
    13 },
    14 }
    15 }
    16 }
    Message: Payload

    View full-size slide

  120. 1 {
    2 "message": "payment:ready",
    3 "payload": {
    4 "payment": { ... },
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 ...
    9 },
    10 "current": {
    11 "number": "R123123123",
    12 ...
    13 },
    14 }
    15 }
    16 }
    Message: Payload

    View full-size slide

  121. Custom Endpoints

    View full-size slide

  122. Message: message_id
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "payment:ready",
    4 "payload": {
    5 "payment": { ... },
    6 "order": {
    7 "actual": {
    8 "number": "R123123123",
    9 ...
    10 },
    11 "current": {
    12 "number": "R123123123",
    13 ...
    14 },
    15 }
    16 }
    ...

    View full-size slide

  123. Message: message_id
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "payment:ready",
    4 "payload": {
    5 "payment": { ... },
    6 "order": {
    7 "actual": {
    8 "number": "R123123123",
    9 ...
    10 },
    11 "current": {
    12 "number": "R123123123",
    13 ...
    14 },
    15 }
    16 }
    ...

    View full-size slide

  124. Dispatcher Endpoint
    order:new

    View full-size slide

  125. Dispatcher Endpoint
    POST JSON
    { ... }
    order:new

    View full-size slide

  126. Dispatcher Endpoint
    {message_id: x}
    HTTP: 200
    POST JSON
    { ... }
    order:new

    View full-size slide

  127. Dispatcher Endpoint
    {message_id: x}
    HTTP: 200
    POST JSON
    { ... }
    order:new
    --------------- ✓

    View full-size slide

  128. Response: Basic
    1 {
    2 "message_id": "518783ac7575e46507000001"
    3 }

    View full-size slide

  129. Basic Example

    View full-size slide

  130. Endpoint: Sinatra
    1 require 'sinatra'
    2 require 'sinatra/json'
    3
    4 class SimpleEndpoint < Sinatra::Base
    5 helpers Sinatra::JSON
    6
    7 post '/' do
    8 message = JSON.parse(request.body.read)
    9
    10 json 'message_id' => message['message_id']
    11 end
    12 end

    View full-size slide

  131. Endpoint: Sinatra
    1 require 'sinatra'
    2 require 'sinatra/json'
    3
    4 class SimpleEndpoint < Sinatra::Base
    5 helpers Sinatra::JSON
    6
    7 post '/' do
    8 message = JSON.parse(request.body.read)
    9
    10 json 'message_id' => message['message_id']
    11 end
    12 end

    View full-size slide

  132. Endpoint: Sinatra
    1 require 'sinatra'
    2 require 'sinatra/json'
    3
    4 class SimpleEndpoint < Sinatra::Base
    5 helpers Sinatra::JSON
    6
    7 post '/' do
    8 message = JSON.parse(request.body.read)
    9
    10 json 'message_id' => message['message_id']
    11 end
    12 end
    <- DO INTERESTING THINGS HERE

    View full-size slide

  133. Endpoint: Node.js
    1 var express = require('express');
    2 var app = express();
    3
    4 app.use(express.bodyParser());
    5
    6 app.post('/', function(req, res){
    7 var id = req.body['message_id'];
    8 res.setHeader('Content-Type', 'application/json');
    9 res.end(JSON.stringify({ "mesage_id": id}));
    10 });
    11 app.listen(3000);

    View full-size slide

  134. Endpoint: Node.js
    1 var express = require('express');
    2 var app = express();
    3
    4 app.use(express.bodyParser());
    5
    6 app.post('/', function(req, res){
    7 var id = req.body['message_id'];
    8 res.setHeader('Content-Type', 'application/json');
    9 res.end(JSON.stringify({ "mesage_id": id}));
    10 });
    11 app.listen(3000);

    View full-size slide

  135. 1 2 $message = json_decode(file_get_contents('php://input'));
    3
    4 $response = array(
    5 'message_id' => $message->message_id
    6 );
    7
    8 header('Content-type: application/json');
    9 echo json_encode($response);
    10 ?>
    Endpoint: PHP

    View full-size slide

  136. Endpoint Base
    https://github.com/spree/endpoint_base

    View full-size slide

  137. Example: Endpoint Base
    1 class SimpleEndpoint < EndpointBase
    2 post '/' do
    3 process_result 200, {'message_id' => @message['message_id'] }
    4 end
    5 end

    View full-size slide

  138. Demo Endpoint

    View full-size slide

  139. Demo Endpoint
    Customer stalker endpoint

    View full-size slide

  140. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = 'iQ55...'
    4 c.consumer_secret = 'YQoQ...'
    5 c.oauth_token = '8213...'
    6 c.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  141. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = 'iQ55...'
    4 c.consumer_secret = 'YQoQ...'
    5 c.oauth_token = '8213...'
    6 c.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  142. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = 'iQ55...'
    4 c.consumer_secret = 'YQoQ...'
    5 c.oauth_token = '8213...'
    6 c.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  143. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = 'iQ55...'
    4 c.consumer_secret = 'YQoQ...'
    5 c.oauth_token = '8213...'
    6 c.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  144. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": { ... },
    5 "parameters": [
    6 {
    7 "name": "twitter.consumer_key",
    8 "value": "iQ55k..."
    9 },
    10 {
    11 "name": "twitter.consumer_secret",
    12 "value": "YQoQS..."
    13 }
    14 ]
    15 }
    Message: Parameters

    View full-size slide

  145. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": { ... },
    5 "parameters": [
    6 {
    7 "name": "twitter.consumer_key",
    8 "value": "iQ55k..."
    9 },
    10 {
    11 "name": "twitter.consumer_secret",
    12 "value": "YQoQS..."
    13 }
    14 ]
    15 }
    Message: Parameters

    View full-size slide

  146. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = @config['twitter.consumer_key']
    4 c.consumer_secret = @config['twitter.consumer_secret']
    5 c.oauth_token = @config['twitter.oauth_token']
    6 c.oauth_token_secret = @config['twitter.oauth_token_secret']
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  147. Endpoint: Sinatra
    1 post '/follow' do
    2 Twitter.configure do |c|
    3 c.consumer_key = @config['twitter.consumer_key']
    4 c.consumer_secret = @config['twitter.consumer_secret']
    5 c.oauth_token = @config['twitter.oauth_token']
    6 c.oauth_token_secret = @config['twitter.oauth_token_secret']
    7 end
    8
    9 Twitter.follow(@msg['payload']['order']['actual']['twitter'])
    10
    11 process_result 200, { 'message_id' => @msg[:message_id],
    12 'following' => Twitter.following.map &:name }
    13 end

    View full-size slide

  148. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "parameters": [
    4 {
    5 "name": "last_follower",
    6 "value": "@briandq"
    7 }
    8 ]
    9 }
    Message: Parameters Response

    View full-size slide

  149. “Followed customer on Twitter”

    View full-size slide

  150. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "events": [
    4 {
    5 "code": 200
    6 }
    12 ]
    13 }
    Response: Events

    View full-size slide

  151. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "events": [
    4 {
    5 "code": 200
    6 }
    12 ]
    13 }
    Response: Events

    View full-size slide

  152. Humanizer
    200: "Followed customer on Twitter"

    View full-size slide

  153. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "events": [
    4 {
    5 "code": 200,
    6 "username": "@briandq"
    7 }
    8 ]
    9 }
    Response: Events

    View full-size slide

  154. Humanizer
    200: "Followed {{username}} on Twitter"

    View full-size slide

  155. “Followed @briandq on Twitter”

    View full-size slide

  156. New Messages

    View full-size slide

  157. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "events": [ { "code": 200 } ],
    4 "messages": [
    5 {
    6 "message": "customer:followed",
    7 "payload": {
    8 “username": "@briandq",
    9 }
    10 }
    11 ]
    12 }
    Response: Messages

    View full-size slide

  158. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "events": [ { "code": 200 } ],
    4 "messages": [
    5 {
    6 "message": "customer:followed",
    7 "payload": {
    8 “username": "@briandq",
    9 }
    10 }
    11 ]
    12 }
    Response: Messages

    View full-size slide

  159. Dispatcher Endpoint
    order:new

    View full-size slide

  160. Dispatcher Endpoint
    POST JSON
    { ... }
    order:new

    View full-size slide

  161. Dispatcher Endpoint
    { reason: X }
    HTTP: 500
    POST JSON
    { ... }
    order:new

    View full-size slide

  162. Dispatcher Endpoint
    { reason: X }
    HTTP: 500
    POST JSON
    { ... }
    order:new
    order:new

    attempts: 1
    attempt_at: 14:02

    View full-size slide

  163. Dispatcher Endpoint
    order:new
    order:new

    attempts: 1
    attempt_at: 14:02

    View full-size slide

  164. Dispatcher Endpoint
    { reason: Y }
    HTTP: 500
    POST JSON
    { ... }
    order:new
    order:new

    attempts: 2
    attempt_at: 14:08

    View full-size slide

  165. 1 post '/follow' do
    2 Twitter.configure do |config|
    3 config.consumer_key = 'iQ55...'
    4 config.consumer_secret = 'YQoQ...'
    5 config.oauth_token = '8213...'
    6 config.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 begin
    10 Twitter.follow(@msg['payload']['order']['twitter'])
    11
    12 process_result 200, { 'message_id' => @msg[:message_id],
    13 'following' => Twitter.following.map &:name }
    14 rescue
    15 process_result 500,
    16 { 'username' => @msg['payload']['order']['twitter'] }
    17 end
    18
    19 end
    Endpoint: Sinatra

    View full-size slide

  166. 1 post '/follow' do
    2 Twitter.configure do |config|
    3 config.consumer_key = 'iQ55...'
    4 config.consumer_secret = 'YQoQ...'
    5 config.oauth_token = '8213...'
    6 config.oauth_token_secret = '6Rwn...'
    7 end
    8
    9 begin
    10 Twitter.follow(@msg['payload']['order']['twitter'])
    11
    12 process_result 200, { 'message_id' => @msg[:message_id],
    13 'following' => Twitter.following.map &:name }
    14 rescue
    15 process_result 500,
    16 { 'username' => @msg['payload']['order']['twitter'] }
    17 end
    18
    19 end
    Endpoint: Sinatra

    View full-size slide

  167. Humanizer
    200: "Followed {{username}} on Twitter"
    500: "Failed to follow {{username}} on Twitter"

    View full-size slide

  168. Dispatcher Endpoint
    order:new

    View full-size slide

  169. Dispatcher Endpoint
    POST JSON
    { ... }
    order:new

    View full-size slide

  170. Dispatcher Endpoint
    { delay: n }
    HTTP: 200
    POST JSON
    { ... }
    order:new

    View full-size slide

  171. 1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "delay ": 600,
    4 "update_url": "http://example.com/some/path?value=x"
    5 }
    Response: Delayed

    View full-size slide

  172. Dispatcher Endpoint
    { delay: n }
    HTTP: 200
    POST JSON
    { ... }
    order:new

    View full-size slide

  173. Dispatcher Endpoint
    { delay: n }
    HTTP: 200
    POST JSON
    { ... }
    order:new
    --------------- ✓

    View full-size slide

  174. Dispatcher Endpoint
    { delay: n }
    HTTP: 200
    POST JSON
    { ... }
    order:new
    --------------- ✓
    push
    remote:poll

    View full-size slide

  175. Registering Endpoints

    View full-size slide

  176. Registering Endpoints
    •Message(s)

    View full-size slide

  177. Registering Endpoints
    •Message(s)
    •URL

    View full-size slide

  178. Registering Endpoints
    •Message(s)
    •URL
    •Token

    View full-size slide

  179. Registering Endpoints
    •Message(s)
    •URL
    •Token
    •Parameters

    View full-size slide

  180. Registering Endpoints
    •Message(s)
    •URL
    •Token
    •Parameters
    •Filters

    View full-size slide

  181. Registering Endpoints
    •Message(s)
    •URL
    •Token
    •Parameters
    •Filters
    •Events (keys & details)

    View full-size slide

  182. Registering Endpoints
    •Message(s)
    •URL
    •Token
    •Parameters
    •Filters
    •Events (keys & details)
    •Options

    View full-size slide

  183. Messages
    [‘order:new’, ‘order:updated’, ‘order:canceled’]

    View full-size slide

  184. URL
    SSL Required

    View full-size slide

  185. Filters
    Path
    Operator

    View full-size slide

  186. Filters
    Path
    Operator
    Value

    View full-size slide

  187. Filter: Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "twitter": "@briandq",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }

    View full-size slide

  188. Filter: Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "twitter": "@briandq",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }

    View full-size slide

  189. Filter: Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "twitter": "@briandq",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }
    Path: payload.order.actual.twitter

    View full-size slide

  190. Filter: Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "twitter": "@briandq",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }
    Path: payload.order.actual.twitter
    Operator: is_not

    View full-size slide

  191. Filter: Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "twitter": "@briandq",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }
    Path: payload.order.actual.twitter
    Operator: is_not
    Value: nil

    View full-size slide

  192. MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Message Flow: Filters

    View full-size slide

  193. MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Message Flow: Filters
    Apply Filters

    View full-size slide

  194. MSG
    Incoming
    Queue Router
    Consumer
    Registry
    Accepted
    Queue
    Message Flow: Filters
    Apply Filters

    View full-size slide

  195. Events
    1. Provide human readable logs

    View full-size slide

  196. Events
    1. Provide human readable logs
    2. Prevent duplicate execution

    View full-size slide

  197. Event Key(s)
    Highlights the unique identifier

    View full-size slide

  198. Event: Key Example
    1 {
    2 "message_id": "518783ac7575e46507000001",
    3 "message": "order:new",
    4 "payload": {
    5 "order": {
    6 "actual": {
    7 "number": "R123123123",
    8 "total": "199.99",
    9 "email": "[email protected]",
    10 "line_items": [ ... ]
    11 }
    12 }
    13 }
    Name: order_number
    Path: payload.order.actual.number

    View full-size slide

  199. Event Detail(s)
    Extra data for display

    View full-size slide

  200. What’s planned?

    View full-size slide

  201. Endpoint Hosting

    View full-size slide

  202. Render & Transform

    View full-size slide

  203. Render & Transform

    View full-size slide

  204. Discoverability

    View full-size slide

  205. Self Provisioning

    View full-size slide

  206. Get Started!

    View full-size slide

  207. Guides
    http://edgeguides.spreecommerce.com/integration/

    View full-size slide

  208. Mandrill
    Basic Sinatra Endpoint
    Fully open-source
    https://github.com/spree/mandrill_endpoint

    View full-size slide

  209. Shipwire
    Basic Sinatra Endpoint
    Fully open-source
    https://github.com/spree/shipwire_endpoint

    View full-size slide

  210. QuickBooks
    Delayed Endpoint
    Fully open-source
    https://github.com/spree/quickbooks_endpoint

    View full-size slide

  211. Alexey
    @devilcoders
    Washington
    @huoxito

    View full-size slide