masstransit 0.2 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/masstransit.rb +13 -0
- data/lib/masstransit/bus.rb +84 -0
- data/lib/masstransit/config.rb +55 -0
- data/lib/masstransit/envelope.rb +15 -0
- data/lib/masstransit/exceptions.rb +0 -0
- data/lib/masstransit/message.rb +26 -0
- data/lib/masstransit/serializer.rb +25 -0
- data/lib/masstransit/transports/amqp.rb +84 -0
- data/lib/masstransit/urn.rb +14 -0
- metadata +16 -7
data/lib/masstransit.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support' unless defined?(ActiveSupport)
|
3
|
+
|
4
|
+
here = File.expand_path(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
$LOAD_PATH << "#{here}/masstransit"
|
7
|
+
require 'bus'
|
8
|
+
require 'config'
|
9
|
+
require 'message'
|
10
|
+
require 'serializer'
|
11
|
+
require 'envelope'
|
12
|
+
require 'transports/amqp'
|
13
|
+
require 'urn'
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module MassTransit
|
2
|
+
#The bus abstracts the desired transportation, and manages the callbacks
|
3
|
+
#orchestrates the threading
|
4
|
+
#
|
5
|
+
#three main queues (data, control, poison)
|
6
|
+
class Bus
|
7
|
+
def initialize(conf)
|
8
|
+
@subscriptions = {}
|
9
|
+
@serializer = conf.serializer
|
10
|
+
@transport = conf.transport
|
11
|
+
@queue = conf.queue
|
12
|
+
|
13
|
+
@transport.open(conf)
|
14
|
+
end
|
15
|
+
|
16
|
+
#this will register an exchange in rabbit for the 'message_name'
|
17
|
+
#and then bind the queue to that exchange. it then sets
|
18
|
+
# the subscriptions[message_name] to the callback provided
|
19
|
+
def subscribe(message_name, &block)
|
20
|
+
@subscriptions = {} if @subscriptions.nil?
|
21
|
+
consumers = @subscriptions[message_name]
|
22
|
+
consumers = [] if consumers.nil?
|
23
|
+
consumers << block
|
24
|
+
@subscriptions[message_name] = consumers
|
25
|
+
@transport.bind message_name
|
26
|
+
end
|
27
|
+
|
28
|
+
#this will unregister the queue with the exchange in rabbitmq
|
29
|
+
#for the message_name. It then removes the callbacks in the
|
30
|
+
#subscriptions
|
31
|
+
def unsubscribe(message_name)
|
32
|
+
@transport.unbind(message_name, @queue)
|
33
|
+
|
34
|
+
#has key check
|
35
|
+
@subscriptions.delete(message_name)
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
#tells the bus to start listening for messages
|
40
|
+
#this method blocks forver. Need to implement
|
41
|
+
#better ctrl-c support
|
42
|
+
def start()
|
43
|
+
#start listening
|
44
|
+
@transport.monitor do |rmsg|
|
45
|
+
consume(rmsg)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def close()
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
#this will publish the message object to an exchange in rabbitmq
|
54
|
+
#that is equal to the message class name. this is a direct concept
|
55
|
+
#from .net and should be adopted into a more ruby manner
|
56
|
+
def publish(message)
|
57
|
+
envelope = @transport.create_message(message, @serializer)
|
58
|
+
data = @serializer.serialize(envelope)
|
59
|
+
|
60
|
+
@transport.publish(envelope.MessageType, data) #exchange?
|
61
|
+
end
|
62
|
+
|
63
|
+
#takes a rabbitmq message, strips off the noise and gets back to an
|
64
|
+
#envelope
|
65
|
+
def consume(rmsg)
|
66
|
+
data = @transport.get_message(rmsg)
|
67
|
+
#payload is a string
|
68
|
+
env = @serializer.deserialize data
|
69
|
+
puts 'oeuaoeusatoehuntsaoheuntsahoeusnth'
|
70
|
+
puts env
|
71
|
+
deliver(env)
|
72
|
+
end
|
73
|
+
|
74
|
+
#for local distribution
|
75
|
+
def deliver(env)
|
76
|
+
consumers = @subscriptions[env.MessageType]
|
77
|
+
consumers = [] if consumers.nil?
|
78
|
+
consumers.each do |c|
|
79
|
+
obj = @serializer.deserialize(env.Message)
|
80
|
+
c.call obj
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'transports/amqp'
|
3
|
+
require 'serializer'
|
4
|
+
|
5
|
+
module MassTransit
|
6
|
+
#A class that groups all of the configuration options and provides defaults
|
7
|
+
#Currently AMQP is the only transport option
|
8
|
+
class Config
|
9
|
+
attr_accessor :server
|
10
|
+
attr_accessor :port
|
11
|
+
attr_accessor :vdir
|
12
|
+
attr_accessor :user
|
13
|
+
attr_accessor :password
|
14
|
+
attr_accessor :insist
|
15
|
+
attr_accessor :transport
|
16
|
+
attr_accessor :serializer
|
17
|
+
attr_accessor :queue
|
18
|
+
|
19
|
+
def initialize()
|
20
|
+
@server = 'localhost'
|
21
|
+
@port = 5672
|
22
|
+
@vdir = '/'
|
23
|
+
@user = 'guest'
|
24
|
+
@password = 'guest'
|
25
|
+
@insist = true
|
26
|
+
@transport = Amqp.new()
|
27
|
+
@serializer = Serializer.new
|
28
|
+
@queue = 'default_queue'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Sample Config File
|
33
|
+
# ---
|
34
|
+
# server : localhost
|
35
|
+
# port : 5672
|
36
|
+
# vdir : /
|
37
|
+
# user : guest
|
38
|
+
# password : guest
|
39
|
+
# insist: true def load_config(file_name)
|
40
|
+
def MassTransit.load_config(file_name)
|
41
|
+
o = YAML::load_file(file_name)
|
42
|
+
cfg = Config.new
|
43
|
+
|
44
|
+
cfg.server = o['server']
|
45
|
+
cfg.port = o['port']
|
46
|
+
cfg.vdir = o['vdir']
|
47
|
+
cfg.user = o['user']
|
48
|
+
cfg.password = o['password']
|
49
|
+
cfg.insist = o['insist']
|
50
|
+
cfg.queue = o['queue']
|
51
|
+
|
52
|
+
return cfg
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module MassTransit
|
2
|
+
#a simple class to wrap the message and name
|
3
|
+
class Envelope
|
4
|
+
attr_accessor :MessageType
|
5
|
+
attr_accessor :Message
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
end
|
9
|
+
|
10
|
+
# def initialize(message_name, body)
|
11
|
+
# @message_name = message_name
|
12
|
+
# @body = body
|
13
|
+
# end
|
14
|
+
end
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module MassTransit
|
4
|
+
|
5
|
+
#creates a method missing style dictionary for when
|
6
|
+
#i don't have the actual type availible
|
7
|
+
class Message
|
8
|
+
attr_accessor :hash
|
9
|
+
|
10
|
+
def initialize(hash)
|
11
|
+
@hash = hash
|
12
|
+
@o = OpenStruct.new hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(name, *args)
|
16
|
+
value = @o.send name, args
|
17
|
+
if value.class == Hash
|
18
|
+
value = Message.new value
|
19
|
+
end
|
20
|
+
return value unless value.nil?
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'ostruct'
|
3
|
+
# may want to write my own to change the json_class bit
|
4
|
+
#http://flori.github.com/json/doc/classes/Object.html#method-i-to_json
|
5
|
+
#look at the source and hack! whoot whoot
|
6
|
+
|
7
|
+
module MassTransit
|
8
|
+
|
9
|
+
class Serializer
|
10
|
+
def serialize(env)
|
11
|
+
#enforce that env is an Envelope
|
12
|
+
return ActiveSupport::JSON.encode env
|
13
|
+
end
|
14
|
+
|
15
|
+
#returns an Envelope
|
16
|
+
def deserialize(data)
|
17
|
+
result = ActiveSupport::JSON.decode(data)
|
18
|
+
|
19
|
+
result = MassTransit::Message.new(result)
|
20
|
+
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'bunny'
|
2
|
+
|
3
|
+
module MassTransit
|
4
|
+
#The wrapper class on top of AMQP, that provides the standard
|
5
|
+
#masstransit 'transport' api
|
6
|
+
class Amqp
|
7
|
+
|
8
|
+
#opens a connection to the Amqp server
|
9
|
+
def open(config)
|
10
|
+
@client = Bunny.new(
|
11
|
+
:logging=>true,
|
12
|
+
:host => config.server,
|
13
|
+
:port => config.port,
|
14
|
+
:user => config.user,
|
15
|
+
:pass => config.password,
|
16
|
+
:vhost => config.vdir,
|
17
|
+
:insist => config.insist
|
18
|
+
)
|
19
|
+
@queue = config.queue
|
20
|
+
@client.start
|
21
|
+
end
|
22
|
+
|
23
|
+
#closes the connection to the Amqp server
|
24
|
+
def close()
|
25
|
+
@client.close()
|
26
|
+
end
|
27
|
+
|
28
|
+
#declares a queue on the server
|
29
|
+
def queue_declare(name)
|
30
|
+
@client.queue(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def queue_delete(name)
|
34
|
+
#how to?
|
35
|
+
end
|
36
|
+
|
37
|
+
#binds the queue to the exchange
|
38
|
+
def bind(exchange)
|
39
|
+
ex = @client.exchange(exchange, :type=>:fanout, :durable=>true)
|
40
|
+
q = @client.queue(@queue)
|
41
|
+
q.bind(ex)
|
42
|
+
end
|
43
|
+
|
44
|
+
#unbnids the queue from the exchange
|
45
|
+
def unbind(queue, exchange)
|
46
|
+
end
|
47
|
+
|
48
|
+
#creates a transport ready message object
|
49
|
+
def create_message(data, serializer)
|
50
|
+
msg_name = data.class.name.gsub("::",".")
|
51
|
+
msg = data
|
52
|
+
|
53
|
+
env = Envelope.new
|
54
|
+
env.MessageType = msg_name
|
55
|
+
#this needs to be a string for .net
|
56
|
+
env.Message = serializer.serialize(msg)
|
57
|
+
|
58
|
+
return env
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_message(rmsg)
|
62
|
+
return rmsg[:payload]
|
63
|
+
end
|
64
|
+
|
65
|
+
def monitor(&block)
|
66
|
+
#basic consume / pop loop here
|
67
|
+
q = @client.queue(@queue)
|
68
|
+
q.subscribe(:consumer_tag => 'testtag1', :timeout => 30) do |msg|
|
69
|
+
block.call msg
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
#pushes the message onto the exchange
|
75
|
+
def send(queue, data)
|
76
|
+
@client.queue(queue).publish(data)
|
77
|
+
end
|
78
|
+
|
79
|
+
def publish(exchange, data)
|
80
|
+
ex = @client.exchange(exchange, :type=>:fanout, :durable=>true)
|
81
|
+
ex.publish(data)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: masstransit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- ACM,PBG,LEGO
|
@@ -14,7 +15,7 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-12 00:00:00 -06:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
@@ -39,8 +40,16 @@ extensions: []
|
|
39
40
|
|
40
41
|
extra_rdoc_files: []
|
41
42
|
|
42
|
-
files:
|
43
|
-
|
43
|
+
files:
|
44
|
+
- ./lib/masstransit/bus.rb
|
45
|
+
- ./lib/masstransit/config.rb
|
46
|
+
- ./lib/masstransit/envelope.rb
|
47
|
+
- ./lib/masstransit/exceptions.rb
|
48
|
+
- ./lib/masstransit/message.rb
|
49
|
+
- ./lib/masstransit/serializer.rb
|
50
|
+
- ./lib/masstransit/transports/amqp.rb
|
51
|
+
- ./lib/masstransit/urn.rb
|
52
|
+
- ./lib/masstransit.rb
|
44
53
|
has_rdoc: true
|
45
54
|
homepage: http://www.masstransit.com
|
46
55
|
licenses: []
|
@@ -71,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
80
|
requirements: []
|
72
81
|
|
73
82
|
rubyforge_project: masstransit
|
74
|
-
rubygems_version: 1.
|
83
|
+
rubygems_version: 1.4.2
|
75
84
|
signing_key:
|
76
85
|
specification_version: 3
|
77
86
|
summary: a simple message framework
|