apisonator 2.100.2 → 2.101.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36a24cd40b3b9d707a5b4c06243a17c11fa0d3e42929dd0c5f5edc5aae5e35fd
4
- data.tar.gz: c523234e3ce2afeaf1b536a99b138532020643574cd24173e8457187c1cc9693
3
+ metadata.gz: 4740b1613c8bd2182adf9587db2a2ae6667a50ee140c99c679c232b6da3b7193
4
+ data.tar.gz: 0e34376e2e788194b44eeb5aedf7d8654110c8baa4a0885ed2c55a3a28fcb0c1
5
5
  SHA512:
6
- metadata.gz: 93da0370affbadcbf04cba8e213faa5d7cc2ff03ec2e848436596c54b5fec05d6bf0847da4d799243d62c46f7cab6c8121010c975a174b6d5beb5f4d63280019
7
- data.tar.gz: '07685172c1e7f102a9fe0ed967cbcd61dfbbe138d8f6447a0183e5a6ba28a7873b96e52ff72206d268fa233642f1195de0b6a8a7ab777e4e90f39146d35fa618'
6
+ metadata.gz: c6431c06f07433710308ef8b9121d2975415cbec27d2c82db3c8f13c4a0dab364b6a9085a550a530bd000a18234bfd63d67ee555ea69299f8745734725f9f436
7
+ data.tar.gz: 90618d349784bfe5ff9d78b940f93d7b63013fb9f1ec1b9c68f03881ff9e13a165d0532a98d50c26218402cc197c3f9f730f7b34ca26589cb8f4b91fa37e6cab
@@ -2,6 +2,24 @@
2
2
 
3
3
  Notable changes to Apisonator will be tracked in this document.
4
4
 
5
+ ## 2.101.0 - 2020-06-04
6
+
7
+ ### Added
8
+
9
+ - Introduced the `CONFIG_REDIS_MAX_CONNS` and `CONFIG_QUEUES_MAX_CONNS` ENVs to
10
+ configure the max number of Redis connections when using the async mode
11
+ ([#214](https://github.com/3scale/apisonator/pull/214)).
12
+
13
+ ### Changed
14
+
15
+ - Perf optimization: loading the usage limits is now done more efficiently.
16
+ There is a noticeable improvement in requests with `no_body` enabled for
17
+ services with many metrics defined
18
+ ([#221](https://github.com/3scale/apisonator/pull/221)).
19
+ - Updated activesupport to 5.2.4.3
20
+ ([#217](https://github.com/3scale/apisonator/pull/217)).
21
+
22
+
5
23
  ## 2.100.2 - 2020-05-08
6
24
 
7
25
  ### Changed
@@ -25,7 +25,6 @@ group :test do
25
25
  gem 'resque_spec', '~> 0.17.0'
26
26
  gem 'timecop', '~> 0.9.1'
27
27
  gem 'rspec', '~> 3.7.0', require: nil
28
- gem 'geminabox', '~> 0.13.11', require: false
29
28
  gem 'codeclimate-test-reporter', '~> 0.6.0', require: nil
30
29
  gem 'async-rspec'
31
30
  end
@@ -35,14 +35,14 @@ GIT
35
35
  PATH
36
36
  remote: .
37
37
  specs:
38
- apisonator (2.100.2)
38
+ apisonator (2.101.0)
39
39
 
40
40
  GEM
41
41
  remote: https://rubygems.org/
42
42
  specs:
43
- activesupport (5.1.4)
43
+ activesupport (5.2.4.3)
44
44
  concurrent-ruby (~> 1.0, >= 1.0.2)
45
- i18n (~> 0.7)
45
+ i18n (>= 0.7, < 2)
46
46
  minitest (~> 5.1)
47
47
  tzinfo (~> 1.1)
48
48
  airbrake (4.3.1)
@@ -95,7 +95,7 @@ GEM
95
95
  codeclimate-test-reporter (0.6.0)
96
96
  simplecov (>= 0.7.1, < 1.0.0)
97
97
  coderay (1.1.2)
98
- concurrent-ruby (1.0.5)
98
+ concurrent-ruby (1.1.6)
99
99
  console (1.8.2)
100
100
  daemons (1.2.4)
101
101
  diff-lcs (1.3)
@@ -112,20 +112,10 @@ GEM
112
112
  process-metrics (~> 0.1.0)
113
113
  rack (>= 1.0)
114
114
  samovar (~> 2.1)
115
- faraday (0.13.1)
116
- multipart-post (>= 1.2, < 3)
117
115
  ffi (1.12.2)
118
- geminabox (0.13.11)
119
- builder
120
- faraday
121
- httpclient (>= 2.2.7)
122
- nesty
123
- reentrant_flock
124
- sinatra (>= 1.2.7)
125
116
  gli (2.16.1)
126
117
  hiredis (0.6.3)
127
- httpclient (2.8.3)
128
- i18n (0.9.1)
118
+ i18n (1.8.2)
129
119
  concurrent-ruby (~> 1.0)
130
120
  jmespath (1.3.1)
131
121
  json (2.1.0)
@@ -141,15 +131,13 @@ GEM
141
131
  metaclass (0.0.4)
142
132
  method_source (0.9.0)
143
133
  mini_portile2 (2.4.0)
144
- minitest (5.10.3)
134
+ minitest (5.14.1)
145
135
  mocha (1.3.0)
146
136
  metaclass (~> 0.0.1)
147
137
  mono_logger (1.1.0)
148
138
  multi_json (1.13.1)
149
- multipart-post (2.0.0)
150
139
  mustache (1.0.5)
151
140
  mustermann (1.0.2)
152
- nesty (1.0.2)
153
141
  net-scp (1.2.1)
154
142
  net-ssh (>= 2.6.5)
155
143
  net-ssh (4.2.0)
@@ -191,7 +179,6 @@ GEM
191
179
  rake (13.0.1)
192
180
  redis-namespace (1.6.0)
193
181
  redis (>= 3.0.4)
194
- reentrant_flock (0.1.1)
195
182
  resque_spec (0.17.0)
196
183
  resque (>= 1.19.0)
197
184
  rspec-core (>= 3.0.0)
@@ -256,7 +243,7 @@ GEM
256
243
  timers (4.3.0)
257
244
  toml (0.2.0)
258
245
  parslet (~> 1.8.0)
259
- tzinfo (1.2.4)
246
+ tzinfo (1.2.7)
260
247
  thread_safe (~> 0.1)
261
248
  vegas (0.1.11)
262
249
  rack (>= 1.0.0)
@@ -288,7 +275,6 @@ DEPENDENCIES
288
275
  codeclimate-test-reporter (~> 0.6.0)
289
276
  daemons (= 1.2.4)
290
277
  falcon (~> 0.35)
291
- geminabox (~> 0.13.11)
292
278
  gli (~> 2.16.1)
293
279
  hiredis (~> 0.6.1)
294
280
  license_finder (~> 5)
@@ -35,14 +35,14 @@ GIT
35
35
  PATH
36
36
  remote: .
37
37
  specs:
38
- apisonator (2.100.2)
38
+ apisonator (2.101.0)
39
39
 
40
40
  GEM
41
41
  remote: https://rubygems.org/
42
42
  specs:
43
- activesupport (5.1.4)
43
+ activesupport (5.2.4.3)
44
44
  concurrent-ruby (~> 1.0, >= 1.0.2)
45
- i18n (~> 0.7)
45
+ i18n (>= 0.7, < 2)
46
46
  minitest (~> 5.1)
47
47
  tzinfo (~> 1.1)
48
48
  async (1.24.2)
@@ -85,7 +85,7 @@ GEM
85
85
  codeclimate-test-reporter (0.6.0)
86
86
  simplecov (>= 0.7.1, < 1.0.0)
87
87
  coderay (1.1.2)
88
- concurrent-ruby (1.0.5)
88
+ concurrent-ruby (1.1.6)
89
89
  console (1.8.2)
90
90
  daemons (1.2.4)
91
91
  diff-lcs (1.3)
@@ -102,20 +102,10 @@ GEM
102
102
  process-metrics (~> 0.1.0)
103
103
  rack (>= 1.0)
104
104
  samovar (~> 2.1)
105
- faraday (0.13.1)
106
- multipart-post (>= 1.2, < 3)
107
105
  ffi (1.12.2)
108
- geminabox (0.13.11)
109
- builder
110
- faraday
111
- httpclient (>= 2.2.7)
112
- nesty
113
- reentrant_flock
114
- sinatra (>= 1.2.7)
115
106
  gli (2.16.1)
116
107
  hiredis (0.6.3)
117
- httpclient (2.8.3)
118
- i18n (0.9.1)
108
+ i18n (1.8.2)
119
109
  concurrent-ruby (~> 1.0)
120
110
  json (2.1.0)
121
111
  license_finder (5.9.2)
@@ -130,15 +120,13 @@ GEM
130
120
  metaclass (0.0.4)
131
121
  method_source (0.9.0)
132
122
  mini_portile2 (2.4.0)
133
- minitest (5.10.3)
123
+ minitest (5.14.1)
134
124
  mocha (1.3.0)
135
125
  metaclass (~> 0.0.1)
136
126
  mono_logger (1.1.0)
137
127
  multi_json (1.13.1)
138
- multipart-post (2.0.0)
139
128
  mustache (1.0.5)
140
129
  mustermann (1.0.2)
141
- nesty (1.0.2)
142
130
  net-scp (1.2.1)
143
131
  net-ssh (>= 2.6.5)
144
132
  net-ssh (4.2.0)
@@ -179,7 +167,6 @@ GEM
179
167
  rake (13.0.1)
180
168
  redis-namespace (1.6.0)
181
169
  redis (>= 3.0.4)
182
- reentrant_flock (0.1.1)
183
170
  resque_spec (0.17.0)
184
171
  resque (>= 1.19.0)
185
172
  rspec-core (>= 3.0.0)
@@ -242,7 +229,7 @@ GEM
242
229
  timers (4.3.0)
243
230
  toml (0.2.0)
244
231
  parslet (~> 1.8.0)
245
- tzinfo (1.2.4)
232
+ tzinfo (1.2.7)
246
233
  thread_safe (~> 0.1)
247
234
  vegas (0.1.11)
248
235
  rack (>= 1.0.0)
@@ -270,7 +257,6 @@ DEPENDENCIES
270
257
  codeclimate-test-reporter (~> 0.6.0)
271
258
  daemons (= 1.2.4)
272
259
  falcon (~> 0.35)
273
- geminabox (~> 0.13.11)
274
260
  gli (~> 2.16.1)
275
261
  hiredis (~> 0.6.1)
276
262
  license_finder (~> 5)
@@ -223,6 +223,24 @@ module ThreeScale
223
223
  @usage_limits ||= UsageLimit.load_all(service_id, plan_id)
224
224
  end
225
225
 
226
+ def load_all_usage_limits
227
+ @usage_limits = UsageLimit.load_all(service_id, plan_id)
228
+ end
229
+
230
+ # Loads the usage limits affected by the metrics received, that is, the
231
+ # limits that are defined for those metrics plus all their ancestors in
232
+ # the metrics hierarchy.
233
+ def load_usage_limits_affected_by(metric_names)
234
+ metric_ids = metric_names.flat_map do |name|
235
+ [name] + Metric.ascendants(service_id, name)
236
+ end.uniq.map do |name|
237
+ Metric.load_id(service_id, name)
238
+ end
239
+
240
+ # IDs are sorted to be able to use the memoizer
241
+ @usage_limits = UsageLimit.load_for_affecting_metrics(service_id, plan_id, metric_ids.sort)
242
+ end
243
+
226
244
  def active?
227
245
  state == :active
228
246
  end
@@ -46,9 +46,9 @@ module ThreeScale
46
46
 
47
47
  # Add configuration sections
48
48
  config.add_section(:queues, :master_name, :sentinels, :role,
49
- :connect_timeout, :read_timeout, :write_timeout)
49
+ :connect_timeout, :read_timeout, :write_timeout, :max_connections)
50
50
  config.add_section(:redis, :url, :proxy, :sentinels, :role,
51
- :connect_timeout, :read_timeout, :write_timeout,
51
+ :connect_timeout, :read_timeout, :write_timeout, :max_connections,
52
52
  :async)
53
53
  config.add_section(:analytics_redis, :server,
54
54
  :connect_timeout, :read_timeout, :write_timeout)
@@ -604,10 +604,6 @@ module ThreeScale
604
604
  end
605
605
  end
606
606
 
607
- def application
608
- @application ||= Application.load_by_id_or_user_key!(service_id, params[:app_id], params[:user_key])
609
- end
610
-
611
607
  def service_id
612
608
  if params[:service_id].nil? || params[:service_id].empty?
613
609
  @service_id ||= Service.default_id!(params[:provider_key])
@@ -75,10 +75,7 @@ module ThreeScale
75
75
  end
76
76
 
77
77
  def load_metric_id(name)
78
- Memoizer.memoize_block(Memoizer.build_key(self,
79
- :load_metric_id, @service_id, name)) do
80
- storage.get(encode_key("metric/service_id:#{@service_id}/name:#{name}/id"))
81
- end || raise(MetricInvalid.new(name))
78
+ Metric.load_id(@service_id, name) || raise(MetricInvalid.new(name))
82
79
  end
83
80
 
84
81
  ## accepts postive integers or positive integers preffixed with # (for sets)
@@ -46,7 +46,9 @@ module ThreeScale
46
46
  port ||= DEFAULT_PORT
47
47
 
48
48
  endpoint = Async::IO::Endpoint.tcp(host, port)
49
- @redis_async = Async::Redis::Client.new(endpoint)
49
+ @redis_async = Async::Redis::Client.new(
50
+ endpoint, connection_limit: opts[:max_connections]
51
+ )
50
52
  @building_pipeline = false
51
53
  end
52
54
 
@@ -52,13 +52,18 @@ module ThreeScale
52
52
  # duplicated commands because of this setting.
53
53
  reconnect_attempts: 1,
54
54
  # use by default the C extension client
55
- driver: :hiredis
55
+ driver: :hiredis,
56
+ # applies only to async mode. The sync library opens 1 connection
57
+ # per process.
58
+ max_connections: 10,
56
59
  }.freeze
57
60
  private_constant :CONN_OPTIONS
58
61
 
59
62
  # CONN_WHITELIST - Connection options that can be specified in config
60
63
  # Note: we don't expose reconnect_attempts until the bug above is fixed
61
- CONN_WHITELIST = [:connect_timeout, :read_timeout, :write_timeout].freeze
64
+ CONN_WHITELIST = [
65
+ :connect_timeout, :read_timeout, :write_timeout, :max_connections
66
+ ].freeze
62
67
  private_constant :CONN_WHITELIST
63
68
 
64
69
  # Parameters regarding target server we will take from a config object
@@ -87,9 +87,13 @@ module ThreeScale
87
87
  application = Application.load_by_id_or_user_key!(service_id,
88
88
  app_id,
89
89
  params[:user_key])
90
+
91
+ extensions = request_info && request_info[:extensions] || {}
92
+
93
+ preload_usage_limits(application, extensions[:no_body], params[:usage])
94
+
90
95
  now = Time.now.getutc
91
96
  usage_values = Usage.application_usage(application, now)
92
- extensions = request_info && request_info[:extensions] || {}
93
97
  status_attrs = {
94
98
  service_id: service_id,
95
99
  application: application,
@@ -169,6 +173,27 @@ module ThreeScale
169
173
  Resque.enqueue(ReportJob, service_id, data, Time.now.getutc.to_f, context_info)
170
174
  end
171
175
 
176
+ # Loads the usage limits that are needed to authorize the current request.
177
+ # These are the cases:
178
+ # - When no_body is enabled, we only need to load the limits related with
179
+ # the metrics included in the request, that is, the ones included plus all
180
+ # their ancestors in the hierarchy. That's all we need to verify if the
181
+ # request is within the limits defined.
182
+ # - When no_body is disabled, we need to load all the limits because they
183
+ # are needed to generate the XML response.
184
+ # - When the usage reported in the request is empty, apisonator returns
185
+ # "limits_exceeded" if any of the limits defined has been violated. That's
186
+ # why in that scenario we need to load all the limits.
187
+ def preload_usage_limits(application, no_body_enabled, usage_in_params)
188
+ metric_names_in_usage = usage_in_params&.keys || {}
189
+
190
+ if no_body_enabled && !metric_names_in_usage.empty?
191
+ application.load_usage_limits_affected_by(metric_names_in_usage)
192
+ else
193
+ application.load_all_usage_limits
194
+ end
195
+ end
196
+
172
197
  def storage
173
198
  Storage.instance
174
199
  end
@@ -80,11 +80,6 @@ module ThreeScale
80
80
  values && values[usage_limit.metric_id] || 0
81
81
  end
82
82
 
83
- def value_for_application_usage_limit(usage_limit)
84
- values = @values[usage_limit.period]
85
- values && values[usage_limit.metric_id] || 0
86
- end
87
-
88
83
  # provides a hierarchy hash with metrics as symbolic names
89
84
  def hierarchy
90
85
  @hierarchy ||= Metric.hierarchy service_id
@@ -22,20 +22,15 @@ module ThreeScale
22
22
 
23
23
  def load_all(service_id, plan_id)
24
24
  metric_ids = Metric.load_all_ids(service_id)
25
- return metric_ids if metric_ids.empty?
26
-
27
- results = []
28
- with_pairs_and_values service_id, plan_id, metric_ids do |pair, value|
29
- value and results << new(service_id: service_id,
30
- plan_id: plan_id,
31
- metric_id: pair[0],
32
- period: pair[1],
33
- value: value.to_i)
34
- end
35
- results
25
+ generate_for_metrics(service_id, plan_id, metric_ids)
36
26
  end
37
27
  memoize :load_all
38
28
 
29
+ def load_for_affecting_metrics(service_id, plan_id, metric_ids)
30
+ generate_for_metrics(service_id, plan_id, metric_ids)
31
+ end
32
+ memoize :load_for_affecting_metrics
33
+
39
34
  def load_value(service_id, plan_id, metric_id, period)
40
35
  raw_value = storage.get(key(service_id, plan_id, metric_id, period))
41
36
  raw_value and raw_value.to_i
@@ -80,6 +75,20 @@ module ThreeScale
80
75
  encode_key(key_pre + period.to_s)
81
76
  end
82
77
 
78
+ def generate_for_metrics(service_id, plan_id, metric_ids)
79
+ return metric_ids if metric_ids.empty?
80
+
81
+ results = []
82
+ with_pairs_and_values service_id, plan_id, metric_ids do |pair, value|
83
+ value and results << new(service_id: service_id,
84
+ plan_id: plan_id,
85
+ metric_id: pair[0],
86
+ period: pair[1],
87
+ value: value.to_i)
88
+ end
89
+ results
90
+ end
91
+
83
92
  # yields [pair(metric_id, period), value]
84
93
  def with_pairs_and_values(service_id, plan_id, metric_ids, &blk)
85
94
  pairs, values = get_pairs_and_values_for service_id, plan_id, metric_ids
@@ -1,5 +1,5 @@
1
1
  module ThreeScale
2
2
  module Backend
3
- VERSION = '2.100.2'
3
+ VERSION = '2.101.0'
4
4
  end
5
5
  end
@@ -3,7 +3,7 @@
3
3
  <dependencies>
4
4
  <dependency>
5
5
  <packageName>activesupport</packageName>
6
- <version>5.1.4</version>
6
+ <version>5.2.4.3</version>
7
7
  <licenses>
8
8
  <license>
9
9
  <name>MIT</name>
@@ -23,7 +23,7 @@
23
23
  </dependency>
24
24
  <dependency>
25
25
  <packageName>apisonator</packageName>
26
- <version>2.100.2</version>
26
+ <version>2.101.0</version>
27
27
  <licenses>
28
28
  <license>
29
29
  <name>Apache 2.0</name>
@@ -243,7 +243,7 @@
243
243
  </dependency>
244
244
  <dependency>
245
245
  <packageName>concurrent-ruby</packageName>
246
- <version>1.0.5</version>
246
+ <version>1.1.6</version>
247
247
  <licenses>
248
248
  <license>
249
249
  <name>MIT</name>
@@ -318,16 +318,6 @@
318
318
  <url>http://opensource.org/licenses/mit-license</url>
319
319
  </license>
320
320
  </licenses>
321
- </dependency>
322
- <dependency>
323
- <packageName>faraday</packageName>
324
- <version>0.13.1</version>
325
- <licenses>
326
- <license>
327
- <name>MIT</name>
328
- <url>http://opensource.org/licenses/mit-license</url>
329
- </license>
330
- </licenses>
331
321
  </dependency>
332
322
  <dependency>
333
323
  <packageName>ffi</packageName>
@@ -338,16 +328,6 @@
338
328
  <url>http://opensource.org/licenses/BSD-3-Clause</url>
339
329
  </license>
340
330
  </licenses>
341
- </dependency>
342
- <dependency>
343
- <packageName>geminabox</packageName>
344
- <version>0.13.11</version>
345
- <licenses>
346
- <license>
347
- <name>MIT-LICENSE</name>
348
- <url></url>
349
- </license>
350
- </licenses>
351
331
  </dependency>
352
332
  <dependency>
353
333
  <packageName>gli</packageName>
@@ -368,20 +348,10 @@
368
348
  <url>http://opensource.org/licenses/BSD-3-Clause</url>
369
349
  </license>
370
350
  </licenses>
371
- </dependency>
372
- <dependency>
373
- <packageName>httpclient</packageName>
374
- <version>2.8.3</version>
375
- <licenses>
376
- <license>
377
- <name>ruby</name>
378
- <url>http://www.ruby-lang.org/en/LICENSE.txt</url>
379
- </license>
380
- </licenses>
381
351
  </dependency>
382
352
  <dependency>
383
353
  <packageName>i18n</packageName>
384
- <version>0.9.1</version>
354
+ <version>1.8.2</version>
385
355
  <licenses>
386
356
  <license>
387
357
  <name>MIT</name>
@@ -471,7 +441,7 @@
471
441
  </dependency>
472
442
  <dependency>
473
443
  <packageName>minitest</packageName>
474
- <version>5.10.3</version>
444
+ <version>5.14.1</version>
475
445
  <licenses>
476
446
  <license>
477
447
  <name>MIT</name>
@@ -512,16 +482,6 @@
512
482
  <url>http://opensource.org/licenses/mit-license</url>
513
483
  </license>
514
484
  </licenses>
515
- </dependency>
516
- <dependency>
517
- <packageName>multipart-post</packageName>
518
- <version>2.0.0</version>
519
- <licenses>
520
- <license>
521
- <name>MIT</name>
522
- <url>http://opensource.org/licenses/mit-license</url>
523
- </license>
524
- </licenses>
525
485
  </dependency>
526
486
  <dependency>
527
487
  <packageName>mustache</packageName>
@@ -542,16 +502,6 @@
542
502
  <url>http://opensource.org/licenses/mit-license</url>
543
503
  </license>
544
504
  </licenses>
545
- </dependency>
546
- <dependency>
547
- <packageName>nesty</packageName>
548
- <version>1.0.2</version>
549
- <licenses>
550
- <license>
551
- <name>MIT</name>
552
- <url>http://opensource.org/licenses/mit-license</url>
553
- </license>
554
- </licenses>
555
505
  </dependency>
556
506
  <dependency>
557
507
  <packageName>net-scp</packageName>
@@ -826,16 +776,6 @@
826
776
  <url>http://opensource.org/licenses/mit-license</url>
827
777
  </license>
828
778
  </licenses>
829
- </dependency>
830
- <dependency>
831
- <packageName>reentrant_flock</packageName>
832
- <version>0.1.1</version>
833
- <licenses>
834
- <license>
835
- <name>MIT</name>
836
- <url>http://opensource.org/licenses/mit-license</url>
837
- </license>
838
- </licenses>
839
779
  </dependency>
840
780
  <dependency>
841
781
  <packageName>resque</packageName>
@@ -1123,7 +1063,7 @@
1123
1063
  </dependency>
1124
1064
  <dependency>
1125
1065
  <packageName>tzinfo</packageName>
1126
- <version>1.2.4</version>
1066
+ <version>1.2.7</version>
1127
1067
  <licenses>
1128
1068
  <license>
1129
1069
  <name>MIT</name>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apisonator
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.100.2
4
+ version: 2.101.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Ciganek
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2020-05-08 00:00:00.000000000 Z
19
+ date: 2020-06-04 00:00:00.000000000 Z
20
20
  dependencies: []
21
21
  description: This gem provides a daemon that handles authorization and reporting of
22
22
  web services managed by 3scale.