gorg_service 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b61b732f42639dd14b22f68e32bf318e598c10f1
4
- data.tar.gz: 22e05f3bf14224e468001802a6a59fd28b40f9b9
3
+ metadata.gz: 73ff949459f530d6de5e500a065a69082b633c13
4
+ data.tar.gz: f33f7599bf4a38afd2c3c3070757109c45e69f61
5
5
  SHA512:
6
- metadata.gz: a407353c48c6c6ddacb7f8ea95c0bd65bf5b289cb95eb4820a1000ffdc6f8639456c1c63a1ce4221f88cd20f410c5b9fc42ab50e93f07d1fb3f0c7ea94604979
7
- data.tar.gz: 00b386980b7eb2e235218f890cbe7194eb9323996c99c6b06eeb5a074e5ade05c40f2d7924ae750da6594cc2cc02eb54ec5a76a59fdfcef8f3a7b7309ee788b1
6
+ metadata.gz: 1d857d88511bd782177f455248b3ce26d9847916250b8f29658c7e678344fbbabc015570d54e4f5d54e8b461aa706c46578eebb42b696f7bfec9e3891d218255
7
+ data.tar.gz: bcfb9af25144da6982cabc973c5d1ffb9c70502987bc6faeb7263ce8ad7f9d04fb5e9f946285f98a0e2363d17e8e9876a1d0bcc972bd99aac988f276072676b2
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gemspec
4
- gem "codeclimate-test-reporter", group: :test, require: nil
5
- gem 'reek', '~> 4.0'
3
+ gemspec
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # GorgService
2
2
  [![Code Climate](https://codeclimate.com/github/Zooip/gorg_service/badges/gpa.svg)](https://codeclimate.com/github/Zooip/gorg_service) [![Test Coverage](https://codeclimate.com/github/Zooip/gorg_service/badges/coverage.svg)](https://codeclimate.com/github/Zooip/gorg_service/coverage) [![Build Status](https://travis-ci.org/Zooip/gorg_service.svg?branch=master)](https://travis-ci.org/Zooip/gorg_service) [![Gem Version](https://badge.fury.io/rb/gorg_service.svg)](https://badge.fury.io/rb/gorg_service) [![Dependency Status](https://gemnasium.com/badges/github.com/Zooip/gorg_service.svg)](https://gemnasium.com/github.com/Zooip/gorg_service)
3
+
3
4
  Standard RabbitMQ bot used in Gadz.org SOA
4
5
 
5
6
  ## Installation
@@ -52,6 +53,10 @@ GorgService.configure do |c|
52
53
  # maximum number of try before discard a message
53
54
  # c.rabbitmq_max_attempts = 48 # 24h with default deferring delay
54
55
  #
56
+ # The routing key used when sending a message to the central log system (Hardfail or Warning)
57
+ # Central logging is disable if nil
58
+ # c.log_routing_key = nil
59
+ #
55
60
  # Routing hash
56
61
  # map routing_key of received message with MessageHandler
57
62
  # exemple:
@@ -76,8 +81,7 @@ my_service.run
76
81
  When running, GorgService act as a consumer on Gadz.org RabbitMQ network.
77
82
  It bind its queue on the main exchange and subscribes to routing keys defines in `message_handler_map`
78
83
 
79
- Each received message will be routed to the corresponding `MessageHandler`
80
- > **Warning** : RabbitMQ wildcards characters `#` and `*`are NOT supported for now
84
+ Each received message will be routed to the corresponding `MessageHandler`. AMQP wildcards are supported.The first key to match the incomiing routing key will be used.
81
85
 
82
86
  A `MessageHandler` is a kind of controller. This is where you put the message is processed.
83
87
  A `MessageHandler` expect a `GorgService::Message` as param of its `initializer`method.
data/gorg_service.gemspec CHANGED
@@ -28,12 +28,11 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_dependency 'bunny', '~> 2.2', '>= 2.2.2'
30
30
  spec.add_dependency 'json-schema', '~> 2.6'
31
+ spec.add_dependency 'gorg_message_sender', '~> 0'
31
32
 
32
33
  spec.add_development_dependency "bundler", "~> 1.11"
33
34
  spec.add_development_dependency "rake", "~> 10.0"
34
35
  spec.add_development_dependency "rspec", "~> 3.0"
35
- spec.add_development_dependency "codeclimate-test-reporter", "~> 3.0"
36
+ spec.add_development_dependency "codeclimate-test-reporter", "~> 0.5.0"
36
37
  spec.add_development_dependency 'bogus', '~> 0.1.6'
37
- spec.add_development_dependency 'bunny-mock', '~> 1.4'
38
- spec.add_development_dependency 'byebug', '~> 9.0'
39
38
  end
data/lib/gorg_service.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "gorg_message_sender"
1
2
  require "gorg_service/configuration"
2
3
  require "gorg_service/version"
3
4
  require "gorg_service/errors"
@@ -5,9 +6,12 @@ require "gorg_service/listener"
5
6
  require "gorg_service/message"
6
7
  require "gorg_service/message_handler"
7
8
 
9
+ #Duplicate GorgMessageSender to avoid configuration conflict
10
+ RabbitmqProducer=GorgMessageSender.dup
11
+
8
12
  class GorgService
9
13
  def initialize(listener: nil, bunny_session: nil)
10
-
14
+
11
15
  @bunny_session= bunny_session || Bunny.new(
12
16
  :hostname => GorgService.configuration.rabbitmq_host,
13
17
  :port => GorgService.configuration.rabbitmq_port,
@@ -23,7 +27,25 @@ class GorgService
23
27
  exchange_name: GorgService.configuration.rabbitmq_exchange_name,
24
28
  deferred_time: GorgService.configuration.rabbitmq_deferred_time,
25
29
  max_attempts: GorgService.configuration.rabbitmq_max_attempts,
30
+ log_routing_key: GorgService.configuration.log_routing_key
26
31
  )
32
+
33
+ RabbitmqProducer.configure do |c|
34
+ # Id used to set the event_sender_id
35
+ c.application_id = GorgService.configuration.application_id
36
+
37
+ # RabbitMQ network and authentification
38
+ c.host = GorgService.configuration.rabbitmq_host
39
+ c.port = GorgService.configuration.rabbitmq_port
40
+ c.vhost = GorgService.configuration.rabbitmq_vhost
41
+ c.user = GorgService.configuration.rabbitmq_user
42
+ c.password = GorgService.configuration.rabbitmq_password
43
+
44
+ # Exchange configuration
45
+ c.exchange_name = GorgService.configuration.rabbitmq_exchange_name
46
+ c.durable_exchange= true
47
+ end
48
+
27
49
  end
28
50
 
29
51
  def run
@@ -27,7 +27,8 @@ class GorgService
27
27
  :rabbitmq_user,
28
28
  :rabbitmq_password,
29
29
  :rabbitmq_vhost,
30
- :message_handler_map
30
+ :message_handler_map,
31
+ :log_routing_key
31
32
 
32
33
 
33
34
  def initialize
@@ -43,6 +44,7 @@ class GorgService
43
44
  @rabbitmq_password = nil
44
45
  @rabbitmq_vhost = "/"
45
46
  @rabbitmq_max_attempts = 48 #24h with default timeout
47
+ @log_routing_key = nil
46
48
  end
47
49
  end
48
50
  end
@@ -6,75 +6,93 @@ require "bunny"
6
6
  class GorgService
7
7
  class Listener
8
8
 
9
- def initialize(bunny_session: nil,queue_name: "gapps", exchange_name: nil, message_handler_map: {default: DefaultMessageHandler}, deferred_time: 1800000, max_attempts: 48)
9
+ def initialize(bunny_session: nil,queue_name: "gapps", exchange_name: nil, message_handler_map: {default: DefaultMessageHandler}, deferred_time: 1800000, max_attempts: 48,log_routing_key:nil)
10
10
  @queue_name=queue_name
11
11
  @exchange_name=exchange_name
12
12
  @message_handler_map=message_handler_map
13
13
  @deferred_time=deferred_time
14
14
  @max_attempts=max_attempts
15
15
  @rmq_connection=bunny_session
16
+ @log_routing_key=log_routing_key
16
17
  end
17
18
 
18
19
  def listen
19
20
 
20
- conn = rmq_connection
21
- ch = conn.create_channel
22
- x = ch.topic(@exchange_name, :durable => true)
23
- q = ch.queue(@queue_name, :durable => true)
24
-
25
- @message_handler_map.keys.each do |routing_key|
26
- q.bind(@exchange_name, :routing_key => routing_key)
27
- end
28
-
29
- q.bind(@exchange_name, :routing_key => '#')
30
-
31
- ch.prefetch(1)
32
-
33
- q.subscribe(:manual_ack => true) do |delivery_info, properties, body|
21
+ set_rabbitmq_env
22
+
23
+ @q.subscribe(:manual_ack => true) do |delivery_info, _properties, body|
34
24
  routing_key=delivery_info[:routing_key]
35
25
  puts " [#] Received message with routing key #{routing_key} containing : #{body}"
36
- message_handler=message_handler_for routing_key
37
- message=Message.parse_body(body)
38
-
39
- call_message_handler(message_handler, message)
40
-
41
- ch.ack(delivery_info.delivery_tag)
26
+ process_message(body,routing_key)
27
+ @ch.ack(delivery_info.delivery_tag)
42
28
  end
43
-
44
29
  end
45
30
 
31
+ protected
32
+
46
33
  def rmq_connection
47
34
  @rmq_connection.start unless @rmq_connection.connected?
48
35
  @rmq_connection
49
36
  end
50
37
 
51
- def call_message_handler(message_handler, message)
52
- begin
53
- raise HardfailError.new(), "Routing error" unless message_handler
54
- message_handler.new(message)
38
+ def set_rabbitmq_env
39
+ conn = rmq_connection
40
+ @ch = conn.create_channel
41
+ @ch.prefetch(1)
42
+ @ch.topic(@exchange_name, :durable => true)
43
+ @q = @ch.queue(@queue_name, :durable => true)
55
44
 
45
+ @message_handler_map.keys.each do |routing_key|
46
+ @q.bind(@exchange_name, :routing_key => routing_key)
47
+ end
48
+ end
49
+
50
+ def process_message(body,routing_key)
51
+ message=nil
52
+ incomming_message_error_count=0
53
+ begin
54
+ message_handler=message_handler_for routing_key
55
+ raise HardfailError.new("Routing error : No message handler finded for this routing key") unless message_handler
56
+
57
+ begin
58
+ message=Message.parse_body(body)
59
+ rescue JSON::ParserError => e
60
+ raise HardfailError.new("JSON Parse error : Can't parse incoming message",e)
61
+ rescue JSON::Schema::ValidationError => e
62
+ raise HardfailError.new("Invalid JSON : This message does not respect Gadz.org JSON Schema",e)
63
+ end
64
+ incomming_message_error_count=message.errors.count
65
+ message_handler.new(message)
66
+ process_logging(message) if message.errors.count>incomming_message_error_count
56
67
  rescue SoftfailError => e
57
- message.log_error(e)
58
68
  process_softfail(e,message)
59
-
60
69
  rescue HardfailError => e
61
- message.log_error(e)
62
- process_hardfail(e)
70
+ process_hardfail(e,message)
63
71
  end
64
72
  end
65
73
 
66
74
  def process_softfail(e,message)
75
+ message.log_error(e)
67
76
  puts " [*] SOFTFAIL ERROR : #{e.message}"
68
77
  if message.errors.count >= @max_attempts
69
78
  puts " [*] DISCARD MESSAGE : #{message.errors.count} errors in message log"
79
+ process_hardfail(HardfailError.new("Too Much SoftError : This message reached the limit of softerror (max: #{@max_attempts})"),message)
70
80
  else
71
81
  send_to_deferred_queue(message)
72
82
  end
73
83
  end
74
84
 
75
- def process_hardfail(e)
76
- puts " [*] SOFTFAIL ERROR : #{e.message}"
77
- puts " [*] DISCARD MESSAGE"
85
+ def process_hardfail(e,message)
86
+ puts " [*] HARDFAIL ERROR : #{e.message}"
87
+ puts " [*] DISCARD MESSAGE"
88
+ if message
89
+ message.log_error(e)
90
+ process_logging(message)
91
+ end
92
+ end
93
+
94
+ def process_logging(message)
95
+ RabbitmqProducer.new.send_raw(message.to_json,@log_routing_key, verbose: true) if @log_routing_key
78
96
  end
79
97
 
80
98
  def send_to_deferred_queue(msg)
@@ -31,8 +31,7 @@ class GorgService
31
31
  @sender= sender
32
32
  end
33
33
 
34
- # Generate RabbitMQ message body
35
- def to_json
34
+ def to_h
36
35
  body={
37
36
  event_uuid: @id,
38
37
  event_name: @event,
@@ -44,7 +43,12 @@ class GorgService
44
43
  body[:errors_count]=@errors.count
45
44
  body[:errors]=@errors
46
45
  end
47
- body.to_json
46
+ body
47
+ end
48
+
49
+ # Generate RabbitMQ message body
50
+ def to_json
51
+ self.to_h.to_json
48
52
  end
49
53
 
50
54
  # Log FailError in message body
@@ -2,5 +2,5 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  class GorgService
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.0"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gorg_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Narbonne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-30 00:00:00.000000000 Z
11
+ date: 2016-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '2.6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: gorg_message_sender
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +106,14 @@ dependencies:
92
106
  requirements:
93
107
  - - "~>"
94
108
  - !ruby/object:Gem::Version
95
- version: '3.0'
109
+ version: 0.5.0
96
110
  type: :development
97
111
  prerelease: false
98
112
  version_requirements: !ruby/object:Gem::Requirement
99
113
  requirements:
100
114
  - - "~>"
101
115
  - !ruby/object:Gem::Version
102
- version: '3.0'
116
+ version: 0.5.0
103
117
  - !ruby/object:Gem::Dependency
104
118
  name: bogus
105
119
  requirement: !ruby/object:Gem::Requirement
@@ -114,34 +128,6 @@ dependencies:
114
128
  - - "~>"
115
129
  - !ruby/object:Gem::Version
116
130
  version: 0.1.6
117
- - !ruby/object:Gem::Dependency
118
- name: bunny-mock
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '1.4'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '1.4'
131
- - !ruby/object:Gem::Dependency
132
- name: byebug
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '9.0'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '9.0'
145
131
  description:
146
132
  email:
147
133
  - alexandre.narbonne@gadz.org