eventhub-processor 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3946c885db8e62f874a349182784ac523c5ba60c
4
- data.tar.gz: 790e91c5b5a5c0565c6f43d2150695e670398153
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YjAxYjAwMjEyMzZiODlhNTIzNjI2MTQ5OWI2ZDNkYzJlM2I4MTE4MQ==
5
+ data.tar.gz: !binary |-
6
+ M2Q2NjM4YTg2YTBmMWViMzcyYTU0ODQ3NDAzZjgyYzhlNjlkYjQwYQ==
5
7
  SHA512:
6
- metadata.gz: 958a3ee62b3770e268976256c1f570e7aa2d98d2ff5699d3afc5aabca9d53715eef48fdb4ce2c8b6e0e72bd441366f26294eae08ba6ad5df6e042928a3c97611
7
- data.tar.gz: 9978887939029c93a158ab009e4dc105fd98f3dbc2ea7ccbec0ee576a23409c7c51900322ba4c5fc10b71dc4b1ee0d3656ccc7f7cc393fadda8cb60a2fb2b601
8
+ metadata.gz: !binary |-
9
+ ZGNlNGQ1MzE4NTRiYmFkMDE0MjY0ZTFlNjZiMGZlNGQzZjYxZTNkMWFhYzJl
10
+ MzUyNGVlYTkzNDYyYzc4YTE3YmQ2N2NmM2M0NjdjYjVhNGE3MmEwZTI2M2Ux
11
+ NDVmOWNiOGM2OGExYjQwN2U0NWIyZGMwYmYwZjE5ZmQ4MzQ0NjI=
12
+ data.tar.gz: !binary |-
13
+ ZGExOGJlMTVkNDA4NzVlOWRlNjRjMDVmMmUzY2M0MDcwYTNlMjRjNDBiMDFk
14
+ ZDg4OGY0NmE0YWU4OTllMjllYWQ4YjNkN2ZiMmJjNTYyNjAwZTgwMjM3NGEw
15
+ OWY4ZTBiMmYzYjFlMzQ0MzMyMWZiZTFkYWU2NmM2NzE2M2RhYjI=
@@ -1,27 +1,30 @@
1
- require 'amqp'
2
- require 'rest-client'
3
- require 'json'
4
- require 'singleton'
5
- require 'uuidtools'
6
- require 'base64'
7
- require 'socket'
8
-
9
- require_relative 'eventhub/version'
10
- require_relative 'eventhub/constant'
11
- require_relative 'eventhub/helper'
12
- require_relative 'eventhub/multi_logger'
13
-
14
- require_relative 'eventhub/configuration'
15
- require_relative 'eventhub/hash_extensions'
16
- require_relative 'eventhub/processor'
17
- require_relative 'eventhub/message'
18
-
19
- module EventHub
20
- def self.logger
21
- unless @logger
22
- a = Logger.new(STDOUT)
23
- @logger = MultiLogger.new(a)
24
- end
25
- @logger
26
- end
1
+ require 'amqp'
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'singleton'
5
+ require 'uuidtools'
6
+ require 'base64'
7
+ require 'socket'
8
+ require 'ostruct'
9
+ require 'optparse'
10
+
11
+ require_relative 'eventhub/argument_parser'
12
+ require_relative 'eventhub/version'
13
+ require_relative 'eventhub/constant'
14
+ require_relative 'eventhub/helper'
15
+ require_relative 'eventhub/multi_logger'
16
+
17
+ require_relative 'eventhub/configuration'
18
+ require_relative 'eventhub/hash_extensions'
19
+ require_relative 'eventhub/processor'
20
+ require_relative 'eventhub/message'
21
+
22
+ module EventHub
23
+ def self.logger
24
+ unless @logger
25
+ @logger = MultiLogger.new
26
+ @logger.add_device(Logger.new(STDOUT))
27
+ end
28
+ @logger
29
+ end
27
30
  end
@@ -0,0 +1,33 @@
1
+ module EventHub
2
+
3
+ class ArgumentParser
4
+ def self.parse(args)
5
+ # The options specified on the command line will be collected in *options*.
6
+ # We set default values here.
7
+ options = OpenStruct.new
8
+ options.environment = 'development'
9
+ options.detached = false
10
+
11
+ opt_parser = OptionParser.new do |opts|
12
+ opts.banner = "Usage: #{args[0]}.rb [options]"
13
+
14
+ opts.on("-e", "--environment ENVIRONMENT","Environment the processor is running") do |environment|
15
+ options.environment = environment
16
+ end
17
+
18
+ opts.on("-d", "--detached", "Run processor detached as a daemon") do |v|
19
+ options.detached = v
20
+ end
21
+
22
+ opts.on_tail("-h", "--help", "Show this message") do
23
+ puts opts
24
+ exit
25
+ end
26
+ end
27
+
28
+ opt_parser.parse!(args)
29
+ options
30
+ end
31
+ end
32
+
33
+ end
@@ -1,27 +1,27 @@
1
- module EventHub
2
-
3
- class Configuration
4
- include Singleton
5
- include Helper
6
-
7
- attr_accessor :data, :folder, :environment
8
-
9
- def initialize
10
- @data = nil
11
- @folder = Dir.pwd
12
- @environment = 'development'
13
- end
14
-
15
- def load_file(input, env='development')
16
- tmp = JSON.parse( IO.read(input))
17
- @data = tmp[env]
18
- @environment = env
19
- true
20
- rescue => e
21
- EventHub.logger.info("Unexpected exception while loading configuration [#{input}]: #{format_string(e.message)}")
22
- false
23
- end
24
-
25
- end
26
-
1
+ module EventHub
2
+
3
+ class Configuration
4
+ include Singleton
5
+ include Helper
6
+
7
+ attr_accessor :data, :folder, :environment
8
+
9
+ def initialize
10
+ @data = nil
11
+ @folder = Dir.pwd
12
+ @environment = 'development'
13
+ end
14
+
15
+ def load_file(input, env = 'development')
16
+ tmp = JSON.parse( IO.read(input))
17
+ @data = tmp[env]
18
+ @environment = env
19
+ true
20
+ rescue => e
21
+ EventHub.logger.info("Unexpected exception while loading configuration [#{input}]: #{format_string(e.message)}")
22
+ false
23
+ end
24
+
25
+ end
26
+
27
27
  end
@@ -1,55 +1,55 @@
1
- module EventHub
2
-
3
- module Helper
4
-
5
- # converts a class like EventHub::PlateStore::MyClassName to an array ['event_hub','plate_store','my_class_name']
6
- def class_to_array(class_name)
7
- class_name.to_s.split("::").map{ |m| m.gsub(/[A-Z]/) { |c| "_#{c}"}.gsub(/^_/,"").downcase }
8
- end
9
-
10
- # replaces CR, LF, CRLF with ";" and cut's string to requied length by adding "..." if string would be longer
11
- def format_string(message,max_characters=80)
12
- max_characters = 5 if max_characters < 5
13
- m = message.gsub(/\r\n|\n|\r/m,";")
14
- return (m[0..max_characters-4] + "...") if m.size > max_characters
15
- return m
16
- end
17
-
18
- def get_host
19
- Socket.gethostname
20
- end
21
-
22
- def get_ip_adresses
23
- list = Socket.ip_address_list.map { |i| i.ip_address unless i.ipv4_loopback? || i.ipv6_loopback? }.compact
24
- return list.size == 0 ? ["no ip address found (loopback excluded)"] : list
25
- end
26
-
27
- def now_stamp(now=nil)
28
- now ||= Time.now
29
- now.utc.strftime("%Y-%m-%dT%H:%M:%S.#{now.usec}Z")
30
- end
31
-
32
- def duration(difference)
33
- rest, secs = difference.divmod( 60 ) # self is the time difference t2 - t1
34
- rest, mins = rest.divmod( 60 )
35
- days, hours = rest.divmod( 24 )
36
- secs = secs.truncate
37
- milliseconds = ((difference - difference.truncate)*1000).round
38
-
39
- result = []
40
- result << "#{days} days" if days > 1
41
- result << "#{days} day" if days == 1
42
- result << "#{hours} hours" if hours > 1
43
- result << "#{hours} hour" if hours == 1
44
- result << "#{mins} minutes" if mins > 1
45
- result << "#{mins} minute" if mins == 1
46
- result << "#{secs} seconds" if secs > 1
47
- result << "#{secs} second" if secs == 1
48
- result << "#{milliseconds} milliseconds" if milliseconds > 1
49
- result << "#{milliseconds} millisecond" if milliseconds == 1
50
- return result.join(' ')
51
- end
52
-
53
- end
54
-
1
+ module EventHub
2
+
3
+ module Helper
4
+
5
+ # converts a class like EventHub::PlateStore::MyClassName to an array ['event_hub','plate_store','my_class_name']
6
+ def class_to_array(class_name)
7
+ class_name.to_s.split("::").map{ |m| m.gsub(/[A-Z]/) { |c| "_#{c}"}.gsub(/^_/,"").downcase }
8
+ end
9
+
10
+ # replaces CR, LF, CRLF with ";" and cut's string to requied length by adding "..." if string would be longer
11
+ def format_string(message,max_characters=80)
12
+ max_characters = 5 if max_characters < 5
13
+ m = message.gsub(/\r\n|\n|\r/m,";")
14
+ return (m[0..max_characters-4] + "...") if m.size > max_characters
15
+ return m
16
+ end
17
+
18
+ def get_host
19
+ Socket.gethostname
20
+ end
21
+
22
+ def get_ip_adresses
23
+ list = Socket.ip_address_list.map { |i| i.ip_address unless i.ipv4_loopback? || i.ipv6_loopback? }.compact
24
+ return list.size == 0 ? ["no ip address found (loopback excluded)"] : list
25
+ end
26
+
27
+ def now_stamp(now=nil)
28
+ now ||= Time.now
29
+ now.utc.strftime("%Y-%m-%dT%H:%M:%S.#{now.usec}Z")
30
+ end
31
+
32
+ def duration(difference)
33
+ rest, secs = difference.divmod( 60 ) # self is the time difference t2 - t1
34
+ rest, mins = rest.divmod( 60 )
35
+ days, hours = rest.divmod( 24 )
36
+ secs = secs.truncate
37
+ milliseconds = ((difference - difference.truncate)*1000).round
38
+
39
+ result = []
40
+ result << "#{days} days" if days > 1
41
+ result << "#{days} day" if days == 1
42
+ result << "#{hours} hours" if hours > 1
43
+ result << "#{hours} hour" if hours == 1
44
+ result << "#{mins} minutes" if mins > 1
45
+ result << "#{mins} minute" if mins == 1
46
+ result << "#{secs} seconds" if secs > 1
47
+ result << "#{secs} second" if secs == 1
48
+ result << "#{milliseconds} milliseconds" if milliseconds > 1
49
+ result << "#{milliseconds} millisecond" if milliseconds == 1
50
+ return result.join(' ')
51
+ end
52
+
53
+ end
54
+
55
55
  end
@@ -1,117 +1,128 @@
1
- module EventHub
2
-
3
- class Message
4
- include Helper
5
-
6
- VERSION = '1.0.0'
7
-
8
- # Headers that are required (value can be nil) in order to pass valid?
9
- REQUIRED_HEADERS = [
10
- 'message_id',
11
- 'version',
12
- 'created_at',
13
- 'origin.module_id',
14
- 'origin.type',
15
- 'origin.site_id',
16
- 'process.name',
17
- 'process.step_position',
18
- 'process.execution_id',
19
- 'status.retried_count',
20
- 'status.code',
21
- 'status.message'
22
- ]
23
-
24
- attr_accessor :header, :body, :raw, :vhost, :routing_key
25
-
26
- # Build accessors for all required headers
27
- REQUIRED_HEADERS.each do |header|
28
- name = header.gsub(/\./,"_")
29
-
30
- define_method(name) do
31
- self.header.get(header)
32
- end
33
-
34
- define_method("#{name}=") do |value|
35
- self.header.set(header,value)
36
- end
37
- end
38
-
39
- def self.from_json(raw)
40
- data = JSON.parse(raw)
41
- Message.new(data.get('header'), data.get('body'),raw)
42
- rescue => e
43
- Message.new({ "status" => { "code" => STATUS_INVALID, "message" => "JSON parse error: #{e}" }} ,{ "original_message_base64_encoded" => Base64.encode64(raw)},raw)
44
- end
45
-
46
- # process_step_position should be
47
- def initialize(header=nil, body=nil,raw=nil)
48
-
49
- @header = header || {}
50
- @body = body || {}
51
- @raw = raw
52
-
53
- # set message defaults, that we have required headers
54
- @header.set('message_id',UUIDTools::UUID.timestamp_create.to_s,false)
55
- @header.set('version',VERSION,false)
56
- @header.set('created_at',now_stamp,false)
57
-
58
- @header.set('origin.module_id','undefined',false)
59
- @header.set('origin.type','undefined',false)
60
- @header.set('origin.site_id','undefined',false)
61
-
62
- @header.set('process.name','undefined',false)
63
- @header.set('process.execution_id',UUIDTools::UUID.timestamp_create.to_s,false)
64
- @header.set('process.step_position',0,false)
65
-
66
- @header.set('status.retried_count',0,false)
67
- @header.set('status.code',STATUS_INITIAL,false)
68
- @header.set('status.message','',false)
69
-
70
- end
71
-
72
- def valid?
73
- # check for existence and defined value
74
- REQUIRED_HEADERS.all? { |key| @header.all_keys_with_path.include?(key) && !!self.send(key.gsub(/\./,"_").to_sym)}
75
- end
76
-
77
- def success?
78
- self.status_code == STATUS_SUCCESS
79
- end
80
-
81
- def retry?
82
- !success?
83
- end
84
-
85
- def initial?
86
- self.status_code == STATUS_INITIAL
87
- end
88
-
89
- def retry_pending?
90
- self.status_code == STATUS_RETRY_PENDING
91
- end
92
-
93
- def to_json
94
- {'header' => self.header, 'body' => self.body}.to_json
95
- end
96
-
97
- def to_s
98
- "Msg: process [#{self.process_name},#{self.process_step_position},#{self.process_execution_id}], status [#{self.status_code},#{self.status_message},#{self.status_retried_count}]"
99
- end
100
-
101
- # copies the message and set's provided status code (default: success), actual stamp, and a new message id
102
- def copy(status_code=STATUS_SUCCESS)
103
-
104
- # use Marshal dump and load to make a deep object copy
105
- copied_header = Marshal.load( Marshal.dump(header))
106
- copied_body = Marshal.load( Marshal.dump(body))
107
-
108
- copied_header.set("message_id",UUIDTools::UUID.timestamp_create.to_s)
109
- copied_header.set("created_at",now_stamp)
110
- copied_header.set("status.code",status_code)
111
-
112
- Message.new(copied_header, copied_body)
113
- end
114
-
115
- end
116
-
117
- end
1
+ module EventHub
2
+
3
+ class Message
4
+ include Helper
5
+
6
+ VERSION = '1.0.0'
7
+
8
+ # Headers that are required (value can be nil) in order to pass valid?
9
+ REQUIRED_HEADERS = [
10
+ 'message_id',
11
+ 'version',
12
+ 'created_at',
13
+ 'origin.module_id',
14
+ 'origin.type',
15
+ 'origin.site_id',
16
+ 'process.name',
17
+ 'process.step_position',
18
+ 'process.execution_id',
19
+ 'status.retried_count',
20
+ 'status.code',
21
+ 'status.message'
22
+ ]
23
+
24
+ attr_accessor :header, :body, :raw, :vhost, :routing_key
25
+
26
+ # Build accessors for all required headers
27
+ REQUIRED_HEADERS.each do |header|
28
+ name = header.gsub(/\./,"_")
29
+
30
+ define_method(name) do
31
+ self.header.get(header)
32
+ end
33
+
34
+ define_method("#{name}=") do |value|
35
+ self.header.set(header,value)
36
+ end
37
+ end
38
+
39
+ def self.from_json(raw)
40
+ data = JSON.parse(raw)
41
+ Message.new(data.get('header'), data.get('body'),raw)
42
+ rescue => e
43
+ Message.new({ "status" => { "code" => STATUS_INVALID, "message" => "JSON parse error: #{e}" }} ,{ "original_message_base64_encoded" => Base64.encode64(raw)},raw)
44
+ end
45
+
46
+ # process_step_position should be
47
+ def initialize(header=nil, body=nil,raw=nil)
48
+
49
+ @header = header || {}
50
+ @body = body || {}
51
+ @raw = raw
52
+
53
+ # set message defaults, that we have required headers
54
+ @header.set('message_id',UUIDTools::UUID.timestamp_create.to_s,false)
55
+ @header.set('version',VERSION,false)
56
+ @header.set('created_at',now_stamp,false)
57
+
58
+ @header.set('origin.module_id','undefined',false)
59
+ @header.set('origin.type','undefined',false)
60
+ @header.set('origin.site_id','undefined',false)
61
+
62
+ @header.set('process.name','undefined',false)
63
+ @header.set('process.execution_id',UUIDTools::UUID.timestamp_create.to_s,false)
64
+ @header.set('process.step_position',0,false)
65
+
66
+ @header.set('status.retried_count',0,false)
67
+ @header.set('status.code',STATUS_INITIAL,false)
68
+ @header.set('status.message','',false)
69
+
70
+ end
71
+
72
+ def valid?
73
+ # check for existence and defined value
74
+ REQUIRED_HEADERS.all? { |key| @header.all_keys_with_path.include?(key) && !!self.send(key.gsub(/\./,"_").to_sym)}
75
+ end
76
+
77
+ def success?
78
+ self.status_code == STATUS_SUCCESS
79
+ end
80
+
81
+ def retry?
82
+ !success?
83
+ end
84
+
85
+ def initial?
86
+ self.status_code == STATUS_INITIAL
87
+ end
88
+
89
+ def retry_pending?
90
+ self.status_code == STATUS_RETRY_PENDING
91
+ end
92
+
93
+ def to_json
94
+ {'header' => self.header, 'body' => self.body}.to_json
95
+ end
96
+
97
+ def to_s
98
+ "Msg: process [#{self.process_name},#{self.process_step_position},#{self.process_execution_id}], status [#{self.status_code},#{self.status_message},#{self.status_retried_count}]"
99
+ end
100
+
101
+ # copies the message and set's provided status code (default: success), actual stamp, and a new message id
102
+ def copy(status_code=STATUS_SUCCESS)
103
+
104
+ # use Marshal dump and load to make a deep object copy
105
+ copied_header = Marshal.load( Marshal.dump(header))
106
+ copied_body = Marshal.load( Marshal.dump(body))
107
+
108
+ copied_header.set("message_id",UUIDTools::UUID.timestamp_create.to_s)
109
+ copied_header.set("created_at",now_stamp)
110
+ copied_header.set("status.code",status_code)
111
+
112
+ Message.new(copied_header, copied_body)
113
+ end
114
+
115
+ def self.translate_status_code(code)
116
+ case code
117
+ when EventHub::STATUS_INITIAL then return 'STATUS_INITIAL'
118
+ when EventHub::STATUS_SUCCESS then return 'STATUS_SUCCESS'
119
+ when EventHub::STATUS_RETRY then return 'STATUS_RETRY'
120
+ when EventHub::STATUS_RETRY_PENDING then return 'STATUS_RETRY_PENDING'
121
+ when EventHub::STATUS_INVALID then return 'STATUS_INVALID'
122
+ when EventHub::STATUS_DEADLETTER then return 'STATUS_DEADLETTER'
123
+ end
124
+ end
125
+
126
+ end
127
+
128
+ end