stompserver 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -6
- data/Manifest.txt +25 -7
- data/README.txt +136 -19
- data/Rakefile +8 -8
- data/STATUS +5 -0
- data/bin/stompserver +43 -19
- data/client/README.txt +1 -0
- data/client/both.rb +25 -0
- data/client/consume.rb +14 -0
- data/client/send.rb +17 -0
- data/config/stompserver.conf +11 -0
- data/etc/passwd.example +3 -0
- data/lib/stomp_server.rb +132 -157
- data/lib/stomp_server/protocols/http.rb +128 -0
- data/lib/stomp_server/protocols/stomp.rb +186 -0
- data/lib/stomp_server/queue.rb +140 -0
- data/lib/stomp_server/queue/activerecord_queue.rb +104 -0
- data/lib/stomp_server/queue/ar_message.rb +5 -0
- data/lib/stomp_server/queue/dbm_queue.rb +68 -0
- data/lib/stomp_server/queue/file_queue.rb +47 -0
- data/lib/stomp_server/queue/memory_queue.rb +58 -0
- data/lib/stomp_server/queue_manager.rb +209 -0
- data/lib/stomp_server/stomp_auth.rb +22 -0
- data/lib/{stomp_frame.rb → stomp_server/stomp_frame.rb} +7 -7
- data/lib/stomp_server/stomp_id.rb +21 -0
- data/lib/stomp_server/stomp_user.rb +17 -0
- data/lib/stomp_server/test_server.rb +21 -0
- data/lib/{topic_manager.rb → stomp_server/topic_manager.rb} +14 -2
- data/test/tesly.rb +15 -0
- data/test/test_queue_manager.rb +39 -32
- data/test/test_stomp_frame.rb +3 -16
- data/test/test_topic_manager.rb +3 -4
- data/{test → test_todo}/test_stomp_server.rb +0 -27
- metadata +56 -23
- data/lib/frame_journal.rb +0 -135
- data/lib/queue_manager.rb +0 -81
- data/test/test_frame_journal.rb +0 -14
data/lib/frame_journal.rb
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
# Simple Journal File(s) Manager
|
2
|
-
# You select the directory, and it will collect the messages
|
3
|
-
# The journal file format is:
|
4
|
-
#
|
5
|
-
# Status Byte: 0 - pending, 1 - processed
|
6
|
-
# Frame Size: 4 byte long (network endian - yes I limit my messages to 4G)
|
7
|
-
# Message
|
8
|
-
#
|
9
|
-
# Repeat
|
10
|
-
#
|
11
|
-
# When the size of a journal file exceeds its limit
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
require 'madeleine'
|
15
|
-
require 'madeleine/automatic'
|
16
|
-
|
17
|
-
class MadFrameJournal
|
18
|
-
include Madeleine::Automatic::Interceptor
|
19
|
-
attr_reader :frames
|
20
|
-
automatic_read_only :frames
|
21
|
-
attr_accessor :frame_index
|
22
|
-
automatic_read_only :frame_index
|
23
|
-
attr_accessor :system_id
|
24
|
-
automatic_read_only :system_id
|
25
|
-
|
26
|
-
def initialize
|
27
|
-
@frames = {}
|
28
|
-
@frame_index = 0
|
29
|
-
@system_id = nil
|
30
|
-
end
|
31
|
-
|
32
|
-
def add(msgid, frame)
|
33
|
-
@frames[msgid] = frame
|
34
|
-
end
|
35
|
-
|
36
|
-
def delete(msgid)
|
37
|
-
@frames.delete(msgid)
|
38
|
-
end
|
39
|
-
|
40
|
-
def clear
|
41
|
-
@frames.clear
|
42
|
-
end
|
43
|
-
|
44
|
-
automatic_read_only :lookup
|
45
|
-
def lookup(msgid)
|
46
|
-
@frames[msgid]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class FrameJournal
|
51
|
-
def initialize(directory='frame-journal', snap_freq = 60 * 5)
|
52
|
-
@directory = directory
|
53
|
-
@mad = AutomaticSnapshotMadeleine.new(directory) do
|
54
|
-
MadFrameJournal.new
|
55
|
-
end
|
56
|
-
|
57
|
-
# always snap on startup, in case we had an previous failure
|
58
|
-
@modified = true
|
59
|
-
Thread.new(@mad, snap_freq) do |mad, freq|
|
60
|
-
while true
|
61
|
-
sleep(freq)
|
62
|
-
mad.take_snapshot if @modified
|
63
|
-
@modified = false
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def []=(msgid, frame)
|
69
|
-
@modified = true
|
70
|
-
@mad.system.add(msgid, frame)
|
71
|
-
end
|
72
|
-
|
73
|
-
def [](msgid)
|
74
|
-
@mad.system.lookup(msgid)
|
75
|
-
end
|
76
|
-
|
77
|
-
def delete(msgid)
|
78
|
-
@modified = true
|
79
|
-
@mad.system.delete(msgid)
|
80
|
-
end
|
81
|
-
|
82
|
-
def keys
|
83
|
-
@mad.system.frames.keys
|
84
|
-
end
|
85
|
-
|
86
|
-
def clear
|
87
|
-
@modified = true
|
88
|
-
@mad.system.clear
|
89
|
-
@mad.take_snapshot
|
90
|
-
end
|
91
|
-
|
92
|
-
def index
|
93
|
-
@mad.system.frame_index
|
94
|
-
end
|
95
|
-
|
96
|
-
def next_index
|
97
|
-
@modified = true
|
98
|
-
@mad.system.frame_index += 1
|
99
|
-
end
|
100
|
-
|
101
|
-
def system_id
|
102
|
-
unless name = @mad.system.system_id
|
103
|
-
# todo - grab default name from some place smarter...
|
104
|
-
@modified = true
|
105
|
-
@mad.system.system_id = 'cmastomp'
|
106
|
-
name = @mad.system.system_id
|
107
|
-
end
|
108
|
-
name
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
if __FILE__ == $0
|
113
|
-
fj = FrameJournal.new('fj', 3)
|
114
|
-
until ARGV.empty?
|
115
|
-
case cmd = ARGV.shift
|
116
|
-
when "keys"
|
117
|
-
puts fj.keys.inspect
|
118
|
-
when "dump"
|
119
|
-
fj.keys.each do |key|
|
120
|
-
puts "#{key}: #{fj[key]}"
|
121
|
-
end
|
122
|
-
when "show"
|
123
|
-
key = ARGV.shift
|
124
|
-
puts "#{key}: #{fj[key]}"
|
125
|
-
when "add"
|
126
|
-
key = ARGV.shift
|
127
|
-
val = ARGV.shift
|
128
|
-
fj[key] = val
|
129
|
-
when "sleep"
|
130
|
-
sleep ARGV.shift.to_i
|
131
|
-
when "delete"
|
132
|
-
fj.delete(ARGV.shift)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/lib/queue_manager.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# queue - persistent sent to a single subscriber
|
2
|
-
# queue_monitor - looks, but does not remove from queue
|
3
|
-
|
4
|
-
class QueueManager
|
5
|
-
Struct::new('QueueUser', :user, :ack)
|
6
|
-
|
7
|
-
def initialize(journal)
|
8
|
-
# read journal information
|
9
|
-
@journal = journal
|
10
|
-
@queues = Hash.new { Array.new }
|
11
|
-
@pending = Hash.new { Array.new }
|
12
|
-
@messages = Hash.new { Array.new }
|
13
|
-
|
14
|
-
# recover from previous run
|
15
|
-
msgids = @journal.keys.sort
|
16
|
-
msgids.each do |msgid|
|
17
|
-
sendmsg(@journal[msgid])
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def subscribe(dest, user, use_ack=false)
|
22
|
-
user = Struct::QueueUser.new(user, use_ack)
|
23
|
-
@queues[dest] += [user]
|
24
|
-
|
25
|
-
# TODO handle this is some form of call back
|
26
|
-
# it is quite possible that this could be a lot
|
27
|
-
# of data and block things up.
|
28
|
-
send_backlog(@messages[dest], user)
|
29
|
-
end
|
30
|
-
|
31
|
-
def send_backlog(queue, user)
|
32
|
-
until queue.empty?
|
33
|
-
current = queue.first
|
34
|
-
send_to_user(current, user)
|
35
|
-
queue.shift
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def unsubscribe(topic, user)
|
40
|
-
@queues[topic].delete_if { |u| u.user == user }
|
41
|
-
end
|
42
|
-
|
43
|
-
def ack(user, frame)
|
44
|
-
pending_size = @pending[user].size
|
45
|
-
msgid = frame.headers['message-id']
|
46
|
-
@pending[user].delete_if { |pf| pf.headers['message-id'] == msgid }
|
47
|
-
raise "Message (#{msgid}) not found" if pending_size == @pending[user].size
|
48
|
-
@journal.delete(msgid)
|
49
|
-
end
|
50
|
-
|
51
|
-
def disconnect(user)
|
52
|
-
@queues.each do |dest, queue|
|
53
|
-
queue.delete_if { |qu| qu.user == user }
|
54
|
-
end
|
55
|
-
@pending[user].each do |frame|
|
56
|
-
sendmsg(frame)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def send_to_user(frame, user)
|
61
|
-
if user.ack
|
62
|
-
@pending[user.user] += [frame]
|
63
|
-
else
|
64
|
-
@journal.delete(frame.headers['message-id'])
|
65
|
-
end
|
66
|
-
user.user.send_data(frame.to_s)
|
67
|
-
end
|
68
|
-
|
69
|
-
def sendmsg(frame)
|
70
|
-
frame.command = "MESSAGE"
|
71
|
-
dest = frame.headers['destination']
|
72
|
-
@journal[frame.headers['message-id']] = frame
|
73
|
-
|
74
|
-
if user = @queues[dest].shift
|
75
|
-
send_to_user(frame, user)
|
76
|
-
@queues[dest].push(user)
|
77
|
-
else
|
78
|
-
@messages[dest] += [frame]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
data/test/test_frame_journal.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'frame_journal'
|
2
|
-
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
3
|
-
require 'tesly'
|
4
|
-
|
5
|
-
# how would you test this? It is pretty simple code
|
6
|
-
# based almost completely on Madeleine...
|
7
|
-
class TestFrameJournal < Test::Unit::TestCase
|
8
|
-
def setup
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_something
|
12
|
-
|
13
|
-
end
|
14
|
-
end
|