liveqa 1.8.3 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -2
- data/.travis.yml +0 -1
- data/LICENCE +21 -0
- data/README.md +10 -117
- data/lib/liveqa/api_resource.rb +7 -3
- data/lib/liveqa/batch.rb +18 -0
- data/lib/liveqa/config.rb +13 -21
- data/lib/liveqa/event.rb +1 -1
- data/lib/liveqa/formated_logger.rb +45 -0
- data/lib/liveqa/message.rb +3 -3
- data/lib/liveqa/plugins/rack/middleware.rb +3 -3
- data/lib/liveqa/plugins/sidekiq/server_middleware.rb +1 -1
- data/lib/liveqa/processor/async.rb +48 -0
- data/lib/liveqa/processor/batch.rb +81 -0
- data/lib/liveqa/processor/worker.rb +66 -0
- data/lib/liveqa/util.rb +3 -3
- data/lib/liveqa/version.rb +1 -1
- data/lib/liveqa.rb +66 -33
- data/liveqa.gemspec +3 -3
- data/spec/lib/liveqa/api_resource_spec.rb +8 -8
- data/spec/lib/liveqa/batch_spec.rb +14 -0
- data/spec/lib/liveqa/config_spec.rb +9 -15
- data/spec/lib/liveqa/formated_logger_spec.rb +99 -0
- data/spec/lib/liveqa/processor/async_spec.rb +19 -0
- data/spec/lib/liveqa/processor/batch_spec.rb +48 -0
- data/spec/lib/liveqa/processor/worker_spec.rb +25 -0
- data/spec/lib/liveqa_spec.rb +133 -40
- metadata +26 -16
- data/lib/liveqa/async_handlers/base.rb +0 -15
- data/lib/liveqa/async_handlers/sidekiq.rb +0 -33
- data/spec/lib/liveqa/async_handlers/base_spec.rb +0 -29
- data/spec/lib/liveqa/async_handlers/sidekiq_spec.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e2af9cc4ebfb7e97a8330c769db5ffb49989ec9
|
4
|
+
data.tar.gz: 4261ba5bbe8cbebd535f876fe9f8762e460286cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f5fc2bd622bdf4e98573f3205ced2fce4ae9b569e398ab28633654cffaf2a3c1e2532c63da9f8352bcc74482d787fd6958104d0c02d52afe83baf3596374595
|
7
|
+
data.tar.gz: 7e2fccdb0c9a117a852989f3ab3e7744b958a0f31f3014cff519614492b3d3cdc862956e375ef6f715c747908170674708ca034a2b578d41201b3c9034f84a91
|
data/.rubocop.yml
CHANGED
@@ -22,7 +22,13 @@ Layout/EmptyLinesAroundBlockBody:
|
|
22
22
|
|
23
23
|
Style/FrozenStringLiteralComment:
|
24
24
|
Enabled: false
|
25
|
-
Style/
|
25
|
+
Style/MissingRespondToMissing:
|
26
|
+
Enabled: false
|
27
|
+
Style/TrailingCommaInHashLiteral:
|
28
|
+
EnforcedStyleForMultiline: comma
|
29
|
+
Style/TrailingCommaInArrayLiteral:
|
30
|
+
EnforcedStyleForMultiline: comma
|
31
|
+
Style/TrailingCommaInArguments:
|
26
32
|
Enabled: false
|
27
33
|
|
28
34
|
Documentation:
|
@@ -32,7 +38,7 @@ Bundler/DuplicatedGem:
|
|
32
38
|
Enabled: false
|
33
39
|
|
34
40
|
AllCops:
|
35
|
-
TargetRubyVersion: 2.
|
41
|
+
TargetRubyVersion: 2.2
|
36
42
|
Exclude:
|
37
43
|
- 'spec/**/*'
|
38
44
|
Exclude:
|
data/.travis.yml
CHANGED
data/LICENCE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018- LiveQA, Inc. (https://www.liveqa.com)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,127 +1,20 @@
|
|
1
1
|
# LiveQA
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/
|
3
|
+
[![Build Status](https://travis-ci.org/LiveQA/liveqa-ruby.svg?branch=master)](https://travis-ci.org/LiveQA/liveqa-ruby)
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
```sh
|
10
|
-
gem install liveqa
|
11
|
-
```
|
12
|
-
|
13
|
-
For Rails in your Gemfile
|
14
|
-
|
15
|
-
```ruby
|
16
|
-
gem 'liveqa'
|
17
|
-
```
|
18
|
-
|
19
|
-
## Configuration
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
LiveQA.configure do |config|
|
23
|
-
##
|
24
|
-
# Account token can be found inside your environment settings
|
25
|
-
config.account_token = 'acc_xx'
|
26
|
-
|
27
|
-
##
|
28
|
-
# The name of your space
|
29
|
-
config.space_name = 'LiveQA'
|
30
|
-
|
31
|
-
##
|
32
|
-
# The name of your environement
|
33
|
-
config.environment_name = 'production'
|
34
|
-
|
35
|
-
##
|
36
|
-
# If you use a proxy.
|
37
|
-
# default: nil
|
38
|
-
# config.proxy_url = ENV['HTTP_PROXY']
|
39
|
-
|
40
|
-
##
|
41
|
-
# If enabled is set to false nothing is send to the server
|
42
|
-
# default: true
|
43
|
-
# config.enabled = true
|
44
|
-
|
45
|
-
##
|
46
|
-
# Extra attributes to be obfuscated
|
47
|
-
# default: []
|
48
|
-
# config.obfuscated_fields = ['credit_card_number']
|
49
|
-
|
50
|
-
##
|
51
|
-
# Use an async handler to send data to the liveqa to
|
52
|
-
# avoid slowing down your application
|
53
|
-
# available option: :sidekiq
|
54
|
-
# default: nil
|
55
|
-
# config.async_handler = :sidekiq
|
56
|
-
|
57
|
-
##
|
58
|
-
# Options to be passed to the async handler
|
59
|
-
# default: {}
|
60
|
-
# config.async_options = { queue: 'liveqa' }
|
5
|
+
[LiveQA](https://www.liveqa.io) Ruby library
|
61
6
|
|
62
|
-
|
63
|
-
# Metadata is passed with every request to the server
|
64
|
-
# default: nil
|
65
|
-
# config.metadata = {
|
66
|
-
#. customer: -> { current_customer.id},
|
67
|
-
#. version: 42
|
68
|
-
# }
|
69
|
-
#
|
70
|
-
end
|
71
|
-
```
|
7
|
+
Our Ruby library let's you interact easily with our API. All the request will go to our servers and will be display processed and display inside our debugger.
|
72
8
|
|
73
|
-
##
|
9
|
+
## Setup
|
74
10
|
|
75
|
-
|
11
|
+
- [Start by creating an account](https://www.liveqa.io/register)
|
12
|
+
- Follow the [Quick Start Guide](https://docs.liveqa.io/docs/quick-start) to get set up
|
13
|
+
- Use our [Ruby Library](https://docs.liveqa.io/docs/ruby) to install and configure LiveQA for your platform.
|
76
14
|
|
77
|
-
Track an event
|
78
15
|
|
79
|
-
|
16
|
+
## Documentation & Usage
|
80
17
|
|
81
|
-
|
82
|
-
* `Hash` event attributes
|
18
|
+
Documentation is available at [docs.liveqa.io/docs/ruby](https://docs.liveqa.io/docs/ruby)
|
83
19
|
|
84
|
-
|
85
|
-
LiveQA.track('my event',
|
86
|
-
user_id: 42,
|
87
|
-
properties: {
|
88
|
-
order_id: 84
|
89
|
-
}
|
90
|
-
);
|
91
|
-
```
|
92
|
-
|
93
|
-
### Identify
|
94
|
-
|
95
|
-
Identify a user
|
96
|
-
|
97
|
-
Attributes:
|
98
|
-
|
99
|
-
* `String` user id from your database
|
100
|
-
* `Hash` user attributes
|
101
|
-
|
102
|
-
```ruby
|
103
|
-
LiveQA.identify(42,
|
104
|
-
properties: {
|
105
|
-
name: 'John Doe'
|
106
|
-
}
|
107
|
-
);
|
108
|
-
```
|
109
|
-
|
110
|
-
### Watch
|
111
|
-
|
112
|
-
Create a watcher
|
113
|
-
|
114
|
-
Attributes:
|
115
|
-
|
116
|
-
* `String|Integer` template flow name or id
|
117
|
-
* `Hash` watcher attributes
|
118
|
-
|
119
|
-
```ruby
|
120
|
-
LiveQA.watch('My Flow',
|
121
|
-
expected_times: 42
|
122
|
-
);
|
123
|
-
```
|
124
|
-
|
125
|
-
## Issues
|
126
|
-
|
127
|
-
If you have any issue you can report them on github, or contact support@liveqa.io
|
20
|
+
LiveQA ruby integration for [LiveQA](https://www.liveqa.io)
|
data/lib/liveqa/api_resource.rb
CHANGED
@@ -60,7 +60,9 @@ module LiveQA
|
|
60
60
|
#
|
61
61
|
# @return [Hash] response
|
62
62
|
# @raise [LiveQA::RequestError] if the request is invalid
|
63
|
+
# rubocop:disable Metrics/AbcSize
|
63
64
|
def request(method, path, payload = {}, options = {})
|
65
|
+
payload[:sent_at] = Time.now.utc.iso8601(3)
|
64
66
|
payload = Util.deep_obfuscate_value(payload, configurations.obfuscated_fields)
|
65
67
|
url_params = Util.encode_parameters(payload) if method == :get
|
66
68
|
uri = build_endpoint_url(path, url_params)
|
@@ -76,7 +78,9 @@ module LiveQA
|
|
76
78
|
Request.execute(request_options).body
|
77
79
|
rescue LiveQA::RequestError => error
|
78
80
|
return error.http_body if error.http_status == 422
|
81
|
+
raise
|
79
82
|
end
|
83
|
+
# rubocop:enable Metrics/AbcSize
|
80
84
|
|
81
85
|
private
|
82
86
|
|
@@ -99,7 +103,7 @@ module LiveQA
|
|
99
103
|
return {} unless configurations.http_secure
|
100
104
|
{
|
101
105
|
ca_file: File.expand_path(File.dirname(__FILE__) + '/../../vendor/cacert.pem'),
|
102
|
-
verify_mode: OpenSSL::SSL::VERIFY_PEER
|
106
|
+
verify_mode: OpenSSL::SSL::VERIFY_PEER,
|
103
107
|
}
|
104
108
|
end
|
105
109
|
|
@@ -110,8 +114,8 @@ module LiveQA
|
|
110
114
|
content_type: 'application/json',
|
111
115
|
x_account_token: options.delete(:account_token) || configurations.account_token,
|
112
116
|
x_space_name: options.delete(:space_name) || configurations.space_name,
|
113
|
-
x_environment_name: options.delete(:environment_name) || configurations.environment_name
|
114
|
-
}
|
117
|
+
x_environment_name: options.delete(:environment_name) || configurations.environment_name,
|
118
|
+
},
|
115
119
|
}
|
116
120
|
end
|
117
121
|
|
data/lib/liveqa/batch.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module LiveQA
|
2
|
+
##
|
3
|
+
# == LiveQA \Batch
|
4
|
+
#
|
5
|
+
# Accepted Methods:
|
6
|
+
#
|
7
|
+
# * create
|
8
|
+
#
|
9
|
+
# @example: Usage
|
10
|
+
#
|
11
|
+
# request = LiveQA::Batch.create(...) #=> #<LiveQA::Response...>
|
12
|
+
#
|
13
|
+
class Batch < APIResource
|
14
|
+
@resource_name = 'batches'
|
15
|
+
|
16
|
+
include LiveQA::APIOperation::Save
|
17
|
+
end
|
18
|
+
end
|
data/lib/liveqa/config.rb
CHANGED
@@ -5,13 +5,6 @@ module LiveQA
|
|
5
5
|
# Represent the LiveQA configuration for the API
|
6
6
|
class Config
|
7
7
|
|
8
|
-
ASYNC_HANDLERS = {
|
9
|
-
sidekiq: {
|
10
|
-
class: 'LiveQA::AsyncHandlers::Sidekiq',
|
11
|
-
require: 'liveqa/async_handlers/sidekiq'
|
12
|
-
}
|
13
|
-
}.freeze
|
14
|
-
|
15
8
|
DEFAULT_OBFUSCATED_FIELDS = %w[
|
16
9
|
password
|
17
10
|
password_confirmation
|
@@ -63,12 +56,8 @@ module LiveQA
|
|
63
56
|
attr_accessor :obfuscated_fields
|
64
57
|
|
65
58
|
##
|
66
|
-
# @return [
|
67
|
-
attr_accessor :
|
68
|
-
|
69
|
-
##
|
70
|
-
# @return [Hash] options for asynchronous handler
|
71
|
-
attr_accessor :async_options
|
59
|
+
# @return [Boolean] send
|
60
|
+
attr_accessor :async
|
72
61
|
|
73
62
|
##
|
74
63
|
# @return [Hash] custom object properties
|
@@ -78,6 +67,14 @@ module LiveQA
|
|
78
67
|
# @return [Hash] metadata to be attach to the payload
|
79
68
|
attr_accessor :metadata
|
80
69
|
|
70
|
+
##
|
71
|
+
# @return [Boolean] enable the logger
|
72
|
+
attr_accessor :log
|
73
|
+
|
74
|
+
##
|
75
|
+
# @return [Logger] logger
|
76
|
+
attr_accessor :logger
|
77
|
+
|
81
78
|
##
|
82
79
|
# @param [Hash{Symbol=>Object}]
|
83
80
|
# Initialize and validate the configuration
|
@@ -93,10 +90,11 @@ module LiveQA
|
|
93
90
|
self.http_secure = options[:http_secure] || true
|
94
91
|
self.enabled = options[:enabled] || true
|
95
92
|
self.obfuscated_fields = options[:obfuscated_fields] || []
|
96
|
-
self.
|
97
|
-
self.async_options = options[:async_options] || {}
|
93
|
+
self.async = options[:async] || true
|
98
94
|
self.custom_object_properties = options[:custom_object_properties] || {}
|
99
95
|
self.metadata = options[:metadata]
|
96
|
+
self.log = options[:log] || true
|
97
|
+
self.logger = FormatedLogger.build(options[:logger])
|
100
98
|
end
|
101
99
|
# rubocop:enable Metrics/CyclomaticComplexity
|
102
100
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -121,15 +119,9 @@ module LiveQA
|
|
121
119
|
# Format configuration fields
|
122
120
|
#
|
123
121
|
# * Set obfuscated_fields to string
|
124
|
-
# * Change to the class for async handler
|
125
122
|
#
|
126
123
|
def format!
|
127
124
|
self.obfuscated_fields = (obfuscated_fields.map(&:to_s) + DEFAULT_OBFUSCATED_FIELDS).uniq
|
128
|
-
|
129
|
-
return unless ASYNC_HANDLERS[async_handler]
|
130
|
-
|
131
|
-
require ASYNC_HANDLERS[async_handler][:require]
|
132
|
-
self.async_handler = Object.const_get(ASYNC_HANDLERS[async_handler][:class]).new(async_options)
|
133
125
|
end
|
134
126
|
|
135
127
|
def validate_presence(field)
|
data/lib/liveqa/event.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
module LiveQA
|
2
|
+
##
|
3
|
+
# Display formated log
|
4
|
+
class FormatedLogger
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def build(logger)
|
9
|
+
return new(logger) if logger
|
10
|
+
return new(Rails.logger) if defined?(Rails)
|
11
|
+
|
12
|
+
new(::Logger.new(STDOUT))
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :logger
|
18
|
+
|
19
|
+
PREFIX = '[LiveQA]'.freeze
|
20
|
+
METHODS = %i[debug info warn error].freeze
|
21
|
+
|
22
|
+
def initialize(logger)
|
23
|
+
@logger = logger
|
24
|
+
end
|
25
|
+
|
26
|
+
METHODS.each do |method|
|
27
|
+
define_method(method) do |message|
|
28
|
+
log(method, message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def log(type, message)
|
35
|
+
return unless configurations.log
|
36
|
+
|
37
|
+
logger.send(type, "#{PREFIX} #{message}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def configurations
|
41
|
+
LiveQA.configurations
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
data/lib/liveqa/message.rb
CHANGED
@@ -37,7 +37,7 @@ module LiveQA
|
|
37
37
|
{
|
38
38
|
name: LiveQA::LIBRARY_NAME,
|
39
39
|
language: 'ruby',
|
40
|
-
version: LiveQA::VERSION
|
40
|
+
version: LiveQA::VERSION,
|
41
41
|
}
|
42
42
|
end
|
43
43
|
|
@@ -45,7 +45,7 @@ module LiveQA
|
|
45
45
|
{
|
46
46
|
host: Socket.gethostname,
|
47
47
|
pid: Process.pid,
|
48
|
-
software: LiveQA::Store.get(:server_software)
|
48
|
+
software: LiveQA::Store.get(:server_software),
|
49
49
|
}
|
50
50
|
end
|
51
51
|
|
@@ -56,7 +56,7 @@ module LiveQA
|
|
56
56
|
if value.is_a?(Proc)
|
57
57
|
begin
|
58
58
|
hash[key] = value.call
|
59
|
-
rescue
|
59
|
+
rescue StandardError => _e
|
60
60
|
nil
|
61
61
|
end
|
62
62
|
next
|
@@ -90,7 +90,7 @@ module LiveQA
|
|
90
90
|
uri.merge(
|
91
91
|
"?#{::Rack::Utils.build_query(params)}"
|
92
92
|
).to_s
|
93
|
-
rescue
|
93
|
+
rescue StandardError => _e
|
94
94
|
''
|
95
95
|
end
|
96
96
|
|
@@ -99,7 +99,7 @@ module LiveQA
|
|
99
99
|
request.send(type),
|
100
100
|
LiveQA.configurations.obfuscated_fields
|
101
101
|
)
|
102
|
-
rescue
|
102
|
+
rescue StandardError => _e
|
103
103
|
{}
|
104
104
|
end
|
105
105
|
|
@@ -125,7 +125,7 @@ module LiveQA
|
|
125
125
|
headers,
|
126
126
|
LiveQA.configurations.obfuscated_fields
|
127
127
|
)
|
128
|
-
rescue
|
128
|
+
rescue StandardError => _e
|
129
129
|
{}
|
130
130
|
end
|
131
131
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module LiveQA
|
2
|
+
module Processor
|
3
|
+
class Async
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@max_queue_size = 10_000
|
7
|
+
@queue = Queue.new
|
8
|
+
@worker = Worker.new(@queue)
|
9
|
+
@worker_mutex = Mutex.new
|
10
|
+
|
11
|
+
at_exit do
|
12
|
+
@worker_thread && @worker_thread[:should_exit] = true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def enqueue(attributes)
|
17
|
+
return false if @queue.length > @max_queue_size
|
18
|
+
|
19
|
+
@queue << attributes
|
20
|
+
ensure_worker_running
|
21
|
+
|
22
|
+
true
|
23
|
+
end
|
24
|
+
|
25
|
+
def flush
|
26
|
+
while !@queue.empty? || @worker.is_requesting?
|
27
|
+
ensure_worker_running
|
28
|
+
sleep(0.1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def ensure_worker_running
|
35
|
+
return if worker_running?
|
36
|
+
@worker_mutex.synchronize do
|
37
|
+
return if worker_running?
|
38
|
+
@worker_thread = Thread.new { @worker.run }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def worker_running?
|
43
|
+
@worker_thread && @worker_thread.alive?
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module LiveQA
|
2
|
+
module Processor
|
3
|
+
class Batch
|
4
|
+
|
5
|
+
attr_reader :messages
|
6
|
+
|
7
|
+
MAX_BYTES = 204_800 # 200Kb
|
8
|
+
MAX_MESSAGES = 100
|
9
|
+
MAX_MESSAGE_BYTES = 32_768 # 32Kb
|
10
|
+
|
11
|
+
MAX_RETRY = 10
|
12
|
+
RETRY_MAP = {
|
13
|
+
1 => 2,
|
14
|
+
2 => 5,
|
15
|
+
3 => 10,
|
16
|
+
4 => 20,
|
17
|
+
5 => 30,
|
18
|
+
6 => 30,
|
19
|
+
7 => 30,
|
20
|
+
8 => 30,
|
21
|
+
9 => 30,
|
22
|
+
10 => 30,
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@retry_count = 0
|
27
|
+
@total_bytes = 0
|
28
|
+
@messages = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def <<(message)
|
32
|
+
message_json_size = message.to_json.bytesize
|
33
|
+
|
34
|
+
if max_message_reached?(message_json_size)
|
35
|
+
LiveQA.configurations.logger.error('Message is too big to be send')
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
|
39
|
+
@total_bytes += message_json_size
|
40
|
+
|
41
|
+
@messages << message
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def full?
|
47
|
+
max_messages_reached? || max_size_reached?
|
48
|
+
end
|
49
|
+
|
50
|
+
def update_retry
|
51
|
+
@retry_count += 1
|
52
|
+
@retry_at = Time.now + (RETRY_MAP[@retry_count] || 120)
|
53
|
+
end
|
54
|
+
|
55
|
+
def can_run?
|
56
|
+
return true if @retry_count.zero?
|
57
|
+
|
58
|
+
Time.now >= @retry_at
|
59
|
+
end
|
60
|
+
|
61
|
+
def can_retry?
|
62
|
+
@retry_count < MAX_RETRY
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def max_messages_reached?
|
68
|
+
@messages.length >= MAX_MESSAGES
|
69
|
+
end
|
70
|
+
|
71
|
+
def max_size_reached?
|
72
|
+
@total_bytes >= MAX_BYTES
|
73
|
+
end
|
74
|
+
|
75
|
+
def max_message_reached?(message_json_size)
|
76
|
+
message_json_size > MAX_MESSAGE_BYTES
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module LiveQA
|
2
|
+
module Processor
|
3
|
+
class Worker
|
4
|
+
|
5
|
+
DEFAULT_WAIT_TIME = 2
|
6
|
+
|
7
|
+
attr_reader :queue
|
8
|
+
attr_reader :lock
|
9
|
+
attr_reader :batches
|
10
|
+
|
11
|
+
def initialize(queue)
|
12
|
+
@queue = queue
|
13
|
+
@lock = Mutex.new
|
14
|
+
@batches = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
until Thread.current[:should_exit]
|
19
|
+
return if queue.empty? && batches.empty?
|
20
|
+
|
21
|
+
sleep(DEFAULT_WAIT_TIME) if queue.empty?
|
22
|
+
|
23
|
+
create_new_batch unless queue.empty?
|
24
|
+
|
25
|
+
send_batches
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def create_new_batch
|
32
|
+
batch = Batch.new
|
33
|
+
lock.synchronize do
|
34
|
+
batch << queue.pop until batch.full? || queue.empty?
|
35
|
+
end
|
36
|
+
batches.push(batch)
|
37
|
+
end
|
38
|
+
|
39
|
+
def send_batches
|
40
|
+
batches.dup.each do
|
41
|
+
batch = batches.pop
|
42
|
+
|
43
|
+
unless batch.can_run?
|
44
|
+
batches.push(batch)
|
45
|
+
next
|
46
|
+
end
|
47
|
+
|
48
|
+
begin
|
49
|
+
LiveQA::Batch.create(Message.base.merge(data: batch.messages))
|
50
|
+
rescue LiveQA::RequestError => error
|
51
|
+
return LiveQA.configurations.logger.error(error.message) if [401, 404].include?(error.http_status)
|
52
|
+
batch_retry(batch)
|
53
|
+
rescue Errno::ECONNREFUSED => _error
|
54
|
+
batch_retry(batch)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def batch_retry(batch)
|
60
|
+
batch.update_retry
|
61
|
+
batches.push(batch) if batch.can_retry?
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/liveqa/util.rb
CHANGED
@@ -94,7 +94,7 @@ module LiveQA
|
|
94
94
|
deep_transform_keys_in_object(hash_object) do |key|
|
95
95
|
begin
|
96
96
|
underscore(key).to_sym
|
97
|
-
rescue
|
97
|
+
rescue StandardError => _e
|
98
98
|
key
|
99
99
|
end
|
100
100
|
end
|
@@ -110,7 +110,7 @@ module LiveQA
|
|
110
110
|
deep_transform_keys_in_object(hash_object) do |key|
|
111
111
|
begin
|
112
112
|
key.to_s
|
113
|
-
rescue
|
113
|
+
rescue StandardError => _e
|
114
114
|
key
|
115
115
|
end
|
116
116
|
end
|
@@ -126,7 +126,7 @@ module LiveQA
|
|
126
126
|
deep_transform_keys_in_object(hash_object) do |key|
|
127
127
|
begin
|
128
128
|
key.to_sym
|
129
|
-
rescue
|
129
|
+
rescue StandardError => _e
|
130
130
|
key
|
131
131
|
end
|
132
132
|
end
|
data/lib/liveqa/version.rb
CHANGED