eventhub-processor2 1.0.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 +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/.travis.yml +36 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +22 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker/Dockerfile +6 -0
- data/docker/README.md +14 -0
- data/docker/definitions.json +87 -0
- data/docker/rabbitmq.config +16 -0
- data/eventhub-processor2.gemspec +34 -0
- data/example/README.md +19 -0
- data/example/config/example.json +19 -0
- data/example/crasher.rb +57 -0
- data/example/example.rb +25 -0
- data/example/publisher.rb +95 -0
- data/lib/eventhub/actor_heartbeat.rb +121 -0
- data/lib/eventhub/actor_listener.rb +161 -0
- data/lib/eventhub/actor_watchdog.rb +41 -0
- data/lib/eventhub/configuration.rb +114 -0
- data/lib/eventhub/constant.rb +35 -0
- data/lib/eventhub/consumer.rb +9 -0
- data/lib/eventhub/hash_extensions.rb +49 -0
- data/lib/eventhub/helper.rb +55 -0
- data/lib/eventhub/logger.rb +14 -0
- data/lib/eventhub/message.rb +158 -0
- data/lib/eventhub/processor2.rb +121 -0
- data/lib/eventhub/statistics.rb +53 -0
- data/lib/eventhub/version.rb +3 -0
- data/lib/eventhub.rb +25 -0
- metadata +190 -0
@@ -0,0 +1,158 @@
|
|
1
|
+
# EventHub module
|
2
|
+
module EventHub
|
3
|
+
# Message class
|
4
|
+
class Message
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
VERSION = '1.0.0'.freeze
|
8
|
+
|
9
|
+
# Headers that are required (value can be nil) in order to pass valid?
|
10
|
+
REQUIRED_HEADERS = [
|
11
|
+
'message_id',
|
12
|
+
'version',
|
13
|
+
'created_at',
|
14
|
+
'origin.module_id',
|
15
|
+
'origin.type',
|
16
|
+
'origin.site_id',
|
17
|
+
'process.name',
|
18
|
+
'process.step_position',
|
19
|
+
'process.execution_id',
|
20
|
+
'status.retried_count',
|
21
|
+
'status.code',
|
22
|
+
'status.message'
|
23
|
+
].freeze
|
24
|
+
|
25
|
+
attr_accessor :header, :body, :raw, :vhost, :routing_key
|
26
|
+
|
27
|
+
# Build accessors for all required headers
|
28
|
+
REQUIRED_HEADERS.each do |header|
|
29
|
+
name = header.tr('.', '_')
|
30
|
+
|
31
|
+
define_method(name) do
|
32
|
+
self.header.get(header)
|
33
|
+
end
|
34
|
+
|
35
|
+
define_method("#{name}=") do |value|
|
36
|
+
self.header.set(header, value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.from_json(raw)
|
41
|
+
data = JSON.parse(raw)
|
42
|
+
Message.new(data.get('header'), data.get('body'), raw)
|
43
|
+
rescue => e
|
44
|
+
Message.new(
|
45
|
+
{
|
46
|
+
'status' =>
|
47
|
+
{
|
48
|
+
'code' => STATUS_INVALID,
|
49
|
+
'message' => "JSON parse error: #{e}"
|
50
|
+
}
|
51
|
+
},
|
52
|
+
{
|
53
|
+
'original_message_base64_encoded' => Base64.encode64(raw)
|
54
|
+
},
|
55
|
+
raw
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(header = nil, body = nil, raw = nil)
|
60
|
+
@header = header || {}
|
61
|
+
@body = body || {}
|
62
|
+
@raw = raw
|
63
|
+
|
64
|
+
# set message defaults, that we have required headers
|
65
|
+
@header.set('message_id', UUIDTools::UUID.timestamp_create.to_s, false)
|
66
|
+
@header.set('version', VERSION, false)
|
67
|
+
@header.set('created_at', now_stamp, false)
|
68
|
+
|
69
|
+
@header.set('origin.module_id', 'undefined', false)
|
70
|
+
@header.set('origin.type', 'undefined', false)
|
71
|
+
@header.set('origin.site_id', 'undefined', false)
|
72
|
+
|
73
|
+
@header.set('process.name', 'undefined', false)
|
74
|
+
@header.set('process.execution_id',
|
75
|
+
UUIDTools::UUID.timestamp_create.to_s, false)
|
76
|
+
@header.set('process.step_position', 0, false)
|
77
|
+
|
78
|
+
@header.set('status.retried_count', 0, false)
|
79
|
+
@header.set('status.code', STATUS_INITIAL, false)
|
80
|
+
@header.set('status.message', '', false)
|
81
|
+
end
|
82
|
+
|
83
|
+
def valid?
|
84
|
+
# check for existence and defined value
|
85
|
+
REQUIRED_HEADERS.all? do |key|
|
86
|
+
@header.all_keys_with_path.include?(key) &&
|
87
|
+
!send(key.tr('.', '_').to_sym).nil?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def success?
|
92
|
+
status_code == STATUS_SUCCESS
|
93
|
+
end
|
94
|
+
|
95
|
+
def retry?
|
96
|
+
status_code == STATUS_RETRY
|
97
|
+
end
|
98
|
+
|
99
|
+
def initial?
|
100
|
+
status_code == STATUS_INITIAL
|
101
|
+
end
|
102
|
+
|
103
|
+
def retry_pending?
|
104
|
+
status_code == STATUS_RETRY_PENDING
|
105
|
+
end
|
106
|
+
|
107
|
+
def invalid?
|
108
|
+
status_code == STATUS_INVALID
|
109
|
+
end
|
110
|
+
|
111
|
+
def schedule?
|
112
|
+
status_code == STATUS_SCHEDULE
|
113
|
+
end
|
114
|
+
|
115
|
+
def schedule_retry?
|
116
|
+
status_code == STATUS_SCHEDULE_RETRY
|
117
|
+
end
|
118
|
+
|
119
|
+
def schedule_pending?
|
120
|
+
status_code == STATUS_SCHEDULE_PENDING
|
121
|
+
end
|
122
|
+
|
123
|
+
def to_json
|
124
|
+
{ 'header' => header, 'body' => body }.to_json
|
125
|
+
end
|
126
|
+
|
127
|
+
def to_s
|
128
|
+
'Msg: process '\
|
129
|
+
"[#{process_name}, #{process_step_position}, #{process_execution_id}]"\
|
130
|
+
", status [#{status_code},#{status_message},#{status_retried_count}]"
|
131
|
+
end
|
132
|
+
|
133
|
+
# copies the message and set's provided status code (default: success),
|
134
|
+
# actual stamp, and a new message id
|
135
|
+
def copy(status_code = STATUS_SUCCESS)
|
136
|
+
# use Marshal dump and load to make a deep object copy
|
137
|
+
copied_header = Marshal.load(Marshal.dump(header))
|
138
|
+
copied_body = Marshal.load(Marshal.dump(body))
|
139
|
+
|
140
|
+
copied_header.set('message_id', UUIDTools::UUID.timestamp_create.to_s)
|
141
|
+
copied_header.set('created_at', now_stamp)
|
142
|
+
copied_header.set('status.code', status_code)
|
143
|
+
|
144
|
+
Message.new(copied_header, copied_body)
|
145
|
+
end
|
146
|
+
|
147
|
+
def append_to_execution_history(processor_name)
|
148
|
+
header.set('execution_history', []) unless \
|
149
|
+
header.get('execution_history')
|
150
|
+
header.get('execution_history') << \
|
151
|
+
{ 'processor' => processor_name, 'timestamp' => now_stamp }
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.translate_status_code(code)
|
155
|
+
STATUS_CODE_TRANSLATION[code]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# EventHub module
|
2
|
+
module EventHub
|
3
|
+
# Processor2 class
|
4
|
+
class Processor2
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
SIGNALS_FOR_TERMINATION = [:INT, :TERM, :QUIT]
|
8
|
+
SIGNALS_FOR_RELOAD_CONFIG = [:HUP]
|
9
|
+
ALL_SIGNALS = SIGNALS_FOR_TERMINATION + SIGNALS_FOR_RELOAD_CONFIG
|
10
|
+
|
11
|
+
attr_reader :started_at, :statistics
|
12
|
+
|
13
|
+
def initialize(args = {})
|
14
|
+
# Set processor name
|
15
|
+
EventHub::Configuration.name = args[:name] ||
|
16
|
+
get_name_from_class(self)
|
17
|
+
|
18
|
+
# Parse comand line options
|
19
|
+
EventHub::Configuration.parse_options
|
20
|
+
|
21
|
+
# Load configuration file
|
22
|
+
EventHub::Configuration.load!(args)
|
23
|
+
|
24
|
+
@command_queue = []
|
25
|
+
|
26
|
+
@started_at = Time.now
|
27
|
+
@statistics = EventHub::Statistics.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def start
|
31
|
+
EventHub.logger.info("#{Configuration.name} (#{version}): has been started")
|
32
|
+
|
33
|
+
before_start
|
34
|
+
main_event_loop
|
35
|
+
after_stop
|
36
|
+
|
37
|
+
EventHub.logger.info("#{Configuration.name} (#{version}): has been stopped")
|
38
|
+
rescue => ex
|
39
|
+
EventHub.logger.error("Unexpected error in Processor2.start: #{ex}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def stop
|
43
|
+
# used by rspec
|
44
|
+
@command_queue << :TERM
|
45
|
+
end
|
46
|
+
|
47
|
+
def version
|
48
|
+
EventHub::VERSION
|
49
|
+
end
|
50
|
+
|
51
|
+
# get message as EventHub::Message class instance
|
52
|
+
# args contain :queue_name, :content_type, :priority, :delivery_tag
|
53
|
+
def handle_message(_message, _args = {})
|
54
|
+
raise 'need to be implemented in derived class'
|
55
|
+
end
|
56
|
+
|
57
|
+
# pass message: '{ "header": ... , "body": { .. }}'
|
58
|
+
# and optionally exchange_name: 'your exchange name'
|
59
|
+
def publish(args = {})
|
60
|
+
Celluloid::Actor[:actor_listener].publish(args)
|
61
|
+
end
|
62
|
+
|
63
|
+
def before_start
|
64
|
+
# can be implemented in derived class
|
65
|
+
end
|
66
|
+
|
67
|
+
def after_stop
|
68
|
+
# can be implemented in derived class
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def setup_signal_handler
|
74
|
+
# have a re-entrant signal handler by just using a simple array
|
75
|
+
# https://www.sitepoint.com/the-self-pipe-trick-explained/
|
76
|
+
ALL_SIGNALS.each do |signal|
|
77
|
+
Signal.trap(signal) { @command_queue << signal }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def start_supervisor
|
82
|
+
@config = Celluloid::Supervision::Configuration.define([
|
83
|
+
{type: ActorHeartbeat, as: :actor_heartbeat, args: [ self ]},
|
84
|
+
{type: ActorListener, as: :actor_listener, args: [ self ]}
|
85
|
+
])
|
86
|
+
|
87
|
+
@config.injection!(:before_restart, proc do
|
88
|
+
EventHub.logger.info('Restarting in 10 seconds...')
|
89
|
+
sleep 10
|
90
|
+
end )
|
91
|
+
|
92
|
+
@config.deploy
|
93
|
+
end
|
94
|
+
|
95
|
+
def main_event_loop
|
96
|
+
setup_signal_handler
|
97
|
+
start_supervisor
|
98
|
+
|
99
|
+
loop do
|
100
|
+
command = @command_queue.pop
|
101
|
+
case
|
102
|
+
when SIGNALS_FOR_TERMINATION.include?(command)
|
103
|
+
EventHub.logger.info("Command [#{command}] received")
|
104
|
+
break
|
105
|
+
when SIGNALS_FOR_RELOAD_CONFIG.include?(command)
|
106
|
+
EventHub::Configuration.load!
|
107
|
+
EventHub.logger.info('Configuration file reloaded')
|
108
|
+
Celluloid::Actor[:actor_listener].async.restart
|
109
|
+
else
|
110
|
+
sleep 0.5
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
Celluloid.shutdown
|
115
|
+
# make sure all actors are gone
|
116
|
+
while Celluloid.running?
|
117
|
+
sleep 0.1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class EventHub::Statistics
|
2
|
+
attr_reader :messages_successful, :messages_unsuccessful, :messages_average_size, :messages_average_process_time
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@messages_successful = 0
|
6
|
+
@messages_unsuccessful = 0
|
7
|
+
@messages_average_size = 0
|
8
|
+
@messages_average_process_time = 0
|
9
|
+
@messages_total_process_time = 0
|
10
|
+
@mutex = Mutex.new
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def measure(size, &block)
|
15
|
+
begin
|
16
|
+
start = Time.now
|
17
|
+
yield
|
18
|
+
success(Time.now - start, size)
|
19
|
+
rescue
|
20
|
+
failure
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def success(process_time, size)
|
26
|
+
@mutex.lock
|
27
|
+
@messages_total_process_time += process_time
|
28
|
+
@messages_average_process_time = (messages_total_process_time + process_time) / (messages_successful + 1).to_f
|
29
|
+
@messages_average_size = (messages_total_size + size) / (messages_successful + 1).to_f
|
30
|
+
@messages_successful += 1
|
31
|
+
ensure
|
32
|
+
@mutex.unlock
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure
|
36
|
+
@mutex.lock
|
37
|
+
@messages_unsuccessful += 1
|
38
|
+
ensure
|
39
|
+
@mutex.unlock
|
40
|
+
end
|
41
|
+
|
42
|
+
def messages_total
|
43
|
+
messages_unsuccessful + messages_successful
|
44
|
+
end
|
45
|
+
|
46
|
+
def messages_total_process_time
|
47
|
+
messages_average_process_time * messages_successful
|
48
|
+
end
|
49
|
+
|
50
|
+
def messages_total_size
|
51
|
+
messages_average_size * messages_successful
|
52
|
+
end
|
53
|
+
end
|
data/lib/eventhub.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'uuidtools'
|
2
|
+
require 'json'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
require 'eventhub/components'
|
6
|
+
require 'logstash-logger'
|
7
|
+
require 'bunny'
|
8
|
+
require 'celluloid/current'
|
9
|
+
|
10
|
+
require_relative 'eventhub/version'
|
11
|
+
require_relative 'eventhub/constant'
|
12
|
+
require_relative 'eventhub/logger'
|
13
|
+
require_relative 'eventhub/helper'
|
14
|
+
require_relative 'eventhub/hash_extensions'
|
15
|
+
require_relative 'eventhub/configuration'
|
16
|
+
require_relative 'eventhub/message'
|
17
|
+
require_relative 'eventhub/statistics'
|
18
|
+
require_relative 'eventhub/consumer'
|
19
|
+
require_relative 'eventhub/actor_heartbeat'
|
20
|
+
require_relative 'eventhub/actor_watchdog'
|
21
|
+
require_relative 'eventhub/actor_listener'
|
22
|
+
require_relative 'eventhub/processor2'
|
23
|
+
|
24
|
+
Celluloid.logger = nil
|
25
|
+
Celluloid.exception_handler { |ex| EventHub.logger.info "Exception occured: #{ex}" }
|
metadata
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eventhub-processor2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Steiner, Thomas
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: celluloid
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.17'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bunny
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: eventhub-components
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: uuidtools
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.16'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.16'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '12.2'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '12.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.7'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.7'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.15'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.15'
|
125
|
+
description: Next generation gem to build ruby based eventhub processor
|
126
|
+
email:
|
127
|
+
- thomas.steiner@ikey.ch
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- Gemfile.lock
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- bin/console
|
141
|
+
- bin/setup
|
142
|
+
- docker/Dockerfile
|
143
|
+
- docker/README.md
|
144
|
+
- docker/definitions.json
|
145
|
+
- docker/rabbitmq.config
|
146
|
+
- eventhub-processor2.gemspec
|
147
|
+
- example/README.md
|
148
|
+
- example/config/example.json
|
149
|
+
- example/crasher.rb
|
150
|
+
- example/example.rb
|
151
|
+
- example/publisher.rb
|
152
|
+
- lib/eventhub.rb
|
153
|
+
- lib/eventhub/actor_heartbeat.rb
|
154
|
+
- lib/eventhub/actor_listener.rb
|
155
|
+
- lib/eventhub/actor_watchdog.rb
|
156
|
+
- lib/eventhub/configuration.rb
|
157
|
+
- lib/eventhub/constant.rb
|
158
|
+
- lib/eventhub/consumer.rb
|
159
|
+
- lib/eventhub/hash_extensions.rb
|
160
|
+
- lib/eventhub/helper.rb
|
161
|
+
- lib/eventhub/logger.rb
|
162
|
+
- lib/eventhub/message.rb
|
163
|
+
- lib/eventhub/processor2.rb
|
164
|
+
- lib/eventhub/statistics.rb
|
165
|
+
- lib/eventhub/version.rb
|
166
|
+
homepage: https://github.com/thomis/eventhub-processor2
|
167
|
+
licenses:
|
168
|
+
- MIT
|
169
|
+
metadata: {}
|
170
|
+
post_install_message:
|
171
|
+
rdoc_options: []
|
172
|
+
require_paths:
|
173
|
+
- lib
|
174
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
requirements: []
|
185
|
+
rubyforge_project:
|
186
|
+
rubygems_version: 2.6.12
|
187
|
+
signing_key:
|
188
|
+
specification_version: 4
|
189
|
+
summary: Next generation gem to build ruby based eventhub processor
|
190
|
+
test_files: []
|