pushyd 0.2.4 → 0.3.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: bef5122c9c7a8a4276bc0e1f735c48b65b88f156
4
- data.tar.gz: 8620fcd2277aafc9ff97c6c65ec4abe25a6f5339
3
+ metadata.gz: deac6c7be88fd0fe05c8afa55880aa29e6c4212d
4
+ data.tar.gz: 4f6a4226355bbee4a76bb489867f0b000d3455ed
5
5
  SHA512:
6
- metadata.gz: dabd44f13d11e6167bb96b1e4c3d5c044bb0394ee386b3fe6ad84882339a518cf941d6f21aaab79090decd982511cbb1b1fe50ce5df124d70ee8d0487000a945
7
- data.tar.gz: dc9779dfd1b20506840ccc799dbe5f8cac4d43daa30634ad4067a32a5a71b11b03dbdecdf4aa3a2075ba02195a6e40994da125cfb3208b8d234d4e2c6d765e38
6
+ metadata.gz: 646e19080f09c51c448189dbe5743a17a5be869670220ce740dd16d1f11ea49f060e8627ffe7ff8c83f61f21cc8d086ee3795bcdf0fce8594c2b639bc5006ffb
7
+ data.tar.gz: b707e637e0bd0e27acfd71f32c2b5db5caf146429fc1f3b9802facfe415242f0bc0222d6fb6d6a0f63ded5c9ba86b37736e9944fb2e63eb73df93a09a9c14b8f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pushyd (0.2.4)
4
+ pushyd (0.3.0)
5
5
  bunny
6
6
  chamber
7
7
  daemons
data/bin/pushyd CHANGED
@@ -39,8 +39,7 @@ begin
39
39
  puts "--- #{Conf.name} #{Conf.version}"
40
40
  puts "Environment \t #{Conf.env}"
41
41
  puts "Config files \t #{Conf.files}"
42
- puts
43
- puts "Log file \t #{Conf[:log]}"
42
+ puts "Loging to file \t #{Conf[:log]}"
44
43
  puts Conf.dump if cmd_dump
45
44
 
46
45
  rescue OptionParser::InvalidOption => e
@@ -55,9 +54,6 @@ end
55
54
  # Run daemon
56
55
  run_options = {
57
56
  ontop: false,
58
- # :dir_mode => :normal,
59
- # :dir => File.join(root, 'amine.log'),
60
- # :log_output => true,
61
57
  :backtrace => true,
62
58
  :multiple => false
63
59
  }
@@ -67,6 +63,6 @@ Daemons.run_proc('pushy-daemon', run_options) do
67
63
  require_relative "../lib/pushyd"
68
64
 
69
65
  # Start daemon
70
- puts "--- starting"
66
+ puts "--- starting daemon"
71
67
  PushyDaemon::Daemon.run
72
68
  end
data/defaults.yml CHANGED
@@ -5,9 +5,12 @@ bus:
5
5
  port: 5672
6
6
  user: guest
7
7
  pass: guest
8
- log: "pushyd.log"
8
+
9
+ log: null
10
+
9
11
  shout:
10
12
  topic: pushyd
13
+ period: 2
11
14
  # keys:
12
15
  # - tic
13
16
  # - tac
data/lib/pushyd/conf.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require "chamber"
2
2
 
3
3
  module PushyDaemon
4
-
5
4
  class ConfigMissingParameter < StandardError; end
6
5
  class ConfigParseError < StandardError; end
7
6
 
@@ -3,13 +3,11 @@ WAY_OUT = "SENT"
3
3
  WAY_IN = "RECD"
4
4
  WAY_POST = "POST"
5
5
 
6
-
7
6
  # Constants: proxy
8
7
  PROXY_MESSAGE_MAX = 1
9
8
  PROXY_USE_ACK = false
10
9
  PROXY_SCOPE = "dev"
11
10
 
12
-
13
11
  # Constants: logger
14
12
  LOG_COL_ID = 6
15
13
  LOG_TRIM_LINE = 200
@@ -18,4 +16,3 @@ LOG_FORMAT_MESSAGE = "%-6s"
18
16
  LOG_NEWLINE = "\n"
19
17
  LOG_INDENT = "\t"
20
18
  LOG_ROTATION = "daily"
21
-
data/lib/pushyd/daemon.rb CHANGED
@@ -14,14 +14,8 @@ module PushyDaemon
14
14
  # Start infinite loop
15
15
  s.shout
16
16
 
17
- rescue Errno::EACCES => e
18
- #logger.error "ABORT #{e.class}: #{e.message}"
19
- abort "ABORT #{e.class}: #{e.message}"
20
-
21
- rescue Exception => e
22
- #logger.error "ABORT #{e.class}: #{e.message}"
23
- abort "ABORT #{e.class}: #{e.message}"
24
-
17
+ rescue Errno::EACCES, Exception => e
18
+ abort "EXITING #{e.class}: #{e.message}"
25
19
  end
26
20
 
27
21
  end
@@ -2,7 +2,6 @@ require 'bunny'
2
2
  require 'securerandom'
3
3
 
4
4
  module PushyDaemon
5
-
6
5
  class EndpointConnexionContext < StandardError; end
7
6
  class EndpointConnectionError < StandardError; end
8
7
  class EndpointSubscribeContext < StandardError; end
@@ -17,17 +16,20 @@ module PushyDaemon
17
16
  # Create the logger
18
17
  @logger = PushyLogger.new(logfile, LOG_ROTATION)
19
18
  @logger.add Logger::INFO, "starting #{self.class.name.to_s}"
19
+
20
+ # Declare we're now logging
21
+ puts "#{self.class} logging to #{logfile}"
20
22
  end
21
23
 
22
24
  protected
23
25
 
24
- def error message
25
- @logger.add Logger::ERROR, "#{self.class}: #{message}"
26
+ def error message, lines = {}
27
+ @logger.add Logger::ERROR, "#{self.class}: #{message}", lines
26
28
  #raise "ABORT #{self.class}: #{message}"
27
29
  end
28
30
 
29
- def info message
30
- @logger.add Logger::INFO, "#{self.class}: #{message}"
31
+ def info message, lines = {}
32
+ @logger.add Logger::INFO, "#{self.class}: #{message}", lines
31
33
  end
32
34
 
33
35
  def message params = {}
@@ -52,8 +54,9 @@ module PushyDaemon
52
54
  end
53
55
 
54
56
  # Body (split in lines to log them separately)
55
- unless (params[:body].nil? || params[:body].empty?)
56
- JSON.pretty_generate(params[:body]).each_line do |line|
57
+ if params[:body] && params[:body].is_a?(Enumerable)
58
+ body_json = JSON.pretty_generate(params[:body])
59
+ body_json.each_line do |line|
57
60
  lines << line.rstrip
58
61
  end
59
62
  end
@@ -64,23 +67,27 @@ module PushyDaemon
64
67
  end
65
68
 
66
69
  # Start connexion to RabbitMQ
67
- def connect busconf
70
+ def connect_channel busconf
68
71
  raise PushyDaemon::EndpointConnexionContext, "invalid bus host/port" unless (busconf.is_a? Hash) &&
69
72
  busconf[:host] && busconf[:port]
70
73
 
71
- puts "connecting to #{busconf[:host]} port #{busconf[:port]}"
74
+ info "connecting to #{busconf[:host]} port #{busconf[:port]}"
72
75
  conn = Bunny.new host: (busconf[:host].to_s || "localhost").to_s,
73
76
  port: busconf[:port].to_i,
74
77
  user: busconf[:user].to_s,
75
78
  pass: busconf[:pass].to_s,
76
79
  heartbeat: :server
77
80
  conn.start
81
+
82
+ # Create channel
83
+ channel = conn.create_channel
84
+
78
85
  rescue Bunny::TCPConnectionFailedForAllHosts, Bunny::AuthenticationFailureError, AMQ::Protocol::EmptyResponseError => e
79
86
  raise PushyDaemon::EndpointConnectionError, "error connecting (#{e.class})"
80
87
  rescue Exception => e
81
88
  raise PushyDaemon::EndpointConnectionError, "unknow (#{e.inspect})"
82
89
  else
83
- return conn
90
+ return channel
84
91
  end
85
92
 
86
93
  # Declare or return the exchange for this topic
data/lib/pushyd/proxy.rb CHANGED
@@ -20,9 +20,8 @@ module PushyDaemon
20
20
  @table.align_column(5, :right)
21
21
 
22
22
  # Start connexion to RabbitMQ and create channel
23
- conn = connect Conf.bus
24
- @channel = conn.create_channel
25
- info "connected on a channel"
23
+ @channel = connect_channel Conf.bus
24
+ info "channel connected"
26
25
 
27
26
  # Check config
28
27
  config_rules = Conf[:rules]
@@ -39,7 +38,8 @@ module PushyDaemon
39
38
  end
40
39
 
41
40
  # Send config table to logs
42
- info "dumping configuration\n#{@table.to_s}"
41
+ table_lines = @table.to_s.lines
42
+ info "initialized with configuration:", table_lines
43
43
 
44
44
  rescue Bunny::TCPConnectionFailedForAllHosts => e
45
45
  error "ERROR: cannot connect to RabbitMQ hosts (#{e.inspect})"
@@ -100,7 +100,6 @@ module PushyDaemon
100
100
 
101
101
  rescue Exception => e
102
102
  error "propagate: #{e.message}"
103
-
104
103
  end
105
104
 
106
105
 
@@ -121,11 +120,11 @@ module PushyDaemon
121
120
  return utf8payload
122
121
  end
123
122
 
124
- # Handle body parse errors
125
- rescue Encoding::UndefinedConversionError => e
126
- error "parse: JSON PARSE ERROR: #{e.inspect}"
127
- return {}
128
- end
129
-
123
+ # Handle body parse errors
124
+ rescue Encoding::UndefinedConversionError => e
125
+ error "parse: JSON PARSE ERROR: #{e.inspect}"
126
+ return {}
130
127
  end
128
+
129
+ end
131
130
  end
@@ -25,12 +25,10 @@ class PushyLogger < Logger
25
25
  def add level, message, lines = {}
26
26
  level ||= Logger::DEBUG
27
27
 
28
- prefix = " | "
29
-
30
28
  if lines.is_a? Hash
31
- output = build_from_hash prefix, lines
29
+ output = build_from_hash lines
32
30
  elsif lines.is_a? Array
33
- output = build_from_array prefix, lines
31
+ output = build_from_array lines
34
32
  else
35
33
  output = []
36
34
  end
@@ -44,17 +42,19 @@ class PushyLogger < Logger
44
42
 
45
43
  protected
46
44
 
47
- def build_from_array prefix, lines
45
+ def trim_line line
46
+ line.to_s.rstrip.strip[0..LOG_TRIM_LINE]
47
+ end
48
+
49
+ def build_from_array lines
48
50
  lines.map do |value|
49
- text = value.to_s[0..LOG_TRIM_LINE]
50
- "#{prefix}#{text}"
51
+ "#{LOG_INDENT}#{trim_line(value)}"
51
52
  end
52
53
  end
53
54
 
54
- def build_from_hash prefix, lines
55
+ def build_from_hash lines
55
56
  lines.map do |name, value|
56
- text = value.to_s.strip[0..LOG_TRIM_LINE]
57
- "#{prefix}#{name}: #{text}"
57
+ "#{LOG_INDENT}#{name}: #{trim_line(value)}"
58
58
  end
59
59
  end
60
60
 
@@ -2,12 +2,11 @@ require 'yaml'
2
2
  require 'json'
3
3
 
4
4
  module PushyDaemon
5
-
6
- class ShouterResponseError < StandardError; end
7
- class ShouterChannelClosed < StandardError; end
8
- class ShouterPreconditionFailed < StandardError; end
9
- class ShouterInterrupted < StandardError; end
10
- class EndpointTopicContext < StandardError; end
5
+ class ShouterResponseError < StandardError; end
6
+ class ShouterChannelClosed < StandardError; end
7
+ class ShouterPreconditionFailed < StandardError; end
8
+ class ShouterInterrupted < StandardError; end
9
+ class EndpointTopicContext < StandardError; end
11
10
 
12
11
  class Shouter < Endpoint
13
12
 
@@ -19,25 +18,24 @@ module PushyDaemon
19
18
  @keys = []
20
19
 
21
20
  # Start connexion to RabbitMQ and create channel
22
- conn = connect Conf.bus
23
- @channel = conn.create_channel
24
- info "connected on a channel"
21
+ @channel = connect_channel Conf.bus
22
+ info "channel connected"
25
23
 
26
24
  # Check config
27
25
  config_shout = Conf[:shout]
28
- if (config_shout.is_a? Enumerable) && !config_shout.empty?
29
- @keys = config_shout[:keys] if config_shout[:keys].is_a? Array
30
- @topic = config_shout[:topic]
31
-
32
- info "found topic: #{@topic}"
33
- info "found keys: #{@keys.join(', ')}"
34
- else
35
- error "prepare: empty [shout] section"
26
+ if config_shout.empty? || (!config_shout.is_a? Enumerable)
27
+ abort "prepare: empty [shout] section"
36
28
  end
37
29
 
30
+ # Extract information
31
+ @keys = config_shout[:keys] if config_shout[:keys].is_a? Array
32
+ @topic = config_shout[:topic]
33
+ @period = config_shout[:period] || 0
34
+
38
35
  # Create exchange
39
36
  raise PushyDaemon::EndpointTopicContext unless @topic
40
37
  @exchange = @channel.topic(@topic, durable: true, persistent: true)
38
+ info "initialized with parameters:", {topic: @topic, period: @period, keys: @keys}
41
39
 
42
40
  rescue Bunny::TCPConnectionFailedForAllHosts => e
43
41
  error "ERROR: cannot connect to RabbitMQ hosts (#{e.inspect})"
@@ -51,7 +49,7 @@ module PushyDaemon
51
49
  random_key = @keys.sample || "random"
52
50
  channel_shout [:ping, random_key, random_string], {}
53
51
  end
54
- sleep 1
52
+ sleep @period
55
53
  end
56
54
  rescue AMQ::Protocol::EmptyResponseError => e
57
55
  raise PushyDaemon::ShouterResponseError, "#{e.class} (#{e.inspect})"
@@ -88,7 +86,6 @@ module PushyDaemon
88
86
  app_id: Conf.name,
89
87
  content_type: "application/json",
90
88
  )
91
-
92
89
  end
93
90
 
94
91
  end
data/pushyd.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  Gem::Specification.new do |spec|
3
3
  # Project version
4
- spec.version = "0.2.4"
4
+ spec.version = "0.3.0"
5
5
 
6
6
  # Project description
7
7
  spec.name = "pushyd"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pushyd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruno MEDICI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-06 00:00:00.000000000 Z
11
+ date: 2016-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -183,7 +183,6 @@ files:
183
183
  - lib/pushyd/constants.rb
184
184
  - lib/pushyd/daemon.rb
185
185
  - lib/pushyd/endpoint.rb
186
- - lib/pushyd/proxy.orig.rb
187
186
  - lib/pushyd/proxy.rb
188
187
  - lib/pushyd/pushy_logger.rb
189
188
  - lib/pushyd/shouter.rb
@@ -1,198 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'terminal-table'
3
- require 'hashie'
4
- require 'securerandom'
5
-
6
- # Log output
7
- def header rule, sign, topic, route
8
- puts
9
- puts SEPARATOR
10
- puts sprintf "%s | %-20s %1s %-10s | %s",
11
- DateTime.now.iso8601, rule, sign, topic, route
12
- puts SEPARATOR
13
- end
14
-
15
-
16
- def extract ctype, payload, fields = []
17
- # Force encoding (pftop...)
18
- utf8payload = payload.force_encoding('UTF-8')
19
-
20
- # Parse payload if content-type provided
21
- case ctype
22
- when "application/json"
23
- # if fields = rule[:payload_extract]
24
- # data = payload_extract(payload, fields)
25
- # data_source = "extract #{fields.inspect} #{data.keys.count}k"
26
- return JSON.parse utf8payload
27
-
28
- when "text/plain"
29
- return utf8payload.to_s
30
-
31
- else
32
- return utf8payload
33
-
34
- end
35
-
36
- # Handle body parse errors
37
- rescue Encoding::UndefinedConversionError => e
38
- puts "\t JSON PARSE ERROR: #{e.inspect}"
39
- return {}
40
-
41
- end
42
-
43
-
44
- # def payload_extract payload, fields = []
45
- # new_payload = payload.force_encoding('UTF-8')
46
- # parsed = JSON.parse new_payload
47
-
48
- # rescue Encoding::UndefinedConversionError => e
49
- # puts "\t JSON PARSE ERROR: #{e.inspect}"
50
- # return {}
51
-
52
- # else
53
- # return parsed
54
- # end
55
-
56
-
57
-
58
- # def handle_message rule_name, rule, delivery_info, metadata, payload
59
- # # Prepare data
60
- # msg_topic = delivery_info.exchange
61
- # msg_rkey = delivery_info.routing_key.force_encoding('UTF-8')
62
- # msg_headers = metadata.headers || {}
63
-
64
- # # Extract fields
65
- # data = extract metadata.content_type, payload, rule
66
-
67
- # # Announce match
68
- # header rule_name, "<", msg_topic, msg_rkey
69
-
70
- # # Build notification payload
71
- # body = {
72
- # # received: msg_topic,
73
- # exchange: msg_topic,
74
- # route: msg_rkey,
75
- # #headers: msg_headers,
76
- # sent_at: msg_headers['sent_at'],
77
- # sent_by: msg_headers['sent_by'],
78
- # data: data,
79
- # }
80
- # pretty_body = JSON.pretty_generate(body)
81
-
82
- # # Dump body data
83
- # puts "RULE: #{rule.inspect}"
84
- # puts "APP-ID: #{metadata.app_id}"
85
- # puts "CONTENT-TYPE: #{metadata.content_type}"
86
- # puts pretty_body
87
-
88
- # # Propagate data if needed
89
- # propagate rule[:relay], pretty_body
90
- # end
91
-
92
- def topic channel, name
93
- @topics ||= {}
94
- @topics[name] ||= channel.topic(name, durable: true, persistent: true)
95
- end
96
-
97
- def shout exchange, keys, body = {}
98
- # Add timestamp
99
- headers = {
100
- sent_at: DateTime.now.iso8601,
101
- sent_by: PROXY_IDENT
102
- }
103
- exchange_name = exchange.name
104
-
105
- # Prepare key and data
106
- routing_key = keys.unshift(exchange_name).join('.')
107
- # payload = data
108
-
109
- # Announce shout
110
- header "SHOUT", ">", exchange_name, routing_key
111
- puts JSON.pretty_generate(body) unless body.empty?
112
-
113
- # Publish
114
- exchange.publish(body.to_json,
115
- routing_key: routing_key,
116
- headers: headers,
117
- app_id: "contributor",
118
- content_type: "application/json",
119
- )
120
-
121
- end
122
-
123
-
124
- # Init ASCII table
125
- config_table = Terminal::Table.new
126
- config_table.title = "Message propagation rules"
127
- config_table.headings = ["queue binding", "topic", "route", "relay", "title"]
128
- config_table.align_column(5, :right)
129
-
130
-
131
- # Bind every topic
132
- config[:rules].each do |rule_name, rule|
133
- # Extract information
134
- catch_subscribe = rule[:subscribe] || true
135
- catch_topic = rule[:topic].to_s
136
- catch_routes = rule[:routes].to_s.split(' ')
137
-
138
- if catch_topic.empty? || catch_routes.empty?
139
- abort "rule [#{rule_name}] is invalid: missing topic / routes"
140
- end
141
-
142
- # Build / attach to queue
143
- rule_queue_name = "#{PROXY_IDENT}-#{QUEUE_HOST}-#{rule_name}"
144
-
145
- begin
146
- # Bind to this topic if not already done
147
- listen_exchange = topic(channel, catch_topic)
148
-
149
- # Pour this into a queue
150
- queue = channel.queue(rule_queue_name, auto_delete: false, durable: true)
151
-
152
- # Bind to these events on each route
153
- catch_routes.each do |route|
154
- # Bind with this routing key
155
- queue.bind listen_exchange, routing_key: route
156
- puts "BIND \t[#{rule_queue_name}] to [#{catch_topic}] / [#{route}] (subscribe: #{catch_subscribe})"
157
-
158
- # Add row to table
159
- config_table.add_row [rule_queue_name, catch_topic, route, rule[:relay].to_s, rule[:title].to_s ]
160
- end
161
-
162
- end
163
-
164
-
165
- # Subscribe
166
-
167
- queue.subscribe(block: false, manual_ack: SUB_USE_ACK, message_max: SUB_MSG_MAX) do |delivery_info, metadata, payload|
168
-
169
- # Handle the message
170
- handle_message rule_name, rule, delivery_info, metadata, payload
171
-
172
- # Ack the msg
173
- # puts "> #{delivery_info.delivery_tag}: nack"
174
- # channel.nack(delivery_info.delivery_tag)
175
-
176
- # if !SUB_USE_ACK
177
- # puts "> #{delivery_info.delivery_tag}: no ack"
178
- # elsif (100*rand) <= ACK_PERCENT
179
- # channel.ack(delivery_info.delivery_tag)
180
- # puts "> #{delivery_info.delivery_tag}: ACKED"
181
- # else
182
- # channel.nack(delivery_info.delivery_tag)
183
- # puts "> #{delivery_info.delivery_tag}: NOT_ACKED"
184
- # end
185
-
186
- end
187
-
188
- # End of loop
189
- end
190
-
191
-
192
- # Display config and susbcribe to queue
193
- puts config_table
194
-
195
-
196
-
197
- puts
198
- puts "ENDED"