cloudist 0.4.4 → 0.5.0

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.
@@ -2,27 +2,27 @@ require "active_support"
2
2
  module Cloudist
3
3
  class Listener
4
4
  include ActiveSupport::Callbacks
5
-
5
+
6
6
  attr_reader :job_queue_name, :payload
7
7
  class_attribute :job_queue_names
8
-
8
+
9
9
  class << self
10
10
  def listen_to(*job_queue_names)
11
11
  self.job_queue_names = job_queue_names.map { |q| Utils.reply_prefix(q) }
12
12
  end
13
-
13
+
14
14
  def subscribe(queue_name)
15
15
  raise RuntimeError, "You can't subscribe until EM is running" unless EM.reactor_running?
16
-
16
+
17
17
  reply_queue = Cloudist::ReplyQueue.new(queue_name)
18
18
  reply_queue.subscribe do |request|
19
19
  instance = Cloudist.listener_instances[queue_name] ||= new
20
20
  instance.handle_request(request)
21
21
  end
22
-
22
+
23
23
  queue_name
24
24
  end
25
-
25
+
26
26
  def before(*args, &block)
27
27
  set_callback(:call, :before, *args, &block)
28
28
  end
@@ -31,16 +31,16 @@ module Cloudist
31
31
  set_callback(:call, :after, *args, &block)
32
32
  end
33
33
  end
34
-
34
+
35
35
  define_callbacks :call, :rescuable => true
36
-
36
+
37
37
  def handle_request(request)
38
38
  @payload = request.payload
39
39
  key = [payload.message_type.to_s, payload.headers[:event]].compact.join(':')
40
-
40
+
41
41
  meth, *args = handle_key(key)
42
-
43
- if meth.present? && self.respond_to?(meth)
42
+
43
+ if meth && self.respond_to?(meth)
44
44
  if method(meth).arity <= args.size
45
45
  call(meth, args.first(method(meth).arity))
46
46
  else
@@ -48,19 +48,19 @@ module Cloudist
48
48
  end
49
49
  end
50
50
  end
51
-
51
+
52
52
  def id
53
53
  payload.id
54
54
  end
55
-
55
+
56
56
  def data
57
57
  payload.body
58
58
  end
59
-
59
+
60
60
  def handle_key(key)
61
61
  key = key.split(':', 2)
62
62
  return [nil, nil] if key.empty?
63
-
63
+
64
64
  method_and_args = [key.shift.to_sym]
65
65
  case method_and_args[0]
66
66
  when :event
@@ -68,33 +68,33 @@ module Cloudist
68
68
  method_and_args = [key.shift]
69
69
  end
70
70
  method_and_args << key
71
-
71
+
72
72
  when :progress
73
73
  method_and_args << payload.progress
74
74
  method_and_args << payload.description
75
-
75
+
76
76
  when :runtime
77
77
  method_and_args << payload.runtime
78
-
78
+
79
79
  when :reply
80
-
80
+
81
81
  when :update
82
-
82
+
83
83
  when :error
84
84
  # method_and_args << Cloudist::SafeError.new(payload)
85
85
  method_and_args << Hashie::Mash.new(payload.body)
86
-
86
+
87
87
  when :log
88
88
  method_and_args << payload.message
89
89
  method_and_args << payload.level
90
-
90
+
91
91
  else
92
92
  method_and_args << data if method(method_and_args[0]).arity == 1
93
93
  end
94
-
94
+
95
95
  return method_and_args
96
96
  end
97
-
97
+
98
98
  def call(meth, args)
99
99
  run_callbacks :call do
100
100
  if args.empty?
@@ -104,30 +104,30 @@ module Cloudist
104
104
  end
105
105
  end
106
106
  end
107
-
107
+
108
108
  def progress(pct)
109
109
  # :noop
110
110
  end
111
-
111
+
112
112
  def runtime(seconds)
113
113
  # :noop
114
114
  end
115
-
115
+
116
116
  def event(type)
117
117
  # :noop
118
118
  end
119
-
119
+
120
120
  def log(message, level)
121
121
  # :noop
122
122
  end
123
-
123
+
124
124
  def error(e)
125
125
  # :noop
126
126
  end
127
-
127
+
128
128
  end
129
-
129
+
130
130
  class GenericListener < Listener
131
-
131
+
132
132
  end
133
133
  end
@@ -1,49 +1,49 @@
1
1
  module Cloudist
2
2
  class Message
3
3
  include Cloudist::Encoding
4
-
4
+
5
5
  attr_reader :body, :headers, :id, :timestamp
6
-
6
+
7
7
  # Expects body to be decoded
8
8
  def initialize(body, headers = {})
9
9
  @body = Hashie::Mash.new(body.dup)
10
-
10
+
11
11
  @id ||= headers[:message_id] || headers[:id] && headers.delete(:id) || UUID.generate
12
12
  @headers = Hashie::Mash.new(headers.dup)
13
-
13
+
14
14
  @timestamp = Time.now.utc.to_f
15
-
15
+
16
16
  update_headers(headers)
17
17
  end
18
-
18
+
19
19
  alias_method :data, :body
20
-
20
+
21
21
  def update_headers(new_headers = {})
22
22
  update_headers!
23
23
  headers.merge!(new_headers)
24
24
  end
25
-
25
+
26
26
  def update_headers!
27
27
  headers[:ttl] ||= Cloudist::DEFAULT_TTL
28
28
  headers[:timestamp] = timestamp
29
29
  headers[:message_id] ||= id
30
30
  headers[:message_type] = 'message'
31
31
  headers[:queue_name] ||= 'test'
32
-
32
+
33
33
  headers.each { |k,v| headers[k] = v.to_s }
34
34
  end
35
-
35
+
36
36
  # Convenience method for replying
37
37
  # Constructs a reply message and publishes it
38
38
  def reply(body, reply_headers = {})
39
39
  raise RuntimeError, "Cannot reply to an unpublished message" unless published?
40
-
40
+
41
41
  msg = Message.new(body, reply_headers)
42
42
  msg.set_reply_header
43
43
  reply_q = Cloudist::ReplyQueue.new(headers[:queue_name])
44
44
  msg.publish(reply_q)
45
45
  end
46
-
46
+
47
47
  # Publishes this message to the exchange or queue
48
48
  # Queue should be a Cloudist::Queue object responding to #publish
49
49
  def publish(queue)
@@ -53,45 +53,45 @@ module Cloudist
53
53
  update_headers!
54
54
  queue.publish(self)
55
55
  end
56
-
56
+
57
57
  def update_published_date!
58
58
  headers[:published_on] = Time.now.utc.to_f
59
59
  end
60
-
60
+
61
61
  # This is so we can reply back to the sender
62
62
  def set_queue_name_header(queue)
63
63
  update_headers(:queue_name => queue.name)
64
64
  end
65
-
65
+
66
66
  def published?
67
67
  @published ||= !!@headers.published_on
68
68
  end
69
-
69
+
70
70
  def created_at
71
71
  headers.timestamp ? Time.at(headers.timestamp.to_f) : timestamp
72
72
  end
73
-
73
+
74
74
  def published_at
75
75
  headers[:published_on] ? Time.at(headers[:published_on].to_f) : timestamp
76
76
  end
77
-
77
+
78
78
  def latency
79
79
  (published_at.to_f - created_at.to_f)
80
80
  end
81
-
81
+
82
82
  def encoded
83
83
  [encode(body), {:headers => headers}]
84
84
  end
85
-
85
+
86
86
  def inspect
87
87
  "<#{self.class.name} id=#{id}>"
88
88
  end
89
-
89
+
90
90
  private
91
-
91
+
92
92
  def set_reply_header
93
93
  headers[:message_type] = 'reply'
94
94
  end
95
-
95
+
96
96
  end
97
97
  end
@@ -1,29 +1,29 @@
1
1
  module Cloudist
2
2
  autoload :Singleton, 'singleton'
3
-
3
+
4
4
  class Messaging
5
5
  include Singleton
6
-
6
+
7
7
  class << self
8
-
8
+
9
9
  def active_queues
10
10
  instance.active_queues
11
11
  end
12
-
12
+
13
13
  def add_queue(queue)
14
14
  (instance.active_queues ||= {}).merge!({queue.name.to_s => queue})
15
15
  instance.active_queues
16
16
  end
17
-
17
+
18
18
  def remove_queue(queue_name)
19
19
  (instance.active_queues ||= {}).delete(queue_name.to_s)
20
20
  instance.active_queues
21
21
  end
22
22
  end
23
-
23
+
24
24
  attr_accessor :active_queues
25
-
26
-
27
-
25
+
26
+
27
+
28
28
  end
29
29
  end
@@ -2,81 +2,81 @@ module Cloudist
2
2
  class Payload
3
3
  include Utils
4
4
  include Encoding
5
-
5
+
6
6
  attr_reader :body, :headers, :amqp_headers, :timestamp
7
-
7
+
8
8
  def initialize(body, headers = {})
9
9
  @published = false
10
10
  @timestamp = Time.now.to_f
11
-
11
+
12
12
  body = decode(body) if body.is_a?(String)
13
13
  @body = Hashie::Mash.new(decode(body))
14
14
  @headers = Hashie::Mash.new(headers)
15
15
  @amqp_headers = {}
16
16
  # puts "Initialised Payload: #{id}"
17
-
17
+
18
18
  parse_headers!
19
19
  end
20
-
20
+
21
21
  def find_or_create_id
22
- if headers["message_id"].present?
22
+ if headers["message_id"]
23
23
  headers.message_id
24
24
  else
25
25
  UUID.generate
26
26
  end
27
27
  end
28
-
28
+
29
29
  def id
30
30
  find_or_create_id
31
31
  end
32
-
32
+
33
33
  def to_a
34
34
  [encode(body), {:headers => encoded_headers}]
35
35
  end
36
-
36
+
37
37
  def parse_headers!
38
38
  headers[:published_on] ||= body.delete("timestamp") || timestamp
39
39
  headers[:message_type] ||= body.delete("message_type") || 'reply'
40
-
40
+
41
41
  headers[:ttl] ||= Cloudist::DEFAULT_TTL
42
42
  headers[:message_id] = id
43
-
43
+
44
44
  headers[:published_on] = headers[:published_on].to_f
45
-
45
+
46
46
  headers[:ttl] = headers[:ttl].to_i rescue -1
47
47
  headers[:ttl] = -1 if headers[:ttl] == 0
48
-
48
+
49
49
  # If this payload was received with a timestamp,
50
50
  # we don't want to override it on #timestamp
51
51
  if timestamp > headers[:published_on]
52
52
  @timestamp = headers[:published_on]
53
53
  end
54
-
54
+
55
55
  headers
56
56
  end
57
-
57
+
58
58
  def encoded_headers
59
59
  h = headers.dup
60
60
  h.each { |k,v| h[k] = v.to_s }
61
61
  return h
62
62
  end
63
-
63
+
64
64
  def set_reply_to(queue_name)
65
65
  headers[:reply_to] = reply_prefix(queue_name)
66
66
  end
67
-
67
+
68
68
  def reply_to
69
69
  headers.reply_to
70
70
  end
71
-
71
+
72
72
  def message_type
73
73
  headers.message_type
74
74
  end
75
-
75
+
76
76
  def [](key)
77
77
  self.body[key.to_s]
78
78
  end
79
-
79
+
80
80
  def method_missing(meth, *args, &blk)
81
81
  if body.has_key?(meth.to_s)
82
82
  return body[meth]
@@ -86,6 +86,6 @@ module Cloudist
86
86
  super
87
87
  end
88
88
  end
89
-
89
+
90
90
  end
91
- end
91
+ end
@@ -1,55 +1,55 @@
1
1
  module Cloudist
2
2
  class Payload
3
3
  include Utils
4
-
4
+
5
5
  attr_reader :body, :publish_opts, :headers, :timestamp
6
6
 
7
7
  def initialize(body, headers = {}, publish_opts = {})
8
8
  @publish_opts, @headers = publish_opts, Hashie::Mash.new(headers)
9
9
  @published = false
10
-
10
+
11
11
  body = parse_message(body) if body.is_a?(String)
12
-
12
+
13
13
  # raise Cloudist::BadPayload, "Expected Hash for payload" unless body.is_a?(Hash)
14
-
14
+
15
15
  @timestamp = Time.now.to_f
16
-
16
+
17
17
  @body = body
18
18
  # Hashie::Mash.new(body)
19
-
19
+
20
20
  update_headers
21
21
  end
22
22
 
23
23
  # Return message formatted as JSON and headers ready for transport in array
24
24
  def formatted
25
25
  update_headers
26
-
26
+
27
27
  [encode_message(body), publish_opts]
28
28
  end
29
-
29
+
30
30
  def id
31
31
  @id ||= event_hash.to_s
32
32
  end
33
-
33
+
34
34
  def id=(new_id)
35
35
  @id = new_id.to_s
36
36
  update_headers
37
37
  end
38
-
38
+
39
39
  def frozen?
40
40
  headers.frozen?
41
41
  end
42
-
42
+
43
43
  def freeze!
44
44
  headers.freeze
45
45
  body.freeze
46
46
  end
47
-
47
+
48
48
  def update_headers
49
49
  headers = extract_custom_headers
50
50
  (publish_opts[:headers] ||= {}).merge!(headers)
51
51
  end
52
-
52
+
53
53
  def extract_custom_headers
54
54
  raise StaleHeadersError, "Headers cannot be changed because payload has already been published" if published?
55
55
  headers[:published_on] ||= body.is_a?(Hash) && body.delete(:published_on) || Time.now.utc.to_i
@@ -60,19 +60,19 @@ module Cloudist
60
60
 
61
61
  # this value should be unique for each published/received message pair
62
62
  headers[:message_id] ||= id
63
-
63
+
64
64
  # We use JSON for message transport exclusively
65
65
  # headers[:content_type] ||= 'application/json'
66
-
66
+
67
67
  # headers[:headers][:message_type] = 'event'
68
68
  # ||= body.delete('message_type') || 'reply'
69
-
69
+
70
70
  # headers[:headers] = custom_headers
71
-
71
+
72
72
  # some strange behavior with integers makes it better to
73
73
  # convert all amqp headers to strings to avoid any problems
74
74
  headers.each { |k,v| headers[k] = v.to_s }
75
-
75
+
76
76
  headers
77
77
  end
78
78
 
@@ -88,59 +88,59 @@ module Cloudist
88
88
 
89
89
  h
90
90
  end
91
-
91
+
92
92
  def set_reply_to(queue_name)
93
93
  headers["reply_to"] = reply_name(queue_name)
94
94
  set_master_queue_name(queue_name)
95
95
  end
96
-
96
+
97
97
  def set_master_queue_name(queue_name)
98
- headers[:master_queue] = queue_name
98
+ headers[:master_queue] = queue_name
99
99
  end
100
-
100
+
101
101
  def reply_name(queue_name)
102
102
  # "#{queue_name}.#{id}"
103
103
  Utils.reply_prefix(queue_name)
104
104
  end
105
-
105
+
106
106
  def reply_to
107
107
  headers["reply_to"]
108
108
  end
109
-
109
+
110
110
  def message_type
111
111
  headers["message_type"]
112
112
  end
113
-
113
+
114
114
  def event_hash
115
115
  @event_hash ||= headers["event_hash"] || create_event_hash
116
116
  end
117
-
117
+
118
118
  def create_event_hash
119
119
  # s = Time.now.to_s + object_id.to_s + rand(100).to_s
120
120
  # Digest::MD5.hexdigest(s)
121
121
  UUID.generate
122
122
  end
123
-
123
+
124
124
  def parse_message(raw)
125
125
  # return { } unless raw
126
126
  # decode_json(raw)
127
127
  decode_message(raw)
128
128
  end
129
-
129
+
130
130
  def [](key)
131
131
  body[key]
132
132
  end
133
-
133
+
134
134
  def published?
135
135
  @published == true
136
136
  end
137
-
137
+
138
138
  def publish
139
139
  return if published?
140
140
  @published = true
141
141
  freeze!
142
142
  end
143
-
143
+
144
144
  def method_missing(meth, *args, &blk)
145
145
  if body.is_a?(Hash) && body.has_key?(meth)
146
146
  return body[meth]
@@ -150,6 +150,6 @@ module Cloudist
150
150
  super
151
151
  end
152
152
  end
153
-
153
+
154
154
  end
155
- end
155
+ end