hawkei 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.rubocop.yml +48 -0
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +12 -0
- data/LICENCE +21 -0
- data/Makefile +9 -0
- data/README.md +17 -0
- data/Rakefile +4 -0
- data/hawkei.gemspec +28 -0
- data/lib/hawkei/api_operation/delete.rb +38 -0
- data/lib/hawkei/api_operation/save.rb +57 -0
- data/lib/hawkei/api_resource.rb +130 -0
- data/lib/hawkei/batch.rb +18 -0
- data/lib/hawkei/config.rb +123 -0
- data/lib/hawkei/errors.rb +41 -0
- data/lib/hawkei/formated_logger.rb +45 -0
- data/lib/hawkei/hawkei_object.rb +179 -0
- data/lib/hawkei/library_name.rb +3 -0
- data/lib/hawkei/message.rb +79 -0
- data/lib/hawkei/plugins/rack/middleware.rb +139 -0
- data/lib/hawkei/plugins/rails/data.rb +19 -0
- data/lib/hawkei/plugins/rails/middleware_data.rb +28 -0
- data/lib/hawkei/plugins/rails/railtie.rb +23 -0
- data/lib/hawkei/plugins/sidekiq/client_middleware.rb +19 -0
- data/lib/hawkei/plugins/sidekiq/load.rb +14 -0
- data/lib/hawkei/plugins/sidekiq/server_middleware.rb +48 -0
- data/lib/hawkei/plugins.rb +17 -0
- data/lib/hawkei/processor/async.rb +50 -0
- data/lib/hawkei/processor/batch.rb +84 -0
- data/lib/hawkei/processor/worker.rb +113 -0
- data/lib/hawkei/request.rb +134 -0
- data/lib/hawkei/store.rb +49 -0
- data/lib/hawkei/util.rb +180 -0
- data/lib/hawkei/version.rb +3 -0
- data/lib/hawkei/watcher.rb +15 -0
- data/lib/hawkei.rb +170 -0
- data/spec/lib/hawkei/api_resource_spec.rb +109 -0
- data/spec/lib/hawkei/batch_spec.rb +14 -0
- data/spec/lib/hawkei/config_spec.rb +36 -0
- data/spec/lib/hawkei/formated_logger_spec.rb +99 -0
- data/spec/lib/hawkei/hawkei_object_spec.rb +123 -0
- data/spec/lib/hawkei/message_spec.rb +178 -0
- data/spec/lib/hawkei/plugins/rack/middleware_spec.rb +88 -0
- data/spec/lib/hawkei/plugins/rails/data_spec.rb +22 -0
- data/spec/lib/hawkei/plugins/rails/middleware_data_spec.rb +46 -0
- data/spec/lib/hawkei/plugins/sidekiq/client_middleware_spec.rb +15 -0
- data/spec/lib/hawkei/plugins/sidekiq/server_middleware_spec.rb +58 -0
- data/spec/lib/hawkei/processor/async_spec.rb +36 -0
- data/spec/lib/hawkei/processor/batch_spec.rb +51 -0
- data/spec/lib/hawkei/processor/worker_spec.rb +100 -0
- data/spec/lib/hawkei/store_spec.rb +82 -0
- data/spec/lib/hawkei/util_spec.rb +132 -0
- data/spec/lib/hawkei/watcher_spec.rb +25 -0
- data/spec/lib/hawkei_spec.rb +175 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/rack_app.rb +12 -0
- metadata +206 -0
@@ -0,0 +1,113 @@
|
|
1
|
+
module Hawkei
|
2
|
+
module Processor
|
3
|
+
class Worker
|
4
|
+
|
5
|
+
FLUSH_INTERVAL_SECONDS = 3
|
6
|
+
|
7
|
+
FLUSH_MESSAGE = Object.new
|
8
|
+
SHUTDOWN_MESSAGE = Object.new
|
9
|
+
|
10
|
+
def initialize(queue, state)
|
11
|
+
@queue = queue
|
12
|
+
@state = state
|
13
|
+
|
14
|
+
@batch = Batch.new
|
15
|
+
@promises = Concurrent::Array.new
|
16
|
+
|
17
|
+
@timer = Concurrent::TimerTask.new(execution_interval: FLUSH_INTERVAL_SECONDS) { @queue << FLUSH_MESSAGE }
|
18
|
+
@timer.execute
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
while thread_active?
|
23
|
+
message = @queue.pop
|
24
|
+
|
25
|
+
add_message_to_batch(message)
|
26
|
+
end
|
27
|
+
|
28
|
+
shutdown_worker
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
##
|
34
|
+
# Add the message to a batch
|
35
|
+
#
|
36
|
+
# - Add message to a batch if it's not a flush message
|
37
|
+
# - flush batch if flush message is receive or batch is full
|
38
|
+
def add_message_to_batch(message)
|
39
|
+
@batch << message if message != FLUSH_MESSAGE
|
40
|
+
flush if message == FLUSH_MESSAGE || @batch.full?
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Shutdown the worker
|
45
|
+
#
|
46
|
+
# - Close the timer
|
47
|
+
# - Retreive the last messages
|
48
|
+
# - Wait for all the request to be completed
|
49
|
+
#
|
50
|
+
# rubocop:disable Lint/HandleExceptions
|
51
|
+
def shutdown_worker
|
52
|
+
@timer.shutdown
|
53
|
+
|
54
|
+
begin
|
55
|
+
until (message = @queue.pop(true)).nil?
|
56
|
+
add_message_to_batch(message)
|
57
|
+
end
|
58
|
+
rescue ThreadError => _
|
59
|
+
end
|
60
|
+
|
61
|
+
flush
|
62
|
+
|
63
|
+
@promises.each do |promise|
|
64
|
+
promise.wait if promise && !promise.fulfilled?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# rubocop:enable Lint/HandleExceptions
|
68
|
+
|
69
|
+
def flush
|
70
|
+
return if @batch.empty?
|
71
|
+
|
72
|
+
send_batch(@batch)
|
73
|
+
@batch = Batch.new
|
74
|
+
end
|
75
|
+
|
76
|
+
# rubocop:disable Metrics/AbcSize
|
77
|
+
def send_batch(batch)
|
78
|
+
promise =
|
79
|
+
Concurrent::Promise
|
80
|
+
.new { Hawkei::Batch.create(Message.base.merge(data: batch.messages)) }
|
81
|
+
.on_success { @promises.delete(promise) }
|
82
|
+
.rescue do |error|
|
83
|
+
batch.update_retry
|
84
|
+
|
85
|
+
if error.is_a?(Hawkei::RequestError) && [401, 404].include?(error.http_status)
|
86
|
+
return logger.error(error.message)
|
87
|
+
end
|
88
|
+
|
89
|
+
if thread_active? && batch.can_retry?
|
90
|
+
Concurrent::ScheduledTask.new(batch.next_retry) { send_batch(batch) }.execute
|
91
|
+
else
|
92
|
+
@promises.delete(promise)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
promise.execute
|
97
|
+
@promises << promise
|
98
|
+
rescue Concurrent::RejectedExecutionError => _
|
99
|
+
logger.error('Impossible to start a thread in closing application')
|
100
|
+
end
|
101
|
+
# rubocop:enable Metrics/AbcSize
|
102
|
+
|
103
|
+
def thread_active?
|
104
|
+
@state.true?
|
105
|
+
end
|
106
|
+
|
107
|
+
def logger
|
108
|
+
Hawkei.configurations.logger
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Hawkei
|
2
|
+
##
|
3
|
+
# == Hawkei \Request
|
4
|
+
#
|
5
|
+
# Build request
|
6
|
+
class Request
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def execute(params = {})
|
10
|
+
klass = new(params)
|
11
|
+
|
12
|
+
if params[:method] == :post
|
13
|
+
klass.post
|
14
|
+
elsif params[:method] == :put
|
15
|
+
klass.put
|
16
|
+
elsif params[:method] == :delete
|
17
|
+
klass.delete
|
18
|
+
elsif params[:method] == :get
|
19
|
+
klass.get
|
20
|
+
else
|
21
|
+
raise Hawkei::UnknownRequestMethod, "#{params[:method]} haven't been implemented"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def post(params = {})
|
26
|
+
new(params).post
|
27
|
+
end
|
28
|
+
|
29
|
+
def put(params = {})
|
30
|
+
new(params).put
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(params = {})
|
34
|
+
new(params).get
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(params = {})
|
38
|
+
new(params).delete
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :params, :http, :request
|
43
|
+
|
44
|
+
def initialize(params = {})
|
45
|
+
@params = params
|
46
|
+
@http = Net::HTTP.new(uri.host, uri.port, uri_proxy.host, uri_proxy.port)
|
47
|
+
|
48
|
+
setup_ssl if params[:use_ssl]
|
49
|
+
end
|
50
|
+
|
51
|
+
def post
|
52
|
+
@request = Net::HTTP::Post.new(uri.path)
|
53
|
+
|
54
|
+
set_header
|
55
|
+
request.body = params[:payload]
|
56
|
+
|
57
|
+
handle_request
|
58
|
+
end
|
59
|
+
|
60
|
+
def put
|
61
|
+
@request = Net::HTTP::Put.new(uri.path)
|
62
|
+
|
63
|
+
set_header
|
64
|
+
request.body = params[:payload]
|
65
|
+
|
66
|
+
handle_request
|
67
|
+
end
|
68
|
+
|
69
|
+
def get
|
70
|
+
@request = Net::HTTP::Get.new(uri)
|
71
|
+
|
72
|
+
set_header
|
73
|
+
|
74
|
+
handle_request
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete
|
78
|
+
@request = Net::HTTP::Delete.new(uri.path)
|
79
|
+
|
80
|
+
set_header
|
81
|
+
request.body = params[:payload]
|
82
|
+
|
83
|
+
handle_request
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def handle_request
|
89
|
+
response = http.request(request)
|
90
|
+
|
91
|
+
case [response.code_type]
|
92
|
+
when [Net::HTTPOK], [Net::HTTPCreated], [Net::HTTPAccepted]
|
93
|
+
response
|
94
|
+
when [Net::HTTPUnauthorized]
|
95
|
+
raise RequestError.new(response, message: 'Unauthorized, please check your api key')
|
96
|
+
when [Net::HTTPNotFound]
|
97
|
+
raise RequestError.new(response, message: 'Requested Resource not found')
|
98
|
+
when [Net::HTTPRequestTimeOut]
|
99
|
+
raise RequestError.new(response, message: 'Server timeout, verify status of the server')
|
100
|
+
when [Net::HTTPInternalServerError]
|
101
|
+
raise RequestError.new(response, message: 'Server Error, please check with Hawkei')
|
102
|
+
else
|
103
|
+
raise RequestError, response
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_header
|
108
|
+
params[:headers].each do |(type, value)|
|
109
|
+
formated_type = type.to_s.split(/_/).map(&:capitalize).join('-')
|
110
|
+
request[formated_type] = value
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def setup_ssl
|
115
|
+
http.use_ssl = true
|
116
|
+
http.ca_file = params[:ca_file]
|
117
|
+
http.verify_mode = params[:verify_mode]
|
118
|
+
end
|
119
|
+
|
120
|
+
def uri
|
121
|
+
@uri ||= URI(params[:url])
|
122
|
+
end
|
123
|
+
|
124
|
+
def uri_proxy
|
125
|
+
@uri_proxy ||=
|
126
|
+
if params[:proxy]
|
127
|
+
URI(params[:proxy])
|
128
|
+
else
|
129
|
+
OpenStruct.new
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
data/lib/hawkei/store.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Hawkei
|
2
|
+
##
|
3
|
+
# == Hawkei \Store
|
4
|
+
#
|
5
|
+
# Store environment data
|
6
|
+
#
|
7
|
+
class Store
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def store
|
11
|
+
Thread.current[:request_store] ||= {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def clear!
|
15
|
+
Thread.current[:request_store] = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_from_hash(object = {})
|
19
|
+
clear!
|
20
|
+
bulk_set(Util.deep_symbolize_key(object)) if object.is_a?(Hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(key)
|
24
|
+
store[key]
|
25
|
+
end
|
26
|
+
alias [] get
|
27
|
+
|
28
|
+
def set(key, value)
|
29
|
+
store[key] = value
|
30
|
+
end
|
31
|
+
alias []= set
|
32
|
+
|
33
|
+
def bulk_set(attributes = {})
|
34
|
+
attributes.each do |(key, value)|
|
35
|
+
set(key, value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def exist?(key)
|
40
|
+
store.key?(key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete(key, &block)
|
44
|
+
store.delete(key, &block)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/hawkei/util.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
module Hawkei
|
2
|
+
module Util
|
3
|
+
class << self
|
4
|
+
|
5
|
+
DATE_FORMAT = '%Y/%m/%d'.freeze
|
6
|
+
OBFUSCATED = '[HIDDEN]'.freeze
|
7
|
+
DEFAULT_OBJECT_DEF = %w[id name].freeze
|
8
|
+
|
9
|
+
##
|
10
|
+
# Remove keys from a Hash
|
11
|
+
#
|
12
|
+
# @param [Hash] to be excepted
|
13
|
+
# @param [List[String]] to be excepted
|
14
|
+
#
|
15
|
+
# @return [Hash]
|
16
|
+
def except_keys(hash, *keys)
|
17
|
+
hash.dup.delete_if { |(key, _value)| keys.include?(key) }
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Convert string to camelize
|
22
|
+
#
|
23
|
+
# @param [String]
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# camelize('my_model') => 'MyModel'
|
27
|
+
def camelize(string)
|
28
|
+
string.split('_').map(&:capitalize).join
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Remove nil value from hash
|
33
|
+
#
|
34
|
+
# @return [Hash]
|
35
|
+
def compact(hash)
|
36
|
+
hash.reject { |_, value| value.nil? }
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Remove nil value from hash recursively
|
41
|
+
#
|
42
|
+
# @return [Hash]
|
43
|
+
def deep_compact(object)
|
44
|
+
object.each_with_object({}) do |(key, value), result|
|
45
|
+
if value.is_a?(Hash)
|
46
|
+
value = deep_compact(value)
|
47
|
+
result[key] = value if !value.nil? && !value.empty?
|
48
|
+
else
|
49
|
+
result[key] = value unless value.nil?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Encodes a hash of parameters in a way that's suitable for use as query
|
56
|
+
# parameters in a URI or as form parameters in a request body. This mainly
|
57
|
+
# involves escaping special characters from parameter keys and values (e.g.
|
58
|
+
# `&`).
|
59
|
+
def encode_parameters(params = {})
|
60
|
+
params.map { |k, v| "#{url_encode(k)}=#{url_encode(v)}" }.join('&')
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Encodes a string in a way that makes it suitable for use in a set of
|
65
|
+
# query parameters in a URI or in a set of form parameters in a request
|
66
|
+
# body.
|
67
|
+
def url_encode(key)
|
68
|
+
CGI.escape(key.to_s).gsub('%5B', '[').gsub('%5D', ']')
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Convert string to underscore
|
73
|
+
#
|
74
|
+
# @param [String]
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# underscore('MyModel') => 'my_model'
|
78
|
+
def underscore(string)
|
79
|
+
string
|
80
|
+
.gsub(/::/, '/')
|
81
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
82
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
83
|
+
.tr('-', '_')
|
84
|
+
.downcase
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Deep convert hash to underscore case keys
|
89
|
+
#
|
90
|
+
# @param [Hash] hash to transform
|
91
|
+
#
|
92
|
+
# @return [Hash] transformed
|
93
|
+
def deep_underscore_key(hash_object)
|
94
|
+
deep_transform_keys_in_object(hash_object) do |key|
|
95
|
+
begin
|
96
|
+
underscore(key).to_sym
|
97
|
+
rescue StandardError => _e
|
98
|
+
key
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Deep convert hash to string keys
|
105
|
+
#
|
106
|
+
# @param [Hash] hash to transform
|
107
|
+
#
|
108
|
+
# @return [Hash] transformed
|
109
|
+
def deep_stringify_key(hash_object)
|
110
|
+
deep_transform_keys_in_object(hash_object) do |key|
|
111
|
+
begin
|
112
|
+
key.to_s
|
113
|
+
rescue StandardError => _e
|
114
|
+
key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Deep convert hash to symbol keys
|
121
|
+
#
|
122
|
+
# @param [Hash] hash to transform
|
123
|
+
#
|
124
|
+
# @return [Hash] transformed
|
125
|
+
def deep_symbolize_key(hash_object)
|
126
|
+
deep_transform_keys_in_object(hash_object) do |key|
|
127
|
+
begin
|
128
|
+
key.to_sym
|
129
|
+
rescue StandardError => _e
|
130
|
+
key
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Deep remove key from hash
|
137
|
+
#
|
138
|
+
# @param [Hash] hash to obfuscate
|
139
|
+
#
|
140
|
+
# @return [Hash] hash obfuscated
|
141
|
+
def deep_obfuscate_value(object, fields, obfuscate_name = OBFUSCATED)
|
142
|
+
case object
|
143
|
+
when Hash
|
144
|
+
object.each_with_object({}) do |(key, value), result|
|
145
|
+
result[key] = fields.include?(key.to_s) ? obfuscate_name : deep_obfuscate_value(value, fields)
|
146
|
+
end
|
147
|
+
when Array
|
148
|
+
object.map { |e| deep_obfuscate_value(e, fields) }
|
149
|
+
else
|
150
|
+
object
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Parse JSON without raise
|
156
|
+
#
|
157
|
+
def safe_json_parse(data)
|
158
|
+
JSON.parse(data.to_s)
|
159
|
+
rescue JSON::ParserError
|
160
|
+
{}
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def deep_transform_keys_in_object(object, &block)
|
166
|
+
case object
|
167
|
+
when Hash
|
168
|
+
object.each_with_object({}) do |(key, value), result|
|
169
|
+
result[yield(key)] = deep_transform_keys_in_object(value, &block)
|
170
|
+
end
|
171
|
+
when Array
|
172
|
+
object.map { |e| deep_transform_keys_in_object(e, &block) }
|
173
|
+
else
|
174
|
+
object
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Hawkei
|
2
|
+
##
|
3
|
+
# == Hawkei \Watcher
|
4
|
+
#
|
5
|
+
# Create and update groups
|
6
|
+
#
|
7
|
+
# @example: Usage
|
8
|
+
#
|
9
|
+
# request = Hawkei::Watcher.create(template_flow: 'My Hawkei', expected_times: 42) #=> #<Hawkei::Response...>
|
10
|
+
#
|
11
|
+
class Watcher < APIResource
|
12
|
+
include Hawkei::APIOperation::Save
|
13
|
+
include Hawkei::APIOperation::Delete
|
14
|
+
end
|
15
|
+
end
|
data/lib/hawkei.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
# Lib
|
2
|
+
require 'securerandom'
|
3
|
+
require 'net/http'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'json'
|
6
|
+
require 'time'
|
7
|
+
require 'cgi'
|
8
|
+
require 'logger'
|
9
|
+
require 'concurrent'
|
10
|
+
|
11
|
+
# Base
|
12
|
+
require 'hawkei/version'
|
13
|
+
require 'hawkei/formated_logger'
|
14
|
+
require 'hawkei/library_name'
|
15
|
+
require 'hawkei/util'
|
16
|
+
require 'hawkei/config'
|
17
|
+
require 'hawkei/errors'
|
18
|
+
require 'hawkei/hawkei_object'
|
19
|
+
require 'hawkei/request'
|
20
|
+
require 'hawkei/api_resource'
|
21
|
+
require 'hawkei/store'
|
22
|
+
require 'hawkei/message'
|
23
|
+
|
24
|
+
# Processor
|
25
|
+
require 'hawkei/processor/async'
|
26
|
+
require 'hawkei/processor/worker'
|
27
|
+
require 'hawkei/processor/batch'
|
28
|
+
|
29
|
+
# Operations
|
30
|
+
require 'hawkei/api_operation/save'
|
31
|
+
require 'hawkei/api_operation/delete'
|
32
|
+
|
33
|
+
# Resources
|
34
|
+
require 'hawkei/watcher'
|
35
|
+
require 'hawkei/batch'
|
36
|
+
|
37
|
+
# Plugins
|
38
|
+
require 'hawkei/plugins'
|
39
|
+
|
40
|
+
##
|
41
|
+
# Implementation of the Hawkei
|
42
|
+
module Hawkei
|
43
|
+
class << self
|
44
|
+
|
45
|
+
TRACK_EVENTS_CREATE = 'track_events:create'.freeze
|
46
|
+
IDENTIFY_EVENTS_CREATE = 'identify_events:create'.freeze
|
47
|
+
GROUP_EVENTS_CREATE = 'group_events:create'.freeze
|
48
|
+
WATCHERS_CREATE_ACTION = 'watchers:create'.freeze
|
49
|
+
|
50
|
+
##
|
51
|
+
# @return [Hawkei::Config] configurations
|
52
|
+
attr_reader :configurations
|
53
|
+
|
54
|
+
##
|
55
|
+
# Configures the Hawkei API
|
56
|
+
#
|
57
|
+
# @example Default configuration
|
58
|
+
# Hawkei.configure do |config|
|
59
|
+
# config.api_key = 'acc_xx'
|
60
|
+
# config.space_name = 'Hawkei'
|
61
|
+
# config.environment_name = 'production'
|
62
|
+
# end
|
63
|
+
def configure
|
64
|
+
yield @configurations = Hawkei::Config.new
|
65
|
+
|
66
|
+
Hawkei.configurations.valid!
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Send a track event to the server
|
71
|
+
#
|
72
|
+
# @param [String] event name
|
73
|
+
# @param [Hash] payload to be send
|
74
|
+
# @param [Hash] options for the request
|
75
|
+
#
|
76
|
+
# @return [Boolean] status of the request
|
77
|
+
def track(name, payload = {}, options = {})
|
78
|
+
return true unless configurations.enabled
|
79
|
+
|
80
|
+
payload[:name] = name
|
81
|
+
Hawkei::Plugins::Rails::Data.store_data if defined?(Hawkei::Plugins::Rails::Data)
|
82
|
+
|
83
|
+
payload = Message.extended.merge(payload)
|
84
|
+
|
85
|
+
processor.enqueue(
|
86
|
+
action: TRACK_EVENTS_CREATE,
|
87
|
+
payload: payload,
|
88
|
+
options: options.select { |k, _v| %i[space_name environment_name].include?(k) },
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Send an identify event to the server
|
94
|
+
#
|
95
|
+
# @param [String] user id from your database
|
96
|
+
# @param [Hash] payload to be send
|
97
|
+
# @param [Hash] options for the request
|
98
|
+
#
|
99
|
+
# @return [Boolean] status of the request
|
100
|
+
def identify(user_id, payload = {}, options = {})
|
101
|
+
return true unless configurations.enabled
|
102
|
+
|
103
|
+
payload[:user_id] = user_id
|
104
|
+
Hawkei::Plugins::Rails::Data.store_data if defined?(Hawkei::Plugins::Rails::Data)
|
105
|
+
|
106
|
+
payload = Message.extended.merge(payload)
|
107
|
+
|
108
|
+
processor.enqueue(
|
109
|
+
action: IDENTIFY_EVENTS_CREATE,
|
110
|
+
payload: payload,
|
111
|
+
options: options.select { |k, _v| %i[space_name environment_name].include?(k) },
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
##
|
116
|
+
# Send a create/update for a group
|
117
|
+
#
|
118
|
+
# @param [String] group id from your database
|
119
|
+
# @param [Hash] payload to be send
|
120
|
+
# @param [Hash] options for the request
|
121
|
+
#
|
122
|
+
# @return [Boolean] status of the request
|
123
|
+
def group(group_id, payload = {}, options = {})
|
124
|
+
return true unless configurations.enabled
|
125
|
+
|
126
|
+
payload = Message.base.merge(payload)
|
127
|
+
payload[:group_id] = group_id
|
128
|
+
|
129
|
+
processor.enqueue(
|
130
|
+
action: GROUP_EVENTS_CREATE,
|
131
|
+
payload: payload,
|
132
|
+
options: options.select { |k, _v| %i[space_name environment_name].include?(k) },
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Send a create a watcher
|
138
|
+
#
|
139
|
+
# @param [String|Integer] template hawkei name or id
|
140
|
+
# @param [Hash] payload to be send
|
141
|
+
# @param [Hash] options for the request
|
142
|
+
#
|
143
|
+
# @return [Boolean|Watcher] status of the request
|
144
|
+
def watch(flow, payload = {}, options = {})
|
145
|
+
return true unless configurations.enabled
|
146
|
+
|
147
|
+
payload[:template_flow] = flow
|
148
|
+
payload = Message.base.merge(payload)
|
149
|
+
|
150
|
+
payload.delete(:session_tracker_id) if payload.delete(:without_session)
|
151
|
+
|
152
|
+
if options[:sync]
|
153
|
+
Watcher.create(payload, options)
|
154
|
+
else
|
155
|
+
processor.enqueue(
|
156
|
+
action: WATCHERS_CREATE_ACTION,
|
157
|
+
payload: payload,
|
158
|
+
options: options.select { |k, _v| %i[space_name environment_name].include?(k) },
|
159
|
+
)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def processor
|
166
|
+
@processor ||= Processor::Async.new
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
end
|