fyrehose 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|