fmq 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +11 -0
- data/README.txt +17 -18
- data/default-server/config.ru +16 -16
- data/lib/fmq/admin.rb +0 -7
- data/lib/fmq/boot.rb +10 -18
- data/lib/fmq/queue_manager.rb +10 -15
- data/lib/fmq/queues/README.txt +4 -4
- data/lib/fmq/queues/base.rb +2 -1
- data/lib/fmq/queues/file.rb +12 -14
- data/lib/fmq/queues/file_persistent.rb +86 -0
- data/lib/fmq/queues/forward.rb +6 -8
- data/lib/fmq/queues/linked.rb +1 -1
- data/lib/fmq/queues/load_balanced.rb +8 -12
- data/lib/fmq/queues/syncronized.rb +11 -13
- data/lib/fmq/server.rb +0 -7
- data/lib/fmq/version.rb +1 -1
- data/lib/fmq.rb +8 -0
- data/test/test_basic.rb +9 -7
- data/test/test_file_persistent.rb +18 -0
- data/test/test_helper.rb +59 -1
- data/test/test_linked.rb +3 -57
- data/test/test_queue_manager.rb +8 -19
- metadata +15 -2
data/History.txt
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
== 0.3.2 2008-08-28
|
2
|
+
|
3
|
+
* 3 minor changes:
|
4
|
+
* changed the way of the queue manager setup
|
5
|
+
* updated rdoc, readme and website documentaition
|
6
|
+
* added a new queue that persists the messages in the file system
|
7
|
+
* 3 tiny changes:
|
8
|
+
* fixed the fmq logger creation
|
9
|
+
* some fixes to the queue manager and some queues
|
10
|
+
* refactored testing of fifo based queues
|
11
|
+
|
1
12
|
== 0.3.1 2008-08-27
|
2
13
|
|
3
14
|
* 2 minor changes:
|
data/README.txt
CHANGED
@@ -6,8 +6,6 @@ Project github repositiory: git://github.com/threez/fmq.git
|
|
6
6
|
|
7
7
|
== TODO:
|
8
8
|
|
9
|
-
* create full rdoc
|
10
|
-
* support of logging to file
|
11
9
|
* add client apis for other languages
|
12
10
|
* complete unit tests
|
13
11
|
|
@@ -15,21 +13,21 @@ Project github repositiory: git://github.com/threez/fmq.git
|
|
15
13
|
|
16
14
|
The project implements a queue system with a server and some client apis.
|
17
15
|
|
18
|
-
The server is a
|
19
|
-
You can GET, POST, DELETE, HEAD queue
|
20
|
-
The system itself uses a configuration
|
21
|
-
startup or even at runtime. The queue
|
22
|
-
|
16
|
+
The server is a rack server that holds REST-named queues, so that the
|
17
|
+
implemention can be changed rapidly. You can GET, POST, DELETE, HEAD queue
|
18
|
+
messages using the normal HTTP requests. The system itself uses a configuration
|
19
|
+
file (*config.ru*) to setup queues at startup or even at runtime. The queue
|
20
|
+
implementations can be changed or you can develep own queues with ease.
|
23
21
|
|
24
|
-
For an simple administration
|
22
|
+
For an simple administration try out the integrated ajax based web interface.
|
25
23
|
|
26
|
-
The client apis are implemented using the HTTP protocol, so that
|
27
|
-
|
24
|
+
The client apis are implemented using the HTTP protocol, so that you can
|
25
|
+
use even curl to receive messages. A client library for ruby is implemented
|
26
|
+
right now, other languages will follow.
|
28
27
|
|
29
|
-
The queue itself is
|
30
|
-
or http://localhost:5884/myApplication/myQueueName
|
31
|
-
this url with a web browser you will receive one message from the queue.
|
32
|
-
stores it’s internal data in an FIFO in system memory.
|
28
|
+
The queue itself is a RESTful url like @http://localhost:5884/myQueueName/@
|
29
|
+
or @http://localhost:5884/myApplication/myQueueName/@. If you do a GET request
|
30
|
+
to this url with a web browser you will receive one message from the queue.
|
33
31
|
|
34
32
|
== FEATURES/PROBLEMS:
|
35
33
|
|
@@ -46,16 +44,17 @@ stores it’s internal data in an FIFO in system memory.
|
|
46
44
|
After installing the gem you can start by creating a project:
|
47
45
|
|
48
46
|
fmq create my_project_name
|
47
|
+
|
49
48
|
next step is to change to the folder and start the FMQ server:
|
50
49
|
|
51
50
|
cd my_project_name
|
52
|
-
|
51
|
+
rackup -p 5884
|
53
52
|
|
54
|
-
The server will start and host a admin interface on http://localhost:5884/admin/index.
|
53
|
+
The server will start and host a admin interface on http://localhost:5884/admin/index.html.
|
55
54
|
|
56
55
|
== REQUIREMENTS:
|
57
56
|
|
58
|
-
*
|
57
|
+
* rack >= 0.4.0 (web server provider)
|
59
58
|
|
60
59
|
== INSTALL:
|
61
60
|
|
@@ -67,4 +66,4 @@ Just install the gem as you expect:
|
|
67
66
|
|
68
67
|
(GNU GENERAL PUBLIC LICENSE, Version 3)
|
69
68
|
|
70
|
-
Copyright (c) 2008 Vincent Landgraf
|
69
|
+
Copyright (c) 2008 Vincent Landgraf
|
data/default-server/config.ru
CHANGED
@@ -7,22 +7,13 @@ end
|
|
7
7
|
# load all local queues (from project directory)
|
8
8
|
Dir.glob("queues/*.rb").each { |f| require f }
|
9
9
|
|
10
|
-
# setup log level of free message queue
|
11
|
-
FreeMessageQueue.log_level("info")
|
12
|
-
|
13
10
|
# =====================================================
|
14
11
|
# create and configure the queue manager
|
15
12
|
# =====================================================
|
16
|
-
queue_manager = FreeMessageQueue::QueueManager.new()
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
# <em>auto_create_queues</em> is <b>true</b>. This
|
22
|
-
# is a useful option if you are in development,
|
23
|
-
# the queue will be a FreeMessageQueue::SyncronizedQueue by default
|
24
|
-
qm.auto_create_queues = true
|
25
|
-
|
14
|
+
# if someone pushes to a queue that don't exists
|
15
|
+
# the queue manager will create one for you if you pass true
|
16
|
+
queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
26
17
|
# =====================================================
|
27
18
|
# if you want some queues right from startup
|
28
19
|
# define there url and constraints here
|
@@ -31,7 +22,7 @@ queue_manager.setup do |qm|
|
|
31
22
|
# the path to the queue e.g. /app1/myframe/test1
|
32
23
|
# means http://localhost:5884/app1/myframe/test1
|
33
24
|
# this parameter is not optional
|
34
|
-
|
25
|
+
setup_queue "/fmq_test/test1" do |q|
|
35
26
|
# this defines the maximum count of messages that
|
36
27
|
# can be in the queue, if the queue is full every
|
37
28
|
# new message will be rejected with a http error
|
@@ -46,19 +37,28 @@ queue_manager.setup do |qm|
|
|
46
37
|
|
47
38
|
# if you want you can specify the class of the queue
|
48
39
|
# this is interessting if you write your own queues
|
49
|
-
|
40
|
+
setup_queue "/fmq_test/test2", FreeMessageQueue::LoadBalancedQueue
|
50
41
|
|
51
42
|
# if you have special queues include put them into the queues
|
52
43
|
# folder and and use them (this MyTestQueue is places in queues/mytest.rb)
|
53
|
-
|
44
|
+
setup_queue "/fmq_test/test3", MyTestQueue
|
54
45
|
|
55
46
|
# this is a forwarding queue wich forwards one message
|
56
47
|
# to some other queues
|
57
|
-
|
48
|
+
setup_queue "/fmq_test/forward_to_1_and_2", FreeMessageQueue::ForwardQueue do |q|
|
58
49
|
# you can add as may queues as you want
|
59
50
|
# but seperate them with a space char
|
60
51
|
q.forward_to = ["/fmq_test/test1", "/fmq_test/test2"]
|
61
52
|
end
|
53
|
+
|
54
|
+
# this is a file system queue that will save each method
|
55
|
+
# in the file system until they are polled
|
56
|
+
# the message is useful if you want to have a queue that will
|
57
|
+
# save it's state so that you can reboot the server
|
58
|
+
setup_queue "/fmq_test/file_persistent", FreeMessageQueue::FilePersistentQueue do |q|
|
59
|
+
q.folder = "./tmp/mail_box/threez"
|
60
|
+
q.max_messages = 10_000
|
61
|
+
end
|
62
62
|
end
|
63
63
|
|
64
64
|
# =====================================================
|
data/lib/fmq/admin.rb
CHANGED
@@ -16,13 +16,6 @@
|
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with Free Message Queue. If not, see <http://www.gnu.org/licenses/>.
|
18
18
|
#
|
19
|
-
begin
|
20
|
-
require "rack"
|
21
|
-
rescue LoadError
|
22
|
-
require "rubygems"
|
23
|
-
require "rack"
|
24
|
-
end
|
25
|
-
|
26
19
|
module FreeMessageQueue
|
27
20
|
# This class is dedicated to the AJAX based admin interface.
|
28
21
|
class AdminInterface
|
data/lib/fmq/boot.rb
CHANGED
@@ -29,35 +29,27 @@ module FreeMessageQueue
|
|
29
29
|
# free message queue, so that it is simple to access
|
30
30
|
# the logger from somewhere in the project
|
31
31
|
def self.logger
|
32
|
-
$FMQ_GLOBAL_LOGGER ||= create_logger
|
32
|
+
$FMQ_GLOBAL_LOGGER ||= FreeMessageQueue.create_logger
|
33
33
|
end
|
34
34
|
|
35
35
|
# This method creates the logger instance once (even if it is called twice).
|
36
|
+
# it is by default on fatal
|
36
37
|
def self.create_logger(log_to = STDOUT)
|
37
38
|
$FMQ_GLOBAL_LOGGER ||= Logger.new(log_to)
|
39
|
+
FreeMessageQueue.log_level(:fatal)
|
40
|
+
return $FMQ_GLOBAL_LOGGER
|
38
41
|
end
|
39
42
|
|
40
43
|
# This method sets the log level of the fmq logger
|
41
44
|
# the level must be a string (either downcase or upcase)
|
42
45
|
# that contains one of the following levels:
|
43
|
-
# *
|
44
|
-
# *
|
45
|
-
# *
|
46
|
-
# *
|
47
|
-
# *
|
46
|
+
# * :fatal => Server side errors
|
47
|
+
# * :error => Server side error backtraces
|
48
|
+
# * :warn => Client side errors
|
49
|
+
# * :info => Setup information (config stuff etc.)
|
50
|
+
# * :debug => All operations of the queue manager and others
|
48
51
|
def self.log_level(level)
|
49
|
-
|
50
|
-
when /fatal/i
|
51
|
-
FreeMessageQueue.logger.level = Logger::FATAL
|
52
|
-
when /error/i
|
53
|
-
FreeMessageQueue.logger.level = Logger::ERROR
|
54
|
-
when /warn/i
|
55
|
-
FreeMessageQueue.logger.level = Logger::WARN
|
56
|
-
when /info/i
|
57
|
-
FreeMessageQueue.logger.level = Logger::INFO
|
58
|
-
when /debug/i
|
59
|
-
FreeMessageQueue.logger.level = Logger::DEBUG
|
60
|
-
end
|
52
|
+
FreeMessageQueue.logger.level = eval("Logger::#{level.to_s.upcase}")
|
61
53
|
FreeMessageQueue.logger.debug "[Logger] set log level to #{level}"
|
62
54
|
end
|
63
55
|
|
data/lib/fmq/queue_manager.rb
CHANGED
@@ -15,8 +15,7 @@
|
|
15
15
|
#
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with Free Message Queue. If not, see <http://www.gnu.org/licenses/>.
|
18
|
-
#
|
19
|
-
require "ostruct"
|
18
|
+
#
|
20
19
|
|
21
20
|
# add kb, mb and gb methods for easy use in the config file
|
22
21
|
class Fixnum
|
@@ -64,10 +63,11 @@ module FreeMessageQueue
|
|
64
63
|
|
65
64
|
# setup the queue manager using the configuration from the configuration
|
66
65
|
# file (which is basically a hash)
|
67
|
-
def initialize()
|
66
|
+
def initialize(auto_create_queues = true, &block)
|
68
67
|
@queues = {}
|
69
68
|
@log = FreeMessageQueue.logger
|
70
|
-
@auto_create_queues =
|
69
|
+
@auto_create_queues = auto_create_queues
|
70
|
+
instance_eval(&block) if block_given?
|
71
71
|
end
|
72
72
|
|
73
73
|
# returns if the creation of queues should be done on demand
|
@@ -78,12 +78,10 @@ module FreeMessageQueue
|
|
78
78
|
|
79
79
|
# create a queue using a block. The block can be used to set configuration
|
80
80
|
# options for the queue
|
81
|
-
def setup_queue(path, queue_class = DEFAULT_QUEUE_CLASS)
|
81
|
+
def setup_queue(path, queue_class = DEFAULT_QUEUE_CLASS, &block)
|
82
82
|
check_queue_name(path)
|
83
83
|
queue_object = queue_class.new(self)
|
84
|
-
if block_given?
|
85
|
-
yield queue_object
|
86
|
-
end
|
84
|
+
block.call(queue_object) if block_given?
|
87
85
|
@queues[path] = queue_object
|
88
86
|
@log.info("[QueueManager] Create queue '#{path}' {type: #{queue_class}, max_messages: #{queue_object.max_messages}, max_size: #{queue_object.max_size}}")
|
89
87
|
return queue_object
|
@@ -93,7 +91,7 @@ module FreeMessageQueue
|
|
93
91
|
def delete_queue(name)
|
94
92
|
if queue_exists? name
|
95
93
|
@log.info("[QueueManager] Delete queue '#{name}' with #{queue(name).size} messages")
|
96
|
-
queue(name).clear
|
94
|
+
queue(name).clear if queue(name).respond_to? :clear
|
97
95
|
@queues.delete name
|
98
96
|
true
|
99
97
|
else
|
@@ -126,7 +124,7 @@ module FreeMessageQueue
|
|
126
124
|
unless queue_exists? name
|
127
125
|
# only auto create queues if it is configured
|
128
126
|
if auto_create_queues?
|
129
|
-
|
127
|
+
setup_queue(name)
|
130
128
|
else
|
131
129
|
raise QueueManagerException.new("[QueueManager] There is no queue '#{name}'", caller)
|
132
130
|
end
|
@@ -152,11 +150,7 @@ module FreeMessageQueue
|
|
152
150
|
!queue(name).nil?
|
153
151
|
end
|
154
152
|
|
155
|
-
#
|
156
|
-
def setup(&config)
|
157
|
-
config.call(self)
|
158
|
-
end
|
159
|
-
|
153
|
+
# returns the queue qith the passed name
|
160
154
|
def queue(name)
|
161
155
|
return @queues[name]
|
162
156
|
end
|
@@ -177,3 +171,4 @@ module FreeMessageQueue
|
|
177
171
|
end
|
178
172
|
end
|
179
173
|
end
|
174
|
+
|
data/lib/fmq/queues/README.txt
CHANGED
@@ -4,7 +4,7 @@ Read this simple description on how to create a queue for your special purpose.
|
|
4
4
|
First of all, this template is where you start.
|
5
5
|
1. You have to create a class that is meanful and ends up with "Queue" (for naming convention) e.g. "MyTestQueue"
|
6
6
|
2. Name your file to the name of the queue. In this example we have the queue "MyTestQueue"
|
7
|
-
so the file will be "my_test.rb". Save your new file to the queue folder of your projects folder "queues/my_test.rb"
|
7
|
+
so the file will be "my_test.rb". Save your new file to the queue folder of your projects folder "./queues/my_test.rb"
|
8
8
|
3. Change the queue implementation to something you like
|
9
9
|
* every queue must have an <em>manager</em>. (for this just inherit from FreeMessageQueue::BaseQueue)
|
10
10
|
* this manager must be able to read <em>bytes</em> and <em>size</em> (for this just inherit from FreeMessageQueue::BaseQueue)
|
@@ -21,7 +21,7 @@ First of all, this template is where you start.
|
|
21
21
|
|
22
22
|
def poll
|
23
23
|
FreeMessageQueue::Message.new "Hello World", "text/plain" do |m|
|
24
|
-
|
25
|
-
|
24
|
+
m.option["Time"] = Time.now
|
25
|
+
end
|
26
26
|
end
|
27
|
-
end
|
27
|
+
end
|
data/lib/fmq/queues/base.rb
CHANGED
data/lib/fmq/queues/file.rb
CHANGED
@@ -22,23 +22,21 @@ module FreeMessageQueue
|
|
22
22
|
# This queue returns everytime the same file. This is useful during debugging or
|
23
23
|
# to serve the admin page.
|
24
24
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# class: FreeMessageQueue::FileQueue
|
32
|
-
# file: admin-interface/index.html
|
33
|
-
# content-type: text/html
|
25
|
+
# queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
26
|
+
# setup_queue "/dummy/file", FreeMessageQueue::FileQueue do |q|
|
27
|
+
# q.file = "tmp/default_message.yml"
|
28
|
+
# q.content_type = "text/yaml"
|
29
|
+
# end
|
30
|
+
# end
|
34
31
|
#
|
35
32
|
# *NOTE* the put method is not implemented in this queue. It is a poll only queue.
|
36
33
|
class FileQueue < BaseQueue
|
37
34
|
# Return the file and content type
|
38
|
-
def poll()
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
def poll()
|
36
|
+
file_content = ""
|
37
|
+
File.open(@file_path, "rb") do |f|
|
38
|
+
file_content = f.read
|
39
|
+
end
|
42
40
|
|
43
41
|
@bytes = file_content.size
|
44
42
|
Message.new(file_content, @content_type)
|
@@ -57,4 +55,4 @@ module FreeMessageQueue
|
|
57
55
|
@content_type = type
|
58
56
|
end
|
59
57
|
end
|
60
|
-
end
|
58
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2008 Vincent Landgraf
|
3
|
+
#
|
4
|
+
# This file is part of the Free Message Queue.
|
5
|
+
#
|
6
|
+
# Free Message Queue is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Free Message Queue is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Free Message Queue. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
require File.dirname(__FILE__) + '/base'
|
20
|
+
require "fileutils"
|
21
|
+
|
22
|
+
module FreeMessageQueue
|
23
|
+
# This a FIFO queue that stores messages in the file system
|
24
|
+
#
|
25
|
+
# queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
26
|
+
# setup_queue "/mail_box/threez", FreeMessageQueue::FilePersistentQueue do |q|
|
27
|
+
# q.folder = "./tmp/mail_box/threez"
|
28
|
+
# q.max_messages = 10000
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# *NOTE* the put method is not implemented in this queue. It is a poll only queue.
|
33
|
+
class FilePersistentQueue < BaseQueue
|
34
|
+
# Return the
|
35
|
+
def poll()
|
36
|
+
check_folder_name
|
37
|
+
messages = all_messages.sort!
|
38
|
+
return nil if messages.size == 0
|
39
|
+
|
40
|
+
msg_bin = File.open(messages.first, "rb") { |f| f.read }
|
41
|
+
FileUtils.rm messages.first
|
42
|
+
remove_message(Marshal.load(msg_bin))
|
43
|
+
end
|
44
|
+
|
45
|
+
# add one message to the queue (will be saved in file system)
|
46
|
+
def put(message)
|
47
|
+
check_folder_name
|
48
|
+
return false if message.nil?
|
49
|
+
|
50
|
+
add_message(message) # check constraints and update stats
|
51
|
+
|
52
|
+
msg_bin = Marshal.dump(message)
|
53
|
+
File.open(@folder_path + "/#{Time.now.to_f}.msg", "wb") do |f|
|
54
|
+
f.write msg_bin
|
55
|
+
end
|
56
|
+
return true
|
57
|
+
end
|
58
|
+
|
59
|
+
# *CONFIGURATION* *OPTION*
|
60
|
+
# sets the path to the folder that holds all messages, this will
|
61
|
+
# create the folder if it doesn't exist
|
62
|
+
def folder=(path)
|
63
|
+
FileUtils.mkdir_p path unless File.exist? path
|
64
|
+
@folder_path = path
|
65
|
+
end
|
66
|
+
|
67
|
+
# remove all items from the queue
|
68
|
+
def clear
|
69
|
+
FileUtils.rm all_messages
|
70
|
+
@size = 0
|
71
|
+
@bytes = 0
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# returns an array with all paths to queue messages
|
77
|
+
def all_messages
|
78
|
+
Dir[@folder_path + "/*.msg"]
|
79
|
+
end
|
80
|
+
|
81
|
+
# raise an exceptin if the folder name is not set
|
82
|
+
def check_folder_name
|
83
|
+
raise QueueException.new("[FilePersistentQueue] The folder_path need to be specified", caller) if @folder_path.nil?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/fmq/queues/forward.rb
CHANGED
@@ -20,14 +20,12 @@ require File.dirname(__FILE__) + '/base'
|
|
20
20
|
|
21
21
|
module FreeMessageQueue
|
22
22
|
# This queue returns sends one message to several queues at a time.
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# class: FreeMessageQueue::ForwardQueue
|
30
|
-
# forward_to: /fmq_test/test1 /fmq_test/test2
|
23
|
+
#
|
24
|
+
# queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
25
|
+
# setup_queue "/fmq_test/forward_to_1_and_2", FreeMessageQueue::ForwardQueue do |q|
|
26
|
+
# q.forward_to = ["/fmq_test/test1", "/fmq_test/test2"]
|
27
|
+
# end
|
28
|
+
# end
|
31
29
|
#
|
32
30
|
# *NOTE* the poll method is not implemented in this queue. It is a put only queue.
|
33
31
|
class ForwardQueue < BaseQueue
|
data/lib/fmq/queues/linked.rb
CHANGED
@@ -22,16 +22,12 @@ module FreeMessageQueue
|
|
22
22
|
# This queue is an approach to the issue that you want to have
|
23
23
|
# multiple threads at one queue at a time. Currently this is not
|
24
24
|
# considered to be a stable queue. Just use it for experimental things.
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# path: /fmq_test/test1
|
32
|
-
# max-messages: 1000000
|
33
|
-
# max-size: 10kb
|
34
|
-
# class: FreeMessageQueue::LoadBalancedQueue
|
25
|
+
#
|
26
|
+
# queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
27
|
+
# setup_queue "/fmq_test/test1", FreeMessageQueue::LoadBalancedQueue do |q|
|
28
|
+
# q.forward_to = ["/fmq_test/test1", "/fmq_test/test2"]
|
29
|
+
# end
|
30
|
+
# end
|
35
31
|
class LoadBalancedQueue
|
36
32
|
# QueueManager refrence
|
37
33
|
attr_accessor :manager
|
@@ -71,8 +67,8 @@ module FreeMessageQueue
|
|
71
67
|
end
|
72
68
|
|
73
69
|
# Put an item to one of the queues
|
74
|
-
def put(
|
75
|
-
@queues[next_put_index].put(
|
70
|
+
def put(message)
|
71
|
+
@queues[next_put_index].put(message)
|
76
72
|
end
|
77
73
|
|
78
74
|
# queue has infinite count
|
@@ -22,15 +22,13 @@ require File.dirname(__FILE__) + '/linked'
|
|
22
22
|
module FreeMessageQueue
|
23
23
|
# The SyncronizedQueue implements a little wrapper around the
|
24
24
|
# LinkedQueue to make it thread safe
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# max-messages: 1000000
|
33
|
-
# max-size: 10kb
|
25
|
+
#
|
26
|
+
# queue_manager = FreeMessageQueue::QueueManager.new(true) do
|
27
|
+
# setup_queue "/fmq_test/test1" do |q|
|
28
|
+
# q.max_messages = 1000000
|
29
|
+
# q.max_size = 10.kb
|
30
|
+
# end
|
31
|
+
# end
|
34
32
|
class SyncronizedQueue < LinkedQueue
|
35
33
|
|
36
34
|
def initialize(manager)
|
@@ -45,11 +43,11 @@ module FreeMessageQueue
|
|
45
43
|
}
|
46
44
|
end
|
47
45
|
|
48
|
-
# Puts one
|
49
|
-
def put(
|
46
|
+
# Puts one message to the queue
|
47
|
+
def put(message)
|
50
48
|
@semaphore.synchronize {
|
51
|
-
super(
|
49
|
+
super(message)
|
52
50
|
}
|
53
51
|
end
|
54
52
|
end
|
55
|
-
end
|
53
|
+
end
|
data/lib/fmq/server.rb
CHANGED
@@ -17,13 +17,6 @@
|
|
17
17
|
# You should have received a copy of the GNU General Public License
|
18
18
|
# along with Free Message Queue. If not, see <http://www.gnu.org/licenses/>.
|
19
19
|
#
|
20
|
-
begin
|
21
|
-
require "rack"
|
22
|
-
rescue LoadError
|
23
|
-
require "rubygems"
|
24
|
-
require "rack"
|
25
|
-
end
|
26
|
-
|
27
20
|
module FreeMessageQueue
|
28
21
|
# This implements server that plugs the free message queue into a rack enviroment
|
29
22
|
class Server
|
data/lib/fmq/version.rb
CHANGED
data/lib/fmq.rb
CHANGED
@@ -17,6 +17,14 @@
|
|
17
17
|
# along with Free Message Queue. If not, see <http://www.gnu.org/licenses/>.
|
18
18
|
#
|
19
19
|
|
20
|
+
# load the rack enviroment
|
21
|
+
begin
|
22
|
+
require "rack"
|
23
|
+
rescue LoadError
|
24
|
+
require "rubygems"
|
25
|
+
require "rack"
|
26
|
+
end
|
27
|
+
|
20
28
|
# load all queues and manager and server
|
21
29
|
Dir.glob(File.dirname(__FILE__) + "/fmq/queues/*.rb").each do |file|
|
22
30
|
require file
|
data/test/test_basic.rb
CHANGED
@@ -27,19 +27,21 @@ end
|
|
27
27
|
|
28
28
|
class BaseQueue < Test::Unit::TestCase
|
29
29
|
def setup
|
30
|
-
@manager = FreeMessageQueue::QueueManager.new()
|
31
|
-
|
32
|
-
|
33
|
-
@queue1 = m.setup_queue "/dummy1"
|
34
|
-
@queue2 = m.setup_queue "/dummy2" do |q|
|
30
|
+
@manager = FreeMessageQueue::QueueManager.new() do
|
31
|
+
setup_queue "/dummy1"
|
32
|
+
setup_queue "/dummy2" do |q|
|
35
33
|
q.max_messages = 100
|
36
34
|
q.max_size = 100.kb
|
37
35
|
end
|
38
|
-
|
36
|
+
setup_queue "/dummy3" do |q|
|
39
37
|
q.max_size = 0
|
40
38
|
q.max_messages = -10
|
41
39
|
end
|
42
40
|
end
|
41
|
+
|
42
|
+
@queue1 = @manager.queue "/dummy1"
|
43
|
+
@queue2 = @manager.queue "/dummy2"
|
44
|
+
@queue3 = @manager.queue "/dummy3"
|
43
45
|
end
|
44
46
|
|
45
47
|
def test_creating
|
@@ -83,4 +85,4 @@ class BaseQueue < Test::Unit::TestCase
|
|
83
85
|
@queue2.put(new_msg("X" * 10.kb))
|
84
86
|
end
|
85
87
|
end
|
86
|
-
end
|
88
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
# This is the default test to the message interface
|
5
|
+
class TestFilePersistentQueue < Test::Unit::TestCase
|
6
|
+
include FifoQueueTests
|
7
|
+
|
8
|
+
def setup
|
9
|
+
manager = nil # the manager is not needed in this test
|
10
|
+
@queue = FreeMessageQueue::FilePersistentQueue.new(manager)
|
11
|
+
@queue.folder = "/tmp/fmq/FilePersistentQueue/testqueue"
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
# remove the test data
|
16
|
+
FileUtils.rm_rf "/tmp/fmq"
|
17
|
+
end
|
18
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -3,4 +3,62 @@ require File.dirname(__FILE__) + '/../lib/fmq'
|
|
3
3
|
|
4
4
|
def new_msg(payload)
|
5
5
|
FreeMessageQueue::Message.new(payload)
|
6
|
-
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module FifoQueueTests
|
9
|
+
def test_basic_get_poll
|
10
|
+
assert_nil @queue.poll
|
11
|
+
assert_equal 0, @queue.size
|
12
|
+
assert @queue.put(nil) == false
|
13
|
+
assert_nil @queue.poll
|
14
|
+
td_1 = new_msg("asdasd")
|
15
|
+
assert @queue.put(td_1)
|
16
|
+
assert_equal 1, @queue.size
|
17
|
+
assert_equal td_1.payload, @queue.poll.payload
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_n_messages
|
21
|
+
n = 20
|
22
|
+
byte_size = 0
|
23
|
+
n.times { |t| byte_size += t.to_s.size }
|
24
|
+
|
25
|
+
assert_equal 0, @queue.bytes
|
26
|
+
assert_nil @queue.poll
|
27
|
+
n.times do |i|
|
28
|
+
assert @queue.put(new_msg(i.to_s))
|
29
|
+
end
|
30
|
+
assert_equal byte_size, @queue.bytes
|
31
|
+
assert_equal n, @queue.size
|
32
|
+
n.times do |i|
|
33
|
+
assert_equal i.to_s, @queue.poll.payload
|
34
|
+
end
|
35
|
+
assert_equal 0, @queue.bytes
|
36
|
+
assert_nil @queue.poll
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_mam_messages
|
40
|
+
@queue.put(new_msg("asd"))
|
41
|
+
@queue.put(new_msg("asd"))
|
42
|
+
@queue.poll()
|
43
|
+
@queue.put(new_msg("asd"))
|
44
|
+
@queue.put(new_msg("asd"))
|
45
|
+
@queue.poll()
|
46
|
+
@queue.put(new_msg("asd"))
|
47
|
+
@queue.poll()
|
48
|
+
assert_equal 2, @queue.size
|
49
|
+
@queue.put(new_msg("asd"))
|
50
|
+
@queue.put(new_msg("asd"))
|
51
|
+
assert_equal 4, @queue.size
|
52
|
+
@queue.clear
|
53
|
+
assert_equal 0, @queue.size
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_queue_bytes
|
57
|
+
@queue.put(new_msg("XX" * 40))
|
58
|
+
@queue.put(new_msg("X" * 40))
|
59
|
+
@queue.put(new_msg("XX888" * 40))
|
60
|
+
assert_equal 2*40+40+5*40, @queue.bytes
|
61
|
+
@queue.clear
|
62
|
+
assert_equal 0, @queue.bytes
|
63
|
+
end
|
64
|
+
end
|
data/test/test_linked.rb
CHANGED
@@ -2,64 +2,10 @@ require File.dirname(__FILE__) + '/test_helper.rb'
|
|
2
2
|
|
3
3
|
# This is the default test to the message interface
|
4
4
|
class TestLinkedQueue < Test::Unit::TestCase
|
5
|
+
include FifoQueueTests
|
6
|
+
|
5
7
|
def setup
|
6
8
|
manager = nil # the manager is not needed in this test
|
7
9
|
@queue = FreeMessageQueue::LinkedQueue.new(manager)
|
8
10
|
end
|
9
|
-
|
10
|
-
def test_basic_get_poll
|
11
|
-
assert_nil @queue.poll
|
12
|
-
assert_equal 0, @queue.size
|
13
|
-
assert @queue.put(nil) == false
|
14
|
-
assert_nil @queue.poll
|
15
|
-
td_1 = new_msg("asdasd")
|
16
|
-
assert @queue.put(td_1)
|
17
|
-
assert_equal 1, @queue.size
|
18
|
-
assert_equal td_1.payload, @queue.poll.payload
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_n_messages
|
22
|
-
n = 20
|
23
|
-
byte_size = 0
|
24
|
-
n.times { |t| byte_size += t.to_s.size }
|
25
|
-
|
26
|
-
assert_equal 0, @queue.bytes
|
27
|
-
assert_nil @queue.poll
|
28
|
-
n.times do |i|
|
29
|
-
assert @queue.put(new_msg(i.to_s))
|
30
|
-
end
|
31
|
-
assert_equal byte_size, @queue.bytes
|
32
|
-
assert_equal n, @queue.size
|
33
|
-
n.times do |i|
|
34
|
-
assert_equal i.to_s, @queue.poll.payload
|
35
|
-
end
|
36
|
-
assert_equal 0, @queue.bytes
|
37
|
-
assert_nil @queue.poll
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_mam_messages
|
41
|
-
@queue.put(new_msg("asd"))
|
42
|
-
@queue.put(new_msg("asd"))
|
43
|
-
@queue.poll()
|
44
|
-
@queue.put(new_msg("asd"))
|
45
|
-
@queue.put(new_msg("asd"))
|
46
|
-
@queue.poll()
|
47
|
-
@queue.put(new_msg("asd"))
|
48
|
-
@queue.poll()
|
49
|
-
assert_equal 2, @queue.size
|
50
|
-
@queue.put(new_msg("asd"))
|
51
|
-
@queue.put(new_msg("asd"))
|
52
|
-
assert_equal 4, @queue.size
|
53
|
-
@queue.clear
|
54
|
-
assert_equal 0, @queue.size
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_queue_bytes
|
58
|
-
@queue.put(new_msg("XX" * 40))
|
59
|
-
@queue.put(new_msg("X" * 40))
|
60
|
-
@queue.put(new_msg("XX888" * 40))
|
61
|
-
assert_equal 2*40+40+5*40, @queue.bytes
|
62
|
-
@queue.clear
|
63
|
-
assert_equal 0, @queue.bytes
|
64
|
-
end
|
65
|
-
end
|
11
|
+
end
|
data/test/test_queue_manager.rb
CHANGED
@@ -5,34 +5,22 @@ class TestQueueManager < Test::Unit::TestCase
|
|
5
5
|
DEFAULT_QUEUE_NAME = "/fmq_test/test1"
|
6
6
|
|
7
7
|
def setup
|
8
|
-
FreeMessageQueue.
|
9
|
-
|
10
|
-
@queue_manager = FreeMessageQueue::QueueManager.new()
|
11
|
-
|
12
|
-
@queue_manager.setup do |qm|
|
13
|
-
qm.auto_create_queues = false
|
14
|
-
|
15
|
-
qm.setup_queue DEFAULT_QUEUE_NAME do |q|
|
8
|
+
@queue_manager = FreeMessageQueue::QueueManager.new(false) do
|
9
|
+
setup_queue DEFAULT_QUEUE_NAME do |q|
|
16
10
|
q.max_messages = 100
|
17
11
|
q.max_size = 100.mb
|
18
12
|
end
|
19
13
|
|
20
|
-
|
21
|
-
|
14
|
+
setup_queue "/second_test_queue"
|
15
|
+
setup_queue "/third_test_queue"
|
22
16
|
end
|
23
17
|
end
|
24
18
|
|
25
|
-
def test_config
|
26
|
-
# check that the simple config will work
|
27
|
-
FreeMessageQueue::QueueManager.new()
|
28
|
-
@queue_manager.setup do |qm|
|
29
|
-
qm.auto_create_queues = false
|
30
|
-
end
|
31
|
-
|
19
|
+
def test_config
|
32
20
|
# check if all queues are available
|
33
21
|
assert_equal 3, @queue_manager.queues.size
|
34
22
|
[DEFAULT_QUEUE_NAME, "/second_test_queue", "/third_test_queue"].each do |e|
|
35
|
-
assert @queue_manager.queues.include?
|
23
|
+
assert @queue_manager.queues.include?(e)
|
36
24
|
end
|
37
25
|
end
|
38
26
|
|
@@ -84,4 +72,5 @@ class TestQueueManager < Test::Unit::TestCase
|
|
84
72
|
@queue_manager.put(url, new_msg("Test"))
|
85
73
|
}
|
86
74
|
end
|
87
|
-
end
|
75
|
+
end
|
76
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fmq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vincent Landgraf
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-08-
|
12
|
+
date: 2008-08-28 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -22,6 +22,16 @@ dependencies:
|
|
22
22
|
- !ruby/object:Gem::Version
|
23
23
|
version: 0.4.0
|
24
24
|
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.7.0
|
34
|
+
version:
|
25
35
|
description: The project implements a queue system with a server and some client apis. This project wants to be a fast and lightweight implementation with most of the features of MQS or ActiveMQ.
|
26
36
|
email:
|
27
37
|
- fmq-3z@gmx.net
|
@@ -63,12 +73,14 @@ files:
|
|
63
73
|
- lib/fmq/queues/linked.rb
|
64
74
|
- lib/fmq/queues/load_balanced.rb
|
65
75
|
- lib/fmq/queues/syncronized.rb
|
76
|
+
- lib/fmq/queues/file_persistent.rb
|
66
77
|
- lib/fmq/version.rb
|
67
78
|
- test/test_basic.rb
|
68
79
|
- test/test_fmq_client.rb
|
69
80
|
- test/test_helper.rb
|
70
81
|
- test/test_linked.rb
|
71
82
|
- test/test_queue_manager.rb
|
83
|
+
- test/test_file_persistent.rb
|
72
84
|
has_rdoc: true
|
73
85
|
homepage: http://fmq.rubyforge.org
|
74
86
|
post_install_message: |-
|
@@ -101,6 +113,7 @@ specification_version: 2
|
|
101
113
|
summary: The project implements a queue system with a server and some client apis. This project wants to be a fast and lightweight implementation with most of the features of MQS or ActiveMQ.
|
102
114
|
test_files:
|
103
115
|
- test/test_basic.rb
|
116
|
+
- test/test_file_persistent.rb
|
104
117
|
- test/test_fmq_client.rb
|
105
118
|
- test/test_helper.rb
|
106
119
|
- test/test_linked.rb
|