nats-pure 2.4.0 → 2.5.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 +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +10 -3
- data/lib/nats/client.rb +7 -3
- data/lib/nats/io/client.rb +303 -280
- data/lib/nats/io/errors.rb +2 -0
- data/lib/nats/io/jetstream/api.rb +53 -50
- data/lib/nats/io/jetstream/errors.rb +30 -14
- data/lib/nats/io/jetstream/js/config.rb +9 -3
- data/lib/nats/io/jetstream/js/header.rb +15 -9
- data/lib/nats/io/jetstream/js/status.rb +11 -5
- data/lib/nats/io/jetstream/js/sub.rb +4 -2
- data/lib/nats/io/jetstream/js.rb +10 -8
- data/lib/nats/io/jetstream/manager.rb +103 -101
- data/lib/nats/io/jetstream/msg/ack.rb +15 -9
- data/lib/nats/io/jetstream/msg/ack_methods.rb +24 -22
- data/lib/nats/io/jetstream/msg/metadata.rb +9 -7
- data/lib/nats/io/jetstream/msg.rb +11 -4
- data/lib/nats/io/jetstream/pull_subscription.rb +21 -10
- data/lib/nats/io/jetstream/push_subscription.rb +3 -1
- data/lib/nats/io/jetstream.rb +102 -106
- data/lib/nats/io/kv/api.rb +7 -3
- data/lib/nats/io/kv/bucket_status.rb +7 -5
- data/lib/nats/io/kv/errors.rb +25 -2
- data/lib/nats/io/kv/manager.rb +19 -10
- data/lib/nats/io/kv.rb +359 -22
- data/lib/nats/io/msg.rb +19 -19
- data/lib/nats/io/parser.rb +23 -23
- data/lib/nats/io/rails.rb +2 -0
- data/lib/nats/io/subscription.rb +25 -22
- data/lib/nats/io/version.rb +4 -2
- data/lib/nats/io/websocket.rb +10 -8
- data/lib/nats/nuid.rb +33 -22
- data/lib/nats/service/callbacks.rb +22 -0
- data/lib/nats/service/endpoint.rb +155 -0
- data/lib/nats/service/errors.rb +44 -0
- data/lib/nats/service/group.rb +37 -0
- data/lib/nats/service/monitoring.rb +108 -0
- data/lib/nats/service/stats.rb +52 -0
- data/lib/nats/service/status.rb +66 -0
- data/lib/nats/service/validator.rb +31 -0
- data/lib/nats/service.rb +121 -0
- data/lib/nats/utils/list.rb +26 -0
- data/lib/nats-pure.rb +5 -0
- data/lib/nats.rb +10 -6
- metadata +176 -5
data/lib/nats/io/jetstream.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -11,17 +13,14 @@
|
|
11
13
|
# See the License for the specific language governing permissions and
|
12
14
|
# limitations under the License.
|
13
15
|
#
|
14
|
-
require_relative
|
15
|
-
require_relative
|
16
|
-
require_relative
|
17
|
-
require_relative
|
18
|
-
require_relative
|
19
|
-
require_relative
|
20
|
-
require_relative
|
21
|
-
require_relative
|
22
|
-
require_relative 'jetstream/msg'
|
23
|
-
require_relative 'jetstream/pull_subscription'
|
24
|
-
require_relative 'jetstream/push_subscription'
|
16
|
+
require_relative "kv"
|
17
|
+
require_relative "jetstream/api"
|
18
|
+
require_relative "jetstream/errors"
|
19
|
+
require_relative "jetstream/js"
|
20
|
+
require_relative "jetstream/manager"
|
21
|
+
require_relative "jetstream/msg"
|
22
|
+
require_relative "jetstream/pull_subscription"
|
23
|
+
require_relative "jetstream/push_subscription"
|
25
24
|
|
26
25
|
module NATS
|
27
26
|
# JetStream returns a context with a similar API as the NATS::Client
|
@@ -33,6 +32,8 @@ module NATS
|
|
33
32
|
# js = nc.jetstream()
|
34
33
|
#
|
35
34
|
class JetStream
|
35
|
+
attr_reader :opts, :prefix, :nc
|
36
|
+
|
36
37
|
# Create a new JetStream context for a NATS connection.
|
37
38
|
#
|
38
39
|
# @param conn [NATS::Client]
|
@@ -40,15 +41,15 @@ module NATS
|
|
40
41
|
# @option params [String] :prefix JetStream API prefix to use for the requests.
|
41
42
|
# @option params [String] :domain JetStream Domain to use for the requests.
|
42
43
|
# @option params [Float] :timeout Default timeout to use for JS requests.
|
43
|
-
def initialize(conn, params={})
|
44
|
+
def initialize(conn, params = {})
|
44
45
|
@nc = conn
|
45
46
|
@prefix = if params[:prefix]
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
params[:prefix]
|
48
|
+
elsif params[:domain]
|
49
|
+
"$JS.#{params[:domain]}.API"
|
50
|
+
else
|
51
|
+
JS::DefaultAPIPrefix
|
52
|
+
end
|
52
53
|
@opts = params
|
53
54
|
@opts[:timeout] ||= 5 # seconds
|
54
55
|
params[:prefix] = @prefix
|
@@ -80,7 +81,7 @@ module NATS
|
|
80
81
|
# @option params [String] :stream Expected Stream to which the message is being published.
|
81
82
|
# @raise [NATS::Timeout] When it takes too long to receive an ack response.
|
82
83
|
# @return [PubAck] The pub ack response.
|
83
|
-
def publish(subject, payload="", **params)
|
84
|
+
def publish(subject, payload = "", **params)
|
84
85
|
params[:timeout] ||= @opts[:timeout]
|
85
86
|
if params[:stream]
|
86
87
|
params[:header] ||= {}
|
@@ -89,8 +90,8 @@ module NATS
|
|
89
90
|
|
90
91
|
# Send message with headers.
|
91
92
|
msg = NATS::Msg.new(subject: subject,
|
92
|
-
|
93
|
-
|
93
|
+
data: payload,
|
94
|
+
header: params[:header])
|
94
95
|
|
95
96
|
begin
|
96
97
|
resp = @nc.request_msg(msg, **params)
|
@@ -113,53 +114,49 @@ module NATS
|
|
113
114
|
# @option params [String] :durable Consumer durable name from where the messages will be fetched.
|
114
115
|
# @option params [Hash] :config Configuration for the consumer.
|
115
116
|
# @return [NATS::JetStream::PushSubscription]
|
116
|
-
def subscribe(subject, params={}, &cb)
|
117
|
+
def subscribe(subject, params = {}, &cb)
|
117
118
|
params[:consumer] ||= params[:durable]
|
118
119
|
params[:consumer] ||= params[:name]
|
119
|
-
multi_filter =
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
120
|
+
multi_filter = if subject.is_a?(Array) && (subject.size == 1)
|
121
|
+
subject = subject.first
|
122
|
+
false
|
123
|
+
elsif subject.is_a?(Array) && (subject.size > 1)
|
124
|
+
true
|
125
|
+
end
|
126
126
|
|
127
|
-
#
|
128
127
|
stream = if params[:stream].nil?
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
end
|
137
|
-
end
|
128
|
+
if multi_filter
|
129
|
+
# Use the first subject to try to find the stream.
|
130
|
+
streams = subject.map do |s|
|
131
|
+
find_stream_name_by_subject(s)
|
132
|
+
rescue NATS::JetStream::Error::NotFound
|
133
|
+
raise NATS::JetStream::Error.new("nats: could not find stream matching filter subject '#{s}'")
|
134
|
+
end
|
138
135
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
136
|
+
# Ensure that the filter subjects are not ambiguous.
|
137
|
+
streams.uniq!
|
138
|
+
if streams.count > 1
|
139
|
+
raise NATS::JetStream::Error.new("nats: multiple streams matched filter subjects: #{streams}")
|
140
|
+
end
|
144
141
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
142
|
+
streams.first
|
143
|
+
else
|
144
|
+
find_stream_name_by_subject(subject)
|
145
|
+
end
|
146
|
+
else
|
147
|
+
params[:stream]
|
148
|
+
end
|
152
149
|
|
153
150
|
queue = params[:queue]
|
154
151
|
durable = params[:durable]
|
155
|
-
|
152
|
+
params[:flow_control]
|
156
153
|
manual_ack = params[:manual_ack]
|
157
154
|
idle_heartbeat = params[:idle_heartbeat]
|
158
155
|
flow_control = params[:flow_control]
|
159
156
|
config = params[:config]
|
160
157
|
|
161
158
|
if queue
|
162
|
-
if durable
|
159
|
+
if durable && (durable != queue)
|
163
160
|
raise NATS::JetStream::Error.new("nats: cannot create queue subscription '#{queue}' to consumer '#{durable}'")
|
164
161
|
else
|
165
162
|
durable = queue
|
@@ -170,7 +167,7 @@ module NATS
|
|
170
167
|
consumer_found = false
|
171
168
|
should_create = false
|
172
169
|
|
173
|
-
if
|
170
|
+
if !durable
|
174
171
|
should_create = true
|
175
172
|
else
|
176
173
|
begin
|
@@ -185,18 +182,16 @@ module NATS
|
|
185
182
|
end
|
186
183
|
|
187
184
|
if consumer_found
|
188
|
-
if
|
185
|
+
if !config.deliver_group
|
189
186
|
if queue
|
190
187
|
raise NATS::JetStream::Error.new("nats: cannot create a queue subscription for a consumer without a deliver group")
|
191
188
|
elsif cinfo.push_bound
|
192
189
|
raise NATS::JetStream::Error.new("nats: consumer is already bound to a subscription")
|
193
190
|
end
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
raise NATS::JetStream::Error.new("nats: cannot create a queue subscription #{queue} for a consumer with a deliver group #{config.deliver_group}")
|
199
|
-
end
|
191
|
+
elsif !queue
|
192
|
+
raise NATS::JetStream::Error.new("nats: cannot create a subscription for a consumer with a deliver group #{config.deliver_group}")
|
193
|
+
elsif queue != config.deliver_group
|
194
|
+
raise NATS::JetStream::Error.new("nats: cannot create a queue subscription #{queue} for a consumer with a deliver group #{config.deliver_group}")
|
200
195
|
end
|
201
196
|
elsif should_create
|
202
197
|
# Auto-create consumer if none found.
|
@@ -209,8 +204,8 @@ module NATS
|
|
209
204
|
raise NATS::JetStream::Error.new("nats: invalid ConsumerConfig")
|
210
205
|
end
|
211
206
|
|
212
|
-
config.durable_name = durable if
|
213
|
-
config.deliver_group = queue if
|
207
|
+
config.durable_name = durable if !config.durable_name
|
208
|
+
config.deliver_group = queue if !config.deliver_group
|
214
209
|
|
215
210
|
# Create inbox for push consumer.
|
216
211
|
deliver = @nc.new_inbox
|
@@ -225,9 +220,8 @@ module NATS
|
|
225
220
|
|
226
221
|
# Heartbeats / FlowControl
|
227
222
|
config.flow_control = flow_control
|
228
|
-
if idle_heartbeat
|
223
|
+
if idle_heartbeat || config.idle_heartbeat
|
229
224
|
idle_heartbeat = config.idle_heartbeat if config.idle_heartbeat
|
230
|
-
idle_heartbeat = idle_heartbeat * ::NATS::NANOSECONDS
|
231
225
|
config.idle_heartbeat = idle_heartbeat
|
232
226
|
end
|
233
227
|
|
@@ -237,11 +231,16 @@ module NATS
|
|
237
231
|
end
|
238
232
|
|
239
233
|
# Enable auto acking for async callbacks unless disabled.
|
240
|
-
|
234
|
+
# In case ack policy is none then we also do not require to ack.
|
235
|
+
if cb && !manual_ack && (config.ack_policy != "none")
|
241
236
|
ocb = cb
|
242
237
|
new_cb = proc do |msg|
|
243
238
|
ocb.call(msg)
|
244
|
-
|
239
|
+
begin
|
240
|
+
msg.ack
|
241
|
+
rescue
|
242
|
+
JetStream::Error::MsgAlreadyAckd
|
243
|
+
end
|
245
244
|
end
|
246
245
|
cb = new_cb
|
247
246
|
end
|
@@ -250,7 +249,7 @@ module NATS
|
|
250
249
|
sub.jsi = JS::Sub.new(
|
251
250
|
js: self,
|
252
251
|
stream: stream,
|
253
|
-
consumer: consumer
|
252
|
+
consumer: consumer
|
254
253
|
)
|
255
254
|
sub
|
256
255
|
end
|
@@ -265,57 +264,54 @@ module NATS
|
|
265
264
|
# @option params [String] :name Name of the Consumer to which the PullSubscription will be bound.
|
266
265
|
# @option params [Hash] :config Configuration for the consumer.
|
267
266
|
# @return [NATS::JetStream::PullSubscription]
|
268
|
-
def pull_subscribe(subject, durable, params={})
|
269
|
-
if (!durable
|
267
|
+
def pull_subscribe(subject, durable, params = {})
|
268
|
+
if (!durable || durable.empty?) && !(params[:consumer] || params[:name])
|
270
269
|
raise JetStream::Error::InvalidDurableName.new("nats: invalid durable name")
|
271
270
|
end
|
272
|
-
multi_filter =
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
end
|
271
|
+
multi_filter = if subject.is_a?(Array) && (subject.size == 1)
|
272
|
+
subject = subject.first
|
273
|
+
false
|
274
|
+
elsif subject.is_a?(Array) && (subject.size > 1)
|
275
|
+
true
|
276
|
+
end
|
279
277
|
|
280
278
|
params[:consumer] ||= durable
|
281
279
|
params[:consumer] ||= params[:name]
|
282
280
|
stream = if params[:stream].nil?
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
end
|
291
|
-
end
|
281
|
+
if multi_filter
|
282
|
+
# Use the first subject to try to find the stream.
|
283
|
+
streams = subject.map do |s|
|
284
|
+
find_stream_name_by_subject(s)
|
285
|
+
rescue NATS::JetStream::Error::NotFound
|
286
|
+
raise NATS::JetStream::Error.new("nats: could not find stream matching filter subject '#{s}'")
|
287
|
+
end
|
292
288
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
289
|
+
# Ensure that the filter subjects are not ambiguous.
|
290
|
+
streams.uniq!
|
291
|
+
if streams.count > 1
|
292
|
+
raise NATS::JetStream::Error.new("nats: multiple streams matched filter subjects: #{streams}")
|
293
|
+
end
|
298
294
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
295
|
+
streams.first
|
296
|
+
else
|
297
|
+
find_stream_name_by_subject(subject)
|
298
|
+
end
|
299
|
+
else
|
300
|
+
params[:stream]
|
301
|
+
end
|
306
302
|
begin
|
307
303
|
consumer_info(stream, params[:consumer])
|
308
304
|
rescue NATS::JetStream::Error::NotFound => e
|
309
305
|
# If attempting to bind, then this is a hard error.
|
310
|
-
raise e if params[:stream]
|
306
|
+
raise e if params[:stream] && !multi_filter
|
311
307
|
|
312
|
-
config = if
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
308
|
+
config = if !(params[:config])
|
309
|
+
JetStream::API::ConsumerConfig.new
|
310
|
+
elsif params[:config].is_a?(JetStream::API::ConsumerConfig)
|
311
|
+
params[:config]
|
312
|
+
else
|
313
|
+
JetStream::API::ConsumerConfig.new(params[:config])
|
314
|
+
end
|
319
315
|
config[:durable_name] = durable
|
320
316
|
config[:ack_policy] ||= JS::Config::AckExplicit
|
321
317
|
if multi_filter
|
data/lib/nats/io/kv/api.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -27,11 +29,13 @@ module NATS
|
|
27
29
|
:placement,
|
28
30
|
:republish,
|
29
31
|
:direct,
|
30
|
-
|
31
|
-
|
32
|
+
:validate_keys,
|
33
|
+
keyword_init: true
|
34
|
+
) do
|
35
|
+
def initialize(opts = {})
|
32
36
|
rem = opts.keys - members
|
33
37
|
opts.delete_if { |k| rem.include?(k) }
|
34
|
-
super
|
38
|
+
super
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -15,23 +17,23 @@
|
|
15
17
|
module NATS
|
16
18
|
class KeyValue
|
17
19
|
class BucketStatus
|
18
|
-
attr_reader :bucket
|
20
|
+
attr_reader :bucket, :stream_info
|
19
21
|
|
20
22
|
def initialize(info, bucket)
|
21
|
-
@
|
23
|
+
@stream_info = info
|
22
24
|
@bucket = bucket
|
23
25
|
end
|
24
26
|
|
25
27
|
def values
|
26
|
-
@
|
28
|
+
@stream_info.state.messages
|
27
29
|
end
|
28
30
|
|
29
31
|
def history
|
30
|
-
@
|
32
|
+
@stream_info.config.max_msgs_per_subject
|
31
33
|
end
|
32
34
|
|
33
35
|
def ttl
|
34
|
-
@
|
36
|
+
@stream_info.config.max_age / ::NATS::NANOSECONDS
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
data/lib/nats/io/kv/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -12,7 +14,7 @@
|
|
12
14
|
# limitations under the License.
|
13
15
|
#
|
14
16
|
|
15
|
-
require_relative
|
17
|
+
require_relative "../errors"
|
16
18
|
|
17
19
|
module NATS
|
18
20
|
class KeyValue
|
@@ -21,7 +23,7 @@ module NATS
|
|
21
23
|
# When a key is not found.
|
22
24
|
class KeyNotFoundError < Error
|
23
25
|
attr_reader :entry, :op
|
24
|
-
def initialize(params={})
|
26
|
+
def initialize(params = {})
|
25
27
|
@entry = params[:entry]
|
26
28
|
@op = params[:op]
|
27
29
|
@message = params[:message]
|
@@ -52,9 +54,30 @@ module NATS
|
|
52
54
|
def initialize(msg)
|
53
55
|
@msg = msg
|
54
56
|
end
|
57
|
+
|
55
58
|
def to_s
|
56
59
|
"nats: #{@msg}"
|
57
60
|
end
|
58
61
|
end
|
62
|
+
|
63
|
+
# When there are no keys.
|
64
|
+
class NoKeysFoundError < Error
|
65
|
+
def to_s
|
66
|
+
"nats: no keys found"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# When history is too large.
|
71
|
+
class KeyHistoryTooLargeError < Error
|
72
|
+
def to_s
|
73
|
+
"nats: history limited to a max of 64"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class InvalidKeyError < Error
|
78
|
+
def to_s
|
79
|
+
"nats: invalid key"
|
80
|
+
end
|
81
|
+
end
|
59
82
|
end
|
60
83
|
end
|
data/lib/nats/io/kv/manager.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2021 The NATS Authors
|
2
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
5
|
# you may not use this file except in compliance with the License.
|
@@ -15,7 +17,7 @@
|
|
15
17
|
module NATS
|
16
18
|
class KeyValue
|
17
19
|
module Manager
|
18
|
-
def key_value(bucket)
|
20
|
+
def key_value(bucket, params = {})
|
19
21
|
stream = "KV_#{bucket}"
|
20
22
|
begin
|
21
23
|
si = stream_info(stream)
|
@@ -31,16 +33,18 @@ module NATS
|
|
31
33
|
stream: stream,
|
32
34
|
pre: "$KV.#{bucket}.",
|
33
35
|
js: self,
|
34
|
-
direct: si.config.allow_direct
|
36
|
+
direct: si.config.allow_direct,
|
37
|
+
validate_keys: params[:validate_keys]
|
35
38
|
)
|
36
39
|
end
|
37
40
|
|
38
41
|
def create_key_value(config)
|
39
|
-
config = if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
config = if !config.is_a?(KeyValue::API::KeyValueConfig)
|
43
|
+
config = {bucket: config} if config.is_a?(String)
|
44
|
+
KeyValue::API::KeyValueConfig.new(config)
|
45
|
+
else
|
46
|
+
config
|
47
|
+
end
|
44
48
|
config.history ||= 1
|
45
49
|
config.replicas ||= 1
|
46
50
|
duplicate_window = 2 * 60 # 2 minutes
|
@@ -51,6 +55,10 @@ module NATS
|
|
51
55
|
config.ttl = config.ttl * ::NATS::NANOSECONDS
|
52
56
|
end
|
53
57
|
|
58
|
+
if config.history > 64
|
59
|
+
raise NATS::KeyValue::KeyHistoryTooLargeError
|
60
|
+
end
|
61
|
+
|
54
62
|
stream = JetStream::API::StreamConfig.new(
|
55
63
|
name: "KV_#{config.bucket}",
|
56
64
|
description: config.description,
|
@@ -68,8 +76,8 @@ module NATS
|
|
68
76
|
max_msgs_per_subject: config.history,
|
69
77
|
num_replicas: config.replicas,
|
70
78
|
storage: config.storage,
|
71
|
-
republish: config.republish
|
72
|
-
|
79
|
+
republish: config.republish
|
80
|
+
)
|
73
81
|
|
74
82
|
si = add_stream(stream)
|
75
83
|
KeyValue.new(
|
@@ -77,7 +85,8 @@ module NATS
|
|
77
85
|
stream: stream.name,
|
78
86
|
pre: "$KV.#{config.bucket}.",
|
79
87
|
js: self,
|
80
|
-
direct: si.config.allow_direct
|
88
|
+
direct: si.config.allow_direct,
|
89
|
+
validate_keys: config.validate_keys
|
81
90
|
)
|
82
91
|
end
|
83
92
|
|