Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add a bullet clock example

  • Loading branch information...
commit 6f17bb1455574012b4a15ad780585f964d85b7f9 1 parent ffde065
Loïc Hoguin essen authored
19 examples/clock/README.md
View
@@ -0,0 +1,19 @@
+Bullet Clock
+============
+
+To compile this example you need rebar in your PATH.
+
+Type the following command:
+```
+$ rebar get-deps compile
+```
+
+You can then start the Erlang node with the following command:
+```
+./start.sh
+```
+
+Then point your browser to the indicated URL.
+
+You can interrupt temporarily the node to check that Bullet
+properly reconnects when something happens.
4 examples/clock/rebar.config
View
@@ -0,0 +1,4 @@
+{deps, [
+ {bullet, ".*",
+ {git, "git://github.com/extend/bullet.git", "master"}}
+]}.
15 examples/clock/src/clock.app.src
View
@@ -0,0 +1,15 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+{application, clock, [
+ {description, "Bullet clock example."},
+ {vsn, "1"},
+ {modules, []},
+ {registered, []},
+ {applications, [
+ kernel,
+ stdlib,
+ cowboy
+ ]},
+ {mod, {clock_app, []}},
+ {env, []}
+]}.
24 examples/clock/src/clock.erl
View
@@ -0,0 +1,24 @@
+%% Copyright (c) 2012, Loïc Hoguin <essen@ninenines.eu>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(clock).
+
+%% API.
+-export([start/0]).
+
+%% API.
+
+start() ->
+ ok = application:start(cowboy),
+ ok = application:start(clock).
33 examples/clock/src/clock_app.erl
View
@@ -0,0 +1,33 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @private
+-module(clock_app).
+-behaviour(application).
+
+%% API.
+-export([start/2]).
+-export([stop/1]).
+
+%% API.
+
+start(_Type, _Args) ->
+ Dispatch = [
+ {'_', [
+ {[], toppage_handler, []},
+ {[<<"bullet">>], bullet_handler, [{handler, stream_handler}]},
+ {[<<"static">>, '...'], cowboy_http_static, [
+ {directory, {priv_dir, bullet, []}},
+ {mimetypes, [
+ {<<".js">>, [<<"application/javascript">>]}
+ ]}
+ ]}
+ ]}
+ ],
+ {ok, _} = cowboy:start_listener(http, 100,
+ cowboy_tcp_transport, [{port, 8080}],
+ cowboy_http_protocol, [{dispatch, Dispatch}]
+ ),
+ clock_sup:start_link().
+
+stop(_State) ->
+ ok.
23 examples/clock/src/clock_sup.erl
View
@@ -0,0 +1,23 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @private
+-module(clock_sup).
+-behaviour(supervisor).
+
+%% API.
+-export([start_link/0]).
+
+%% supervisor.
+-export([init/1]).
+
+%% API.
+
+-spec start_link() -> {ok, pid()}.
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% supervisor.
+
+init([]) ->
+ Procs = [],
+ {ok, {{one_for_one, 10, 10}, Procs}}.
36 examples/clock/src/stream_handler.erl
View
@@ -0,0 +1,36 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @doc Stream handler for clock synchronizing.
+-module(stream_handler).
+
+-export([init/4]).
+-export([stream/3]).
+-export([info/3]).
+-export([terminate/2]).
+
+-define(PERIOD, 1000).
+
+init(_Transport, Req, _Opts, _Active) ->
+ io:format("bullet init~n"),
+ _ = erlang:send_after(?PERIOD, self(), refresh),
+ {ok, Req, undefined}.
+
+stream(<<"ping">>, Req, State) ->
+ io:format("ping received~n"),
+ {reply, <<"pong">>, Req, State};
+stream(Data, Req, State) ->
+ io:format("stream received ~s~n", [Data]),
+ {ok, Req, State}.
+
+info(refresh, Req, State) ->
+ _ = erlang:send_after(?PERIOD, self(), refresh),
+ DateTime = cowboy_clock:rfc1123(),
+ io:format("clock refresh timeout: ~s~n", [DateTime]),
+ {reply, DateTime, Req, State};
+info(Info, Req, State) ->
+ io:format("info received ~p~n", [Info]),
+ {ok, Req, State}.
+
+terminate(_Req, _State) ->
+ io:format("bullet terminate~n"),
+ ok.
60 examples/clock/src/toppage_handler.erl
View
@@ -0,0 +1,60 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @doc Main page of the clock application.
+-module(toppage_handler).
+
+-export([init/3]).
+-export([handle/2]).
+-export([terminate/2]).
+
+init(_Transport, Req, []) ->
+ {ok, Req, undefined}.
+
+handle(Req, State) ->
+ Body = <<"
+<!DOCTYPE html>
+<html lang=\"en\">
+<head>
+ <meta charset=\"utf-8\">
+ <title>Bullet Clock</title>
+</head>
+
+<body>
+ <p>Connection status: <span id=\"status\">bullet not started</span></p>
+ <p>Current time: <span id=\"time\">unknown</span></p>
+
+ <script
+ src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\">
+ </script>
+ <script src=\"/static/bullet.js\"></script>
+ <script type=\"text/javascript\">
+// <![CDATA[
+$(document).ready(function(){
+ var bullet = $.bullet('ws://localhost:8080/bullet');
+ bullet.onopen = function(){
+ $('#status').text('online');
+ };
+ bullet.ondisconnect = function(){
+ $('#status').text('offline');
+ };
+ bullet.onmessage = function(e){
+ if (e.data != 'pong'){
+ $('#time').text(e.data);
+ }
+ };
+ bullet.onheartbeat = function(){
+ console.log('ping');
+ bullet.send('ping');
+ }
+});
+// ]]>
+ </script>
+</body>
+</html>
+">>,
+ {ok, Req2} = cowboy_http_req:reply(200, [{'Content-Type', <<"text/html">>}],
+ Body, Req),
+ {ok, Req2, State}.
+
+terminate(_Req, _State) ->
+ ok.
3  examples/clock/start.sh
View
@@ -0,0 +1,3 @@
+#!/bin/sh
+erl -pa ebin deps/*/ebin -s clock \
+ -eval "io:format(\"Point your browser at http://localhost:8080~n\")."
Please sign in to comment.
Something went wrong with that request. Please try again.