The Workerless Pattern

Who am I?

What am I talking about?

  • The Worker Pattern
  • The Workerless Pattern
  • Code Samples

The Worker Pattern

The Worker Pattern

The Worker Pattern Concepts

Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Worker Pattern Example

The Good Stuff

The Not-so-good Stuff

The Workerless Pattern

The Workerless Pattern Concepts

Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Workerless Pattern Example

The Good Stuff

The Not-so-good Stuff

Code

Skeleton Page

<h1>Node Worker Patter</h1>

<div id="a">
  <img src="/images/spinner.gif" />
</div>

<div id="b">
  <img src="/images/spinner.gif" />
</div>

<div id="c">
  <img src="/images/spinner.gif" />
</div>

<script type="text/coffeescript" src="/javascripts/client.coffee"></script>

Client-side Coffeescript

makeRequest = (url, callback) ->
  $.ajax
    url: url
    success: (data, status, request) ->
      callback(data)
    error: (request, status) ->
      console.log(status)

$ ->
  makeRequest '/fragment/a', (content) ->
    $('#a').replaceWith(content)

  makeRequest '/fragment/b', (content) ->
    $('#b').replaceWith(content)

  makeRequest '/fragment/c', (content) ->
    $('#c').replaceWith(content)

Server-side Coffeescript

express = require "express"
externalApi = require "./externalApi"

app = module.exports = express.createServer()

app.get "/", (req, res) ->
  res.render "index", {}

app.get "/fragment/:fragmentName", (req, res) ->
  query = req.params.fragmentName

  externalApi.slowFind query, (err, result) ->
    res.render "fragment",
      fragmentId: result
      fragmentContent: result
      layout: false

app.listen 3000
console.log "Express server listening on port %d", app.address().port

External API

cacher = require './cacher'

performSlowExternalCall = (query, callback) ->
  timeout = Math.floor(Math.random() * 3001)
  setTimeout ->
    callback("result for #{query}")
  , timeout

slowFind = (query, callback) ->
  cacher.performCached
    query: query
    hit: (value) ->
      callback null, value
    miss: (cacheResultCallback) ->
      performSlowExternalCall query, (result) ->
        cacheResultCallback(result)

exports.slowFind = slowFind

Cacher

EventEmitter = require('events').EventEmitter
redis = require "./redisClient"
client = redis.namespacedClient "worker"

class Cacher extends EventEmitter
  constructor: (options) ->
    @query = options.query
    @on 'hit', options.hit
    @on 'miss', options.miss

  perform: ->
    client.get @query, (err, result) =>
      if result?
        @emit 'hit', result
      else
        @emit 'miss', (result) =>
          client.setWithExpiration @query, result, (err, setResult) =>
            @emit 'hit', result

exports.Cacher = Cacher

exports.performCached = (options) ->
  cacher = new Cacher options
  cacher.perform()

Demo

More Info

Q & A

#

/