summaryrefslogtreecommitdiffstats
path: root/README.md
blob: 93e2070875d7ad11eeb32da8e94a32dd0cd33f37 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
Bullet
======

Bullet is a Cowboy handler and associated Javascript library for
maintaining a persistent connection to the server irregardless of
the browser used and the technologies available.

Bullet defines a common interface both client and server-side to
facilitate the handling of such connections. Bullet also takes care
of reconnecting automatically when the connection is lost, and of
the optional heartbeat managed client-side.

Today Bullet only supports websocket and long-polling transports.

Cowboy handler
--------------

Similar to websocket handlers, you need to define 4 functions.
A very simple bullet handler would look like the following:

``` erlang
-module(stream_handler).
-export([init/4, stream/3, info/3, terminate/2]).

init(_Transport, Req, _Opts, _Active) ->
	{ok, Req, undefined_state}.

stream(Data, Req, State) ->
	{reply, Data, Req, State}.

info(_Info, Req, State) ->
	{ok, Req, State}.

terminate(_Req, _State) ->
	ok.
```

Of note is that the init/4 and terminate/2 functions are called
everytime a connection is made or closed, respectively, which can
happen many times over the course of a bullet connection's life,
as Bullet will reconnect everytime it detects a disconnection.

Note that you do not need to handle a heartbeat server-side, it
is automatically done when needed by the Bullet client as explained
later in this document.

You might have noticed the odd Active argument to init/4. It
indicates what type of connection we have. When Active == false,
we have a temporary connection that only allows one reply before
terminating. When Active == true, the connection allows any number
of replies. You can use this information to inform your session
process that it should send only 1 message, in the case of
Active == false, or that it can send messages whenever in the
case of Active == true.

You would typically use init/4 to inform your session process
that it can send you messages. In the same manner you can use
terminate/2 to inform it that the connection is going down.

Bullet handlers should only contain transport related code,
logic should be done in your session process if any, or other
parts of your application. Bullet processes should be considered
temporary as you never know when a connection is going to close
and therefore lose your State.

Client-side javascript
----------------------

Bullet requires the jQuery library to be used. Initializing a
bullet connection is quite simple and can be done directly from
a document.ready function like this:

``` js
$(document).ready(function(){
	var bullet = $.bullet(stream);
	bullet.onopen = function(){
		console.log('WebSocket: opened');
	};
	bullet.onclose = function(){
		console.log('WebSocket: closed');
	};
	bullet.onmessage = function(e){
		alert(e.data);
	};
	bullet.onheartbeat = function(){
		bullet.send('ping');
	}
});
```

Bullet works especially well when it is used to send JSON data
formatted with the jQuery JSON plugin.

``` js
bullet.send($.toJSON({type: 'event', data: 'hats!'}));
```

When receiving JSON you would typically receive a list of events,
in which case your onmessage handler can look like this, assuming
you previously defined a handlers function array for all your events:

``` js
	bullet.onmessage = function(e){
		var obj = $.parseJSON(e.data);
		for (i = 0; i < obj.length; i++){
			handlers[obj[i].type](obj[i]);
		}
	};
```