fyrehose 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitkeep +0 -0
- data/fyrehose.gemspec +20 -0
- data/lib/fyrehose/input_stream.rb +107 -0
- data/lib/fyrehose/protocol_error.rb +19 -0
- data/lib/fyrehose/reactor.rb +59 -0
- data/lib/fyrehose.rb +2 -0
- metadata +52 -0
data/.gitkeep
ADDED
File without changes
|
data/fyrehose.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "fyrehose"
|
6
|
+
s.version = "0.0.1"
|
7
|
+
s.date = Date.today.to_s
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Paul Asmuth"]
|
10
|
+
s.email = ["paul@paulasmuth.com"]
|
11
|
+
s.homepage = "http://github.com/paulasmuth/fyrehose"
|
12
|
+
s.summary = %q{ruby client for the fyrehose pub/sub protocol}
|
13
|
+
s.description = %q{ruby client for the fyrehose pub/sub protocol}
|
14
|
+
|
15
|
+
s.licenses = ["MIT"]
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n") - [".gitignore", ".rspec", ".travis.yml"]
|
18
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module Fyrehose
|
2
|
+
class InputStream
|
3
|
+
|
4
|
+
attr_accessor :state, :buf, :pos
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@state = -7
|
8
|
+
@pos = 0
|
9
|
+
@buf = ""
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(chunk)
|
13
|
+
buf << chunk
|
14
|
+
end
|
15
|
+
|
16
|
+
def each
|
17
|
+
trim = 0
|
18
|
+
|
19
|
+
while pos < buf.size do
|
20
|
+
case state
|
21
|
+
|
22
|
+
when -7
|
23
|
+
self.state += 1
|
24
|
+
type = nil
|
25
|
+
txid = ""
|
26
|
+
channel = ""
|
27
|
+
len_or_flags = ""
|
28
|
+
body = ""
|
29
|
+
next
|
30
|
+
|
31
|
+
when -6
|
32
|
+
raise ProtocolError if buf[pos] != "#"
|
33
|
+
self.state += 1
|
34
|
+
|
35
|
+
when -3, -5
|
36
|
+
if buf[pos] == " "
|
37
|
+
self.state += 1
|
38
|
+
else
|
39
|
+
txid << buf[pos] if state == -5
|
40
|
+
channel << buf[pos] if state == -3
|
41
|
+
end
|
42
|
+
|
43
|
+
when -4
|
44
|
+
if buf[pos] == "$"
|
45
|
+
type = :ack
|
46
|
+
self.state = -1
|
47
|
+
elsif buf[pos] == "@"
|
48
|
+
self.state += 1
|
49
|
+
else
|
50
|
+
raise ProtocolError
|
51
|
+
end
|
52
|
+
|
53
|
+
when -2
|
54
|
+
self.state += 1
|
55
|
+
if buf[pos] == "*"
|
56
|
+
type = :data
|
57
|
+
elsif buf[pos] == "+"
|
58
|
+
type = :flags
|
59
|
+
else
|
60
|
+
raise ProtocolError
|
61
|
+
end
|
62
|
+
|
63
|
+
when -1
|
64
|
+
if buf[pos] == " " || buf[pos] == "\n"
|
65
|
+
len_or_flags = len_or_flags.to_i
|
66
|
+
if type == :data
|
67
|
+
self.state = len_or_flags
|
68
|
+
else
|
69
|
+
self.state += 1
|
70
|
+
next
|
71
|
+
end
|
72
|
+
else
|
73
|
+
len_or_flags << buf[pos]
|
74
|
+
end
|
75
|
+
|
76
|
+
when 0
|
77
|
+
yield({
|
78
|
+
:type => type,
|
79
|
+
:txid => txid,
|
80
|
+
:channel => channel,
|
81
|
+
:flags => len_or_flags,
|
82
|
+
:body => body
|
83
|
+
})
|
84
|
+
trim = pos + 1
|
85
|
+
self.state = -7
|
86
|
+
|
87
|
+
else
|
88
|
+
self.state -= 1
|
89
|
+
body << buf[pos]
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
self.pos += 1
|
94
|
+
end
|
95
|
+
|
96
|
+
if trim > 0
|
97
|
+
self.pos -= trim
|
98
|
+
self.buf = self.buf[trim..-1]
|
99
|
+
end
|
100
|
+
|
101
|
+
rescue Fyrehose::ProtocolError => e
|
102
|
+
raise Fyrehose::ProtocolError.new(self.buf, self.pos)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fyrehose
|
2
|
+
class ProtocolError < StandardError
|
3
|
+
|
4
|
+
INFO_SIZE = 30
|
5
|
+
|
6
|
+
def initialize(buf=nil, pos=nil)
|
7
|
+
return unless buf
|
8
|
+
offset = [0, pos - (INFO_SIZE / 2)].max
|
9
|
+
@info = "\n => "
|
10
|
+
@info << buf[offset..offset + INFO_SIZE].gsub("\n", " ")
|
11
|
+
@info << "\n#{" " * (pos - offset + 7)}^\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"invalid token#{@info}"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "eventmachine"
|
2
|
+
|
3
|
+
class Fyrehose::Reactor < EventMachine::Connection
|
4
|
+
|
5
|
+
def self.run(host, port, opts = {}, &block)
|
6
|
+
unless block
|
7
|
+
raise "missing proc{ |channel,data| } for #run"
|
8
|
+
end
|
9
|
+
|
10
|
+
EventMachine.run do
|
11
|
+
reactor = EventMachine.connect(host, port, Fyrehose::Reactor)
|
12
|
+
reactor.instance_eval(&block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_init
|
17
|
+
@input_stream = Fyrehose::InputStream.new
|
18
|
+
@callbacks = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def deliver(channel, data)
|
22
|
+
send_data("##{next_txid} @#{channel} *#{data.size} #{data}\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_flags(channel, flags)
|
26
|
+
send_data("##{next_txid} @#{channel} +#{flags}\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def subscribe(channel)
|
30
|
+
set_flags(channel, 1)
|
31
|
+
end
|
32
|
+
|
33
|
+
def unsubscribe(channel)
|
34
|
+
set_flags(channel, 0)
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_message(&block)
|
38
|
+
@callbacks << block
|
39
|
+
end
|
40
|
+
|
41
|
+
def receive_data(chunk)
|
42
|
+
@input_stream << chunk
|
43
|
+
|
44
|
+
@input_stream.each do |msg|
|
45
|
+
next unless msg[:type] == :data
|
46
|
+
|
47
|
+
@callbacks.each do |block|
|
48
|
+
block.call(msg[:channel], msg[:body])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def next_txid
|
56
|
+
rand(8**32).to_s(36)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/fyrehose.rb
ADDED
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fyrehose
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Asmuth
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-03 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ruby client for the fyrehose pub/sub protocol
|
15
|
+
email:
|
16
|
+
- paul@paulasmuth.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitkeep
|
22
|
+
- fyrehose.gemspec
|
23
|
+
- lib/fyrehose.rb
|
24
|
+
- lib/fyrehose/input_stream.rb
|
25
|
+
- lib/fyrehose/protocol_error.rb
|
26
|
+
- lib/fyrehose/reactor.rb
|
27
|
+
homepage: http://github.com/paulasmuth/fyrehose
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.24
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: ruby client for the fyrehose pub/sub protocol
|
52
|
+
test_files: []
|