mm_mq 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 akimatter
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = mm_mq
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 akimatter. See LICENSE for details.
@@ -0,0 +1,79 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "mm_mq"
8
+ gem.summary = %Q{MQ library of MonmeyMagic}
9
+ gem.description = %Q{MQ library of MonmeyMagic}
10
+ gem.email = "monkey-magic@ec-one.com"
11
+ gem.homepage = ""
12
+ gem.authors = ["monkey-magic"]
13
+ if RUBY_PLATFORM == 'java'
14
+ gem.add_dependency "nayutaya-msgpack-pure", "0.0.2"
15
+ else
16
+ gem.add_dependency "msgpack", ">= 0.4.3"
17
+ end
18
+ gem.add_dependency "totty-amqp", ">= 0.6.7.1"
19
+ gem.add_development_dependency "rspec", ">= 1.2.9"
20
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ require 'spec/rake/spectask'
28
+ Spec::Rake::SpecTask.new(:spec) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.spec_files = FileList['spec/**/*_spec.rb']
31
+ end
32
+
33
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
34
+ spec.libs << 'lib' << 'spec'
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ spec.rcov_opts = lambda do
38
+ IO.readlines("spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
39
+ end
40
+ end
41
+
42
+ task :spec => :check_dependencies
43
+
44
+ begin
45
+ require 'reek/adapters/rake_task'
46
+ Reek::RakeTask.new do |t|
47
+ t.fail_on_error = true
48
+ t.verbose = false
49
+ t.source_files = 'lib/**/*.rb'
50
+ end
51
+ rescue LoadError
52
+ task :reek do
53
+ abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
54
+ end
55
+ end
56
+
57
+ begin
58
+ require 'roodi'
59
+ require 'roodi_task'
60
+ RoodiTask.new do |t|
61
+ t.verbose = false
62
+ end
63
+ rescue LoadError
64
+ task :roodi do
65
+ abort "Roodi is not available. In order to run roodi, you must: sudo gem install roodi"
66
+ end
67
+ end
68
+
69
+ task :default => :spec
70
+
71
+ require 'rake/rdoctask'
72
+ Rake::RDocTask.new do |rdoc|
73
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
74
+
75
+ rdoc.rdoc_dir = 'rdoc'
76
+ rdoc.title = "mm_mq #{version}"
77
+ rdoc.rdoc_files.include('README*')
78
+ rdoc.rdoc_files.include('lib/**/*.rb')
79
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.7
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'mq'
3
+ require RUBY_PLATFORM == 'java' ? 'msgpack_pure' : 'msgpack'
4
+ if RUBY_PLATFORM == 'java'
5
+ MessagePack = MessagePackPure
6
+ [NilClass, TrueClass, FalseClass, Fixnum, Bignum, Float, String, Symbol, Array, Hash].each do |klass|
7
+ klass.module_eval do
8
+ def to_msgpack
9
+ MessagePack.pack(self)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ module MmMq
16
+ autoload :Publishable, 'mm_mq/publishable'
17
+ autoload :Subscribable, 'mm_mq/subscribable'
18
+ autoload :HashExt, 'mm_mq/hash_ext'
19
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'mm_mq'
3
+
4
+ module MmMq
5
+ module HashExt
6
+ def symbolize_keys(hash)
7
+ return nil unless hash
8
+ hash.inject({}) do |dest, (key, value)|
9
+ dest[key.to_sym] = value
10
+ dest
11
+ end
12
+ end
13
+ module_function :symbolize_keys
14
+
15
+ end
16
+ end
@@ -0,0 +1,101 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'mm_mq'
3
+
4
+ module MmMq
5
+ module Publishable
6
+ include HashExt
7
+ # https://cloud-dev.ec-one.com/trac/monkey-magic/wiki/amqp-specification
8
+
9
+ # connection
10
+ # host : 'localhost'
11
+ # port : 5672
12
+ # user : 'guest'
13
+ # pass : 'guest'
14
+ # vhost : '/'
15
+ # timeout: nil
16
+ # logging: false
17
+ # insist : false
18
+
19
+ # connections
20
+ # user : 'guest'
21
+ # pass : 'guest'
22
+ # vhost : '/'
23
+ # timeout: nil
24
+ # logging: false
25
+ # insist : false
26
+ # hosts : ["<host1>[:<port>]" [, "<host2>:<port>", "<host3>:<port>"]]
27
+
28
+ # configメソッドを実装する必要があります。
29
+ # def config; {}; end
30
+
31
+ # MQ.startを実行します。
32
+ def connect(options = {}, &block)
33
+ conn = nil
34
+ EM.run do
35
+ if conn_opts = HashExt.symbolize_keys(config[:connections] || config['connections'])
36
+ conn = AMQP.vstart(options.update(conn_opts))
37
+ else
38
+ conn = AMQP.start(options.update(HashExt.symbolize_keys(config[:connection] || config['connection']) || {}))
39
+ end
40
+ channel(conn)
41
+ block.call if block
42
+ end
43
+ end
44
+
45
+ attr_writer :channel
46
+ def channel(connection = nil)
47
+ @channel ||= MQ.new(connection)
48
+ end
49
+
50
+ # queue:
51
+ # name : "<required>"
52
+ # passive : false
53
+ # durable : false
54
+ # auto_delete: false
55
+ # internal : false
56
+ # no_wait : false
57
+
58
+ # exchange:
59
+ # type : direct, fanout, topic, headers, system, implementation_defined
60
+ # name : "<required>"
61
+ # passive : false
62
+ # durable : false
63
+ # auto_delete: false
64
+ # internal : false
65
+ # no_wait : false
66
+
67
+ # MQ.queueやMQ.fanoutなどを実行します。
68
+ def queue_or_exchange
69
+ unless @queue_or_exchange
70
+ opts = symbolize_keys(config[:queue] || config['queue']|| config[:exchange] || config['exchange'] ) || {}
71
+ opts[:type] ||= 'queue' if config[:queue] || config['queue']
72
+ opts[:type] ||= 'direct' if config[:exchange] || config['exchange']
73
+ # channel を明示的に指定するため MQ.send を使わず、MQ::Queue と MQ::Exchange を使用しています
74
+ if (type = opts.delete(:type)) == 'queue'
75
+ @queue_or_exchange = MQ::Queue.new(
76
+ channel,
77
+ opts.delete(:name),
78
+ opts)
79
+ else
80
+ @queue_or_exchange = MQ::Exchange.new(
81
+ channel,
82
+ type,
83
+ opts.delete(:name),
84
+ opts)
85
+ end
86
+ end
87
+ @queue_or_exchange
88
+ end
89
+
90
+ # publish:
91
+ # key : nil
92
+ # mandatory : false
93
+ # immediate : false
94
+ # persistent: false
95
+ def publish(msg, options = {})
96
+ opts = options.update(symbolize_keys(config[:publish] || config['publish']) || {})
97
+ queue_or_exchange.publish(msg.to_msgpack, opts)
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,116 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'mm_mq'
3
+
4
+ module MmMq
5
+ module Subscribable
6
+ include HashExt
7
+ # https://cloud-dev.ec-one.com/trac/monkey-magic/wiki/amqp-specification
8
+
9
+ # connection
10
+ # host : 'localhost'
11
+ # port : 5672
12
+ # user : 'guest'
13
+ # pass : 'guest'
14
+ # vhost : '/'
15
+ # timeout: nil
16
+ # logging: false
17
+ # insist : false
18
+
19
+ # connections
20
+ # user : 'guest'
21
+ # pass : 'guest'
22
+ # vhost : '/'
23
+ # timeout: nil
24
+ # logging: false
25
+ # insist : false
26
+ # hosts : ["<host1>[:<port>]" [, "<host2>:<port>", "<host3>:<port>"]]
27
+
28
+ # configメソッドを実装する必要があります。
29
+ # def config; {}; end
30
+
31
+ # MQ.startを実行します。
32
+ def connect(options = {}, &block)
33
+ if conn_opts = HashExt.symbolize_keys(config[:connections] || config['connections'])
34
+ connections = (conn_opts.delete(:hosts) || []).map do |host_port|
35
+ host, port = host_port.split(/\:/, 2)
36
+ port ||= 5672
37
+ { :host => host, :port => port.to_i }.update(conn_opts)
38
+ end
39
+ else
40
+ connections = [HashExt.symbolize_keys(config[:connection] || config['connection'])]
41
+ end
42
+ connections.each do |conn|
43
+ AMQP.start(conn, &block)
44
+ end
45
+ end
46
+
47
+ # queue:
48
+ # name : "<required>"
49
+ # passive : false
50
+ # durable : false
51
+ # auto_delete: false
52
+ # exclusive : false
53
+ # nowait : false
54
+ def queue
55
+ unless defined?(@queue)
56
+ opts = symbolize_keys(config[:queue] || config['queue']) || {}
57
+ @queue = MQ.queue(opts.delete(:name), opts)
58
+ end
59
+ @queue
60
+ end
61
+
62
+ # exchange:
63
+ # type : direct, fanout, topic, headers, system, implementation_defined
64
+ # name : "<required>"
65
+ # key : nil
66
+ # passive : false
67
+ # durable : false
68
+ # auto_delete: false
69
+ # internal : false
70
+ # nowait : false
71
+ def exchange
72
+ unless defined?(@exchange)
73
+ if opts = symbolize_keys(config[:exchange] || config['exchange'])
74
+ opts[:type] ||= 'direct'
75
+ @routing_key = opts.delete(:key)
76
+ @exchange = MQ.send(opts.delete(:type), opts.delete(:name), opts)
77
+ else
78
+ @exchange = nil
79
+ end
80
+ end
81
+ @exchange
82
+ end
83
+
84
+ def routing_key
85
+ unless defined?(@routing_key)
86
+ if opts = symbolize_keys(config[:exchange] || config['exchange'])
87
+ @routing_key = opts[:key]
88
+ else
89
+ @routing_key = nil
90
+ end
91
+ end
92
+ @routing_key
93
+ end
94
+
95
+ def subscribed
96
+ if routing_key
97
+ exchange ? queue.bind(exchange, :key => routing_key) : queue
98
+ else
99
+ exchange ? queue.bind(exchange) : queue
100
+ end
101
+ end
102
+
103
+ # subscribe:
104
+ # ack : false
105
+ # nowait: false
106
+ # confirm: nil
107
+ def subscribe(options = {}, &block)
108
+ opts = options.update(symbolize_keys(config[:subscribe] || config['subscribe'] || {}))
109
+ subscribed.subscribe(opts) do |head, msg|
110
+ block.call(head, MessagePack.unpack(msg))
111
+ head.ack if opts[:ack]
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{mm_mq}
8
+ s.version = "0.1.7"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["monkey-magic"]
12
+ s.date = %q{2010-11-18}
13
+ s.description = %q{MQ library of MonmeyMagic}
14
+ s.email = %q{monkey-magic@ec-one.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/mm_mq.rb",
27
+ "lib/mm_mq/hash_ext.rb",
28
+ "lib/mm_mq/publishable.rb",
29
+ "lib/mm_mq/subscribable.rb",
30
+ "mm_mq.gemspec",
31
+ "spec/mm_mq/publishable_spec.rb",
32
+ "spec/mm_mq/subscribable_spec.rb",
33
+ "spec/rcov.opts",
34
+ "spec/spec.opts",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{MQ library of MonmeyMagic}
42
+ s.test_files = [
43
+ "spec/mm_mq/publishable_spec.rb",
44
+ "spec/mm_mq/subscribable_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<msgpack>, [">= 0.4.3"])
54
+ s.add_runtime_dependency(%q<totty-amqp>, [">= 0.6.7.1"])
55
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
56
+ else
57
+ s.add_dependency(%q<msgpack>, [">= 0.4.3"])
58
+ s.add_dependency(%q<totty-amqp>, [">= 0.6.7.1"])
59
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
60
+ end
61
+ else
62
+ s.add_dependency(%q<msgpack>, [">= 0.4.3"])
63
+ s.add_dependency(%q<totty-amqp>, [">= 0.6.7.1"])
64
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
65
+ end
66
+ end
67
+
@@ -0,0 +1,161 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
3
+
4
+ describe MmMq::Publishable do
5
+
6
+ class TestPublishment1
7
+ include MmMq::Publishable
8
+ attr_accessor :config
9
+ end
10
+
11
+ before do
12
+ @pub1 = TestPublishment1.new
13
+ end
14
+
15
+ describe :connect do
16
+ it "connectionsで指定されている場合" do
17
+ @pub1.config = {
18
+ "connections" => {
19
+ 'user' => 'goku',
20
+ 'pass' => 'dragonball',
21
+ 'hosts' => ["host1:1234", "host2:1234"]
22
+ }
23
+ }
24
+ conn = mock(:conn)
25
+ AMQP.should_receive(:vstart).with({
26
+ :user => 'goku',
27
+ :pass => 'dragonball',
28
+ :hosts => ["host1:1234", "host2:1234"]
29
+ }).and_return(conn)
30
+ mock_channel = mock(:channel)
31
+ MQ.should_receive(:new).with(conn).and_return(mock_channel)
32
+ block_invoked = false
33
+ @pub1.connect do
34
+ block_invoked = true
35
+ EM.stop
36
+ end
37
+ block_invoked.should == true
38
+ end
39
+
40
+ it "connectionで指定されている場合" do
41
+ @pub1.config = {
42
+ "connection" => {
43
+ 'user' => 'goku',
44
+ 'pass' => 'dragonball'
45
+ }
46
+ }
47
+ conn = mock(:conn)
48
+ AMQP.should_receive(:start).with({
49
+ :user => 'goku',
50
+ :pass => 'dragonball'
51
+ }).and_return(conn)
52
+ mock_channel = mock(:channel)
53
+ MQ.should_receive(:new).with(conn).and_return(mock_channel)
54
+ block_invoked = false
55
+ @pub1.connect do
56
+ block_invoked = true
57
+ EM.stop
58
+ end
59
+ block_invoked.should == true
60
+ end
61
+ end
62
+
63
+ describe :publish do
64
+ it "exchangeで接続する場合" do
65
+ @pub1.config = {
66
+ "exchange" => {
67
+ 'type' => 'fanout',
68
+ 'name' => 'exhange_name1',
69
+ 'durable' => true,
70
+ 'auto_delete' => true
71
+ },
72
+ "publish" => {
73
+ 'mandatory' => true
74
+ }
75
+ }
76
+ mock_channel = mock(:channel)
77
+ @pub1.channel = mock_channel
78
+ mock_exchange = mock(:exchange)
79
+ mock_exchange.should_receive(:publish).
80
+ with("abcd".to_msgpack, :mandatory => true)
81
+ MQ::Exchange.should_receive(:new).with(mock_channel, 'fanout', 'exhange_name1', {
82
+ :durable => true,
83
+ :auto_delete => true
84
+ }).and_return(mock_exchange)
85
+ @pub1.publish("abcd")
86
+ end
87
+
88
+ it "routing_keyを指定して接続する場合" do
89
+ @pub1.config = {
90
+ "exchange" => {
91
+ 'name' => 'exhange_name1',
92
+ 'durable' => true,
93
+ 'auto_delete' => true
94
+ },
95
+ "publish" => {
96
+ 'key' => 'xyz',
97
+ 'mandatory' => true
98
+ }
99
+ }
100
+ mock_channel = mock(:channel)
101
+ @pub1.channel = mock_channel
102
+ mock_exchange = mock(:exchange)
103
+ mock_exchange.should_receive(:publish).
104
+ with("abcd".to_msgpack, {:mandatory => true, :key => 'xyz'})
105
+ MQ::Exchange.should_receive(:new).with(mock_channel, 'direct', 'exhange_name1', {
106
+ :durable => true,
107
+ :auto_delete => true
108
+ }).and_return(mock_exchange)
109
+ @pub1.publish("abcd")
110
+ end
111
+
112
+ it "queueで接続する場合" do
113
+ @pub1.config = {
114
+ "queue" => {
115
+ 'name' => 'queue_name1',
116
+ 'durable' => true,
117
+ 'auto_delete' => true
118
+ },
119
+ "publish" => {
120
+ 'mandatory' => true
121
+ }
122
+ }
123
+ mock_channel = mock(:channel)
124
+ @pub1.channel = mock_channel
125
+ mock_queue = mock(:queue)
126
+ mock_queue.should_receive(:publish).
127
+ with("abcd".to_msgpack, :mandatory => true)
128
+ MQ::Queue.should_receive(:new).with(mock_channel, 'queue_name1', {
129
+ :durable => true,
130
+ :auto_delete => true
131
+ }).and_return(mock_queue)
132
+ @pub1.publish("abcd")
133
+ end
134
+
135
+ it "メッセージをMessagePackでserializeして送る場合" do
136
+ @pub1.config = {
137
+ "queue" => {
138
+ 'name' => 'queue_name1',
139
+ 'durable' => true,
140
+ 'auto_delete' => true
141
+ },
142
+ "publish" => {
143
+ 'mandatory' => true
144
+ }
145
+ }
146
+ mock_channel = mock(:channel)
147
+ @pub1.channel = mock_channel
148
+ mock_queue = mock(:queue)
149
+ mock_queue.should_receive(:publish).
150
+ with("abcd".to_msgpack, :mandatory => true)
151
+ MQ::Queue.should_receive(:new).with(mock_channel, 'queue_name1', {
152
+ :durable => true,
153
+ :auto_delete => true
154
+ }).and_return(mock_queue)
155
+ @pub1.publish("abcd")
156
+ end
157
+
158
+
159
+ end
160
+
161
+ end
@@ -0,0 +1,199 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
3
+
4
+ describe MmMq::Subscribable do
5
+
6
+ class TestSubscriber1
7
+ include MmMq::Subscribable
8
+ attr_accessor :config
9
+ end
10
+
11
+ before do
12
+ @sub1 = TestSubscriber1.new
13
+ end
14
+
15
+ describe :connect do
16
+ it "connectionsで指定されている場合" do
17
+ @sub1.config = {
18
+ "connections" => {
19
+ 'user' => 'goku',
20
+ 'pass' => 'dragonball',
21
+ 'hosts' => ["host1:1234", "host2:1234"]
22
+ }
23
+ }
24
+ AMQP.should_receive(:start).with({
25
+ :user => 'goku',
26
+ :pass => 'dragonball',
27
+ :host => "host1",
28
+ :port => 1234
29
+ }).and_yield
30
+ AMQP.should_receive(:start).with({
31
+ :user => 'goku',
32
+ :pass => 'dragonball',
33
+ :host => "host2",
34
+ :port => 1234
35
+ }).and_yield
36
+ block_invoked = 0
37
+ @sub1.connect do
38
+ block_invoked += 1
39
+ end
40
+ block_invoked.should == 2
41
+ end
42
+
43
+ it "connectionで指定されている場合" do
44
+ @sub1.config = {
45
+ "connection" => {
46
+ 'user' => 'goku',
47
+ 'pass' => 'dragonball'
48
+ }
49
+ }
50
+ AMQP.should_receive(:start).with({
51
+ :user => 'goku',
52
+ :pass => 'dragonball'
53
+ }).and_yield
54
+ block_invoked = false
55
+ @sub1.connect do
56
+ block_invoked = true
57
+ end
58
+ block_invoked.should == true
59
+ end
60
+ end
61
+
62
+ describe :subscribe do
63
+ it "queueだけで接続する場合" do
64
+ @sub1.config = {
65
+ "queue" => {
66
+ 'name' => 'queue_name1',
67
+ 'durable' => true,
68
+ 'auto_delete' => true
69
+ }
70
+ }
71
+ mock_queue = mock(:queue)
72
+ mock_queue.should_receive(:subscribe).with({})
73
+ MQ.should_receive(:queue).with('queue_name1', {
74
+ :durable => true,
75
+ :auto_delete => true
76
+ }).and_return(mock_queue)
77
+ @sub1.subscribe do |head, msg|
78
+ fail "ここはすぐには実行されないはず"
79
+ end
80
+ end
81
+
82
+ it "queueとexchangeで接続する場合" do
83
+ @sub1.config = {
84
+ "queue" => {
85
+ 'name' => 'queue_name1',
86
+ 'durable' => true,
87
+ 'auto_delete' => true
88
+ },
89
+ "exchange" => {
90
+ 'type' => 'fanout',
91
+ 'name' => 'exhange_name1'
92
+ },
93
+ "subscribe" => {
94
+ 'ack' => true
95
+ }
96
+ }
97
+ mock_exchange = mock(:exchange)
98
+ mock_binding = mock(:binding)
99
+ mock_binding.should_receive(:subscribe).with({:ack => true})
100
+ mock_queue = mock(:queue)
101
+ mock_queue.should_receive(:bind).with(mock_exchange).and_return(mock_binding)
102
+ MQ.should_receive(:queue).with('queue_name1', {
103
+ :durable => true,
104
+ :auto_delete => true
105
+ }).and_return(mock_queue)
106
+ MQ.should_receive(:fanout).with('exhange_name1', {}).
107
+ and_return(mock_exchange)
108
+ @sub1.subscribe do |head, msg|
109
+ fail "ここはすぐには実行されないはず"
110
+ end
111
+ end
112
+
113
+ it "routing_keyで受け取る場合" do
114
+ @sub1.config = {
115
+ "queue" => {
116
+ 'name' => 'queue_name1',
117
+ 'durable' => true,
118
+ 'auto_delete' => true
119
+ },
120
+ "exchange" => {
121
+ 'name' => 'exhange_name1',
122
+ 'key' => 'xxxx'
123
+ },
124
+ "subscribe" => {
125
+ 'ack' => true
126
+ }
127
+ }
128
+ mock_exchange = mock(:exchange)
129
+ mock_binding = mock(:binding)
130
+ mock_binding.should_receive(:subscribe).with({:ack => true})
131
+ mock_queue = mock(:queue)
132
+ mock_queue.should_receive(:bind).
133
+ with(mock_exchange, :key => 'xxxx').and_return(mock_binding)
134
+ MQ.should_receive(:queue).with('queue_name1', {
135
+ :durable => true,
136
+ :auto_delete => true
137
+ }).and_return(mock_queue)
138
+ MQ.should_receive(:direct).with('exhange_name1', {}).
139
+ and_return(mock_exchange)
140
+ @sub1.subscribe do |head, msg|
141
+ fail "ここはすぐには実行されないはず"
142
+ end
143
+ end
144
+
145
+ it "MessagePackでシリアライズされている" do
146
+ @sub1.config = {
147
+ "queue" => {
148
+ 'name' => 'queue_name1',
149
+ 'durable' => true,
150
+ 'auto_delete' => true
151
+ },
152
+ "exchange" => {
153
+ 'type' => 'fanout',
154
+ 'name' => 'exhange_name1'
155
+ },
156
+ "subscribe" => {
157
+ 'ack' => true
158
+ }
159
+ }
160
+ pack_msg = "msg".to_msgpack
161
+ mock_queue = mock(:queue)
162
+ mock_header = mock(:header)
163
+ @sub1.should_receive(:subscribed).and_return(mock_queue)
164
+ mock_header.should_receive(:ack)
165
+ mock_queue.should_receive(:subscribe).and_yield(mock_header, pack_msg)
166
+ lambda {
167
+ @sub1.subscribe do |head, msg|
168
+ msg.should == "msg"
169
+ end
170
+ }.should_not raise_error
171
+ end
172
+
173
+ it "MessagePackでシリアライズされていない場合" do
174
+ @sub1.config = {
175
+ "queue" => {
176
+ 'name' => 'queue_name1',
177
+ 'durable' => true,
178
+ 'auto_delete' => true
179
+ },
180
+ "exchange" => {
181
+ 'type' => 'fanout',
182
+ 'name' => 'exhange_name1'
183
+ },
184
+ "subscribe" => {
185
+ 'ack' => true
186
+ }
187
+ }
188
+ mock_queue = mock(:queue)
189
+ @sub1.should_receive(:subscribed).and_return(mock_queue)
190
+ mock_queue.should_receive(:subscribe).and_yield("head", "msg")
191
+ lambda {
192
+ @sub1.subscribe do |head, msg|
193
+ end
194
+ }.should raise_error
195
+ end
196
+
197
+ end
198
+
199
+ end
@@ -0,0 +1 @@
1
+ --exclude "spec/*,gems/*"
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+
6
+ require 'mm_mq'
7
+ require RUBY_PLATFORM == 'java' ? 'msgpack_pure' : 'msgpack'
8
+ require 'spec'
9
+ require 'spec/autorun'
10
+
11
+
12
+ Spec::Runner.configure do |config|
13
+
14
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mm_mq
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 7
10
+ version: 0.1.7
11
+ platform: ruby
12
+ authors:
13
+ - monkey-magic
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-18 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: msgpack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 9
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 3
34
+ version: 0.4.3
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: totty-amqp
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 97
46
+ segments:
47
+ - 0
48
+ - 6
49
+ - 7
50
+ - 1
51
+ version: 0.6.7.1
52
+ type: :runtime
53
+ version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 13
63
+ segments:
64
+ - 1
65
+ - 2
66
+ - 9
67
+ version: 1.2.9
68
+ type: :development
69
+ version_requirements: *id003
70
+ description: MQ library of MonmeyMagic
71
+ email: monkey-magic@ec-one.com
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files:
77
+ - LICENSE
78
+ - README.rdoc
79
+ files:
80
+ - .document
81
+ - .gitignore
82
+ - LICENSE
83
+ - README.rdoc
84
+ - Rakefile
85
+ - VERSION
86
+ - lib/mm_mq.rb
87
+ - lib/mm_mq/hash_ext.rb
88
+ - lib/mm_mq/publishable.rb
89
+ - lib/mm_mq/subscribable.rb
90
+ - mm_mq.gemspec
91
+ - spec/mm_mq/publishable_spec.rb
92
+ - spec/mm_mq/subscribable_spec.rb
93
+ - spec/rcov.opts
94
+ - spec/spec.opts
95
+ - spec/spec_helper.rb
96
+ has_rdoc: true
97
+ homepage: ""
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirements: []
124
+
125
+ rubyforge_project:
126
+ rubygems_version: 1.3.7
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: MQ library of MonmeyMagic
130
+ test_files:
131
+ - spec/mm_mq/publishable_spec.rb
132
+ - spec/mm_mq/subscribable_spec.rb
133
+ - spec/spec_helper.rb