orchestrate 0.6.3 → 0.7.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/README.md +64 -27
- data/lib/orchestrate.rb +6 -1
- data/lib/orchestrate/api.rb +1 -0
- data/lib/orchestrate/api/errors.rb +3 -1
- data/lib/orchestrate/api/helpers.rb +1 -0
- data/lib/orchestrate/api/response.rb +43 -10
- data/lib/orchestrate/application.rb +55 -0
- data/lib/orchestrate/client.rb +5 -24
- data/lib/orchestrate/collection.rb +310 -0
- data/lib/orchestrate/key_value.rb +232 -0
- data/lib/orchestrate/version.rb +2 -1
- data/orchestrate.gemspec +1 -1
- data/test/orchestrate/api/{collections_test.rb → collections_api_test.rb} +1 -1
- data/test/orchestrate/api/exceptions_test.rb +9 -55
- data/test/orchestrate/api/{key_value_test.rb → key_value_api_test.rb} +1 -1
- data/test/orchestrate/application_test.rb +44 -0
- data/test/orchestrate/client_test.rb +19 -17
- data/test/orchestrate/collection_enumeration_test.rb +116 -0
- data/test/orchestrate/collection_kv_accessors_test.rb +145 -0
- data/test/orchestrate/collection_test.rb +63 -0
- data/test/orchestrate/key_value_persistence_test.rb +161 -0
- data/test/orchestrate/key_value_test.rb +116 -0
- data/test/test_helper.rb +134 -8
- metadata +24 -15
@@ -0,0 +1,310 @@
|
|
1
|
+
module Orchestrate
|
2
|
+
# Collections are groupings of KeyValue items. They are analagous to tables in SQL databases.
|
3
|
+
class Collection
|
4
|
+
|
5
|
+
# @return [Orchestrate::Application] The application this collection belongs to.
|
6
|
+
attr_reader :app
|
7
|
+
|
8
|
+
# @return [String] The name of this collection.
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# Instantiate the Collection
|
12
|
+
# @param app [Orchestrate::Client, Orchestrate::Application] The application the Collection belongs to.
|
13
|
+
# @param collection_name [#to_s] The name of the collection.
|
14
|
+
# @return Orchestrate::Collection
|
15
|
+
def initialize(app, collection_name)
|
16
|
+
if app.kind_of? Orchestrate::Client
|
17
|
+
@app = Application.new(app)
|
18
|
+
else
|
19
|
+
@app = app
|
20
|
+
end
|
21
|
+
@name = collection_name.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return a pretty-printed representation of the collection.
|
25
|
+
def to_s
|
26
|
+
"#<Orchestrate::Collection name=#{name} api_key=#{app.api_key[0..7]}...>"
|
27
|
+
end
|
28
|
+
alias :inspect :to_s
|
29
|
+
|
30
|
+
# Equivalent to `String#==`. Compares by name and app's api_key.
|
31
|
+
# @param other [Orchestrate::Collection] the collection to compare against.
|
32
|
+
# @return [true, false]
|
33
|
+
def ==(other)
|
34
|
+
other.kind_of?(Orchestrate::Collection) && \
|
35
|
+
other.app.api_key == app.api_key && \
|
36
|
+
other.name == name
|
37
|
+
end
|
38
|
+
alias :eql? :==
|
39
|
+
|
40
|
+
# Equivalent to `String#<=>`. Compares by name and app's api_key.
|
41
|
+
# @param other [Orchestrate::Collection] the collection to compare against.
|
42
|
+
# @return [nil, -1, 0, 1]
|
43
|
+
def <=>(other)
|
44
|
+
return nil unless other.kind_of?(Orchestrate::Collection)
|
45
|
+
return nil unless other.app.api_key == app.api_key
|
46
|
+
other.name <=> name
|
47
|
+
end
|
48
|
+
|
49
|
+
# @!group Collection api
|
50
|
+
|
51
|
+
# Deletes the collection.
|
52
|
+
# @return Orchestrate::API::Response
|
53
|
+
def destroy!
|
54
|
+
app.client.delete_collection(name)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @!endgroup
|
58
|
+
|
59
|
+
# @!group KeyValue getters, setters
|
60
|
+
|
61
|
+
# [Retrieves a KeyValue item by key](http://orchestrate.io/docs/api/#key/value/get).
|
62
|
+
# @param key_name [#to_s] The key of the item
|
63
|
+
# @return [Orchestrate::KeyValue, nil] The KeyValue item if found, nil if not.
|
64
|
+
def [](key_name)
|
65
|
+
begin
|
66
|
+
KeyValue.load(self, key_name)
|
67
|
+
rescue API::NotFound
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# [Sets a KeyValue item by key](http://orchestrate.io/docs/api/#key/value/put-\(create/update\)).
|
73
|
+
# @param key_name [#to_s] The key of the item.
|
74
|
+
# @param value [#to_json] The value to store at the key.
|
75
|
+
# @return [value] The item provided for 'value'.
|
76
|
+
# @note Ruby will return the value provided to `something=` methods. If you want the KeyValue returned, use #set.
|
77
|
+
# @raise Orchestrate::API::BadRequest the body is not valid JSON.
|
78
|
+
# @see #set
|
79
|
+
def []=(key_name, value)
|
80
|
+
set(key_name, value)
|
81
|
+
end
|
82
|
+
|
83
|
+
# [Sets a KeyValue item by key](http://orchestrate.io/docs/api/#key/value/put-\(create/update\)).
|
84
|
+
# @param key_name [#to_s] The key of the item.
|
85
|
+
# @param value [#to_json] The value to store at the key.
|
86
|
+
# @param condition [nil, false, #to_s] (see Orchestraate::Client#put)
|
87
|
+
# @return [Orchestrate::KeyValue] The new KeyValue item.
|
88
|
+
# @raise Orchestrate::API::BadRequest the body is not valid JSON.
|
89
|
+
# @raise Orchestrate::API::VersionMismatch a String condition was provided, but does not match the ref for the current value.
|
90
|
+
# @raise Orchestrate::API::AlreadyPresent a false condition was provided, but a value already exists for this key
|
91
|
+
# @see #[]=
|
92
|
+
def set(key_name, value, condition=nil)
|
93
|
+
response = app.client.put(name, key_name, value, condition)
|
94
|
+
KeyValue.from_bodyless_response(self, key_name, value, response)
|
95
|
+
end
|
96
|
+
|
97
|
+
# [Creates a KeyValue item with an auto-generated
|
98
|
+
# key](http://orchestrate.io/docs/api/#key/value/post-\(create-&-generate-key\))
|
99
|
+
# @param value [#to_json] The value to store
|
100
|
+
# @return [Orchestrate::KeyValue] The KeyValue created.
|
101
|
+
# @note If the create is considered a success but the client is unable to parse the key
|
102
|
+
# from the location header, an API::ServiceError is raised.
|
103
|
+
def <<(value)
|
104
|
+
response = app.client.post(name, value)
|
105
|
+
match_data = response.location.match(%r{#{name}/([^/]+)})
|
106
|
+
raise API::ServiceError.new(response) unless match_data
|
107
|
+
KeyValue.from_bodyless_response(self, match_data[1], value, response)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Creates a KeyValue item in the collection.
|
111
|
+
# @overload create(value)
|
112
|
+
# (see #<<)
|
113
|
+
# [Creates a KeyValue item with an auto-generated
|
114
|
+
# key](http://orchestrate.io/docs/api/#key/value/post-\(create-&-generate-key\))
|
115
|
+
# @param value [#to_json] The value to store
|
116
|
+
# @return [Orchestrate::KeyValue] The KeyValue created.
|
117
|
+
# @note If the create is considered a success but the client is unable to parse the key
|
118
|
+
# from the location header, an API::ServiceError is raised.
|
119
|
+
# @overload create(key_name, value)
|
120
|
+
# [Creates a KeyValue item by key, if the key doesn't have
|
121
|
+
# a value](http://orchestrate.io/docs/api/#key/value/put-\(create/update\)).
|
122
|
+
# @param key_name [#to_s] The name of the key
|
123
|
+
# @param value [#to_json] The value to store at the key
|
124
|
+
# @return [Orchestrate::KeyValue, nil] The KeyValue if created, false if not
|
125
|
+
def create(key_name_or_value, value=nil)
|
126
|
+
if value.nil? and key_name_or_value.respond_to?(:to_json)
|
127
|
+
self << key_name_or_value
|
128
|
+
else
|
129
|
+
begin
|
130
|
+
set(key_name_or_value, value, false)
|
131
|
+
rescue Orchestrate::API::AlreadyPresent
|
132
|
+
false
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# [Deletes the value for a KeyValue
|
138
|
+
# item](http://orchestrate.io/docs/api/#key/value/delete12).
|
139
|
+
# @param key_name [#to_s] The name of the key
|
140
|
+
# @return [true] If the request suceeds.
|
141
|
+
def delete(key_name)
|
142
|
+
app.client.delete(name, key_name)
|
143
|
+
true
|
144
|
+
end
|
145
|
+
|
146
|
+
# [Purges a KeyValue item and its Ref
|
147
|
+
# history](http://orchestrate.io/docs/api/#key/value/delete12).
|
148
|
+
# @param key_name [#to_s] The name of the key
|
149
|
+
# @return [true] If the request suceeds.
|
150
|
+
def purge(key_name)
|
151
|
+
app.client.purge(name, key_name)
|
152
|
+
true
|
153
|
+
end
|
154
|
+
|
155
|
+
# @!endgroup
|
156
|
+
|
157
|
+
|
158
|
+
include Enumerable
|
159
|
+
# @!group KeyValue enumerators
|
160
|
+
|
161
|
+
# Iterates over each KeyValue item in the collection. Used as the basis for Enumerable methods.
|
162
|
+
# Items are provided in lexicographically sorted order by key name.
|
163
|
+
# @yieldparam [Orchestrate::KeyValue] key_value The KeyValue item
|
164
|
+
# @see KeyValueList#each
|
165
|
+
# @example
|
166
|
+
# keys = collection.take(20).map(&:key)
|
167
|
+
# # returns the first 20 keys in the collection.
|
168
|
+
def each(&block)
|
169
|
+
return enum_for(:each) unless block
|
170
|
+
KeyValueList.new(self).each(&block)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Sets the inclusive start key for enumeration over the KeyValue items in the collection.
|
174
|
+
# @see KeyValueList#start
|
175
|
+
# @return [KeyValueList]
|
176
|
+
def start(start_key)
|
177
|
+
KeyValueList.new(self).start(start_key)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Sets the exclusive start key for enumeration over the KeyValue items in the collection.
|
181
|
+
# @see KeyValueList#after
|
182
|
+
# @return [KeyValueList]
|
183
|
+
def after(start_key)
|
184
|
+
KeyValueList.new(self).after(start_key)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Sets the exclusive end key for enumeration over the KeyValue items in the collection.
|
188
|
+
# @see KeyValueList#before
|
189
|
+
# @return [KeyValueList]
|
190
|
+
def before(end_key)
|
191
|
+
KeyValueList.new(self).before(end_key)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Sets the inclusive end key for enumeration over the KeyValue items in the collection.
|
195
|
+
# @see KeyValueList#end
|
196
|
+
# @return [KeyValueList]
|
197
|
+
def end(end_key)
|
198
|
+
KeyValueList.new(self).end(end_key)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns the first n items. Equivalent to Enumerable#take. Sets the
|
202
|
+
# `limit` parameter on the query to Orchestrate, so we don't ask for more than is needed.
|
203
|
+
# @param count [Integer] The number of items to limit to.
|
204
|
+
# @return [Array]
|
205
|
+
def take(count)
|
206
|
+
KeyValueList.new(self).take(count)
|
207
|
+
end
|
208
|
+
|
209
|
+
# @!endgroup
|
210
|
+
|
211
|
+
# An enumerator with boundaries for performing a [KeyValue List
|
212
|
+
# query](http://orchestrate.io/docs/api/#key/value/list) against a collection.
|
213
|
+
class KeyValueList
|
214
|
+
# @return [Collection] The collection which this KeyValueList enumerates over.
|
215
|
+
attr_reader :collection
|
216
|
+
|
217
|
+
# @return [Hash] parameters for setting the boundaries of the enumeration.
|
218
|
+
attr_reader :range
|
219
|
+
|
220
|
+
# Instantiate a new KeyValueList to enumerate over a collection
|
221
|
+
# @param collection [Collection] the collection to enumerate over.
|
222
|
+
# @param range [Hash] parameters for setting the boundaries of the enumeration.
|
223
|
+
# @option range [#to_s] :begin The beginning of the range.
|
224
|
+
# @option range [true, false] :begin_inclusive Whether the begin key is inclusive or not.
|
225
|
+
# @option range [#to_s] :end The end of the range.
|
226
|
+
# @option range [true, false] :end_inclusive Whether the end key is inclusive or not.
|
227
|
+
# @return KeyValueList
|
228
|
+
def initialize(collection, range={})
|
229
|
+
@collection = collection
|
230
|
+
@range = range
|
231
|
+
range[:limit] ||= 100
|
232
|
+
end
|
233
|
+
|
234
|
+
# Sets the inclusive start key for enumeration over the KeyValue items in the collection.
|
235
|
+
# Overwrites any value given to #after.
|
236
|
+
# @param start_key [#to_s] The inclusive start of the key range.
|
237
|
+
# @return [KeyValueList] A new KeyValueList with the new range.
|
238
|
+
def start(start_key)
|
239
|
+
self.class.new(collection, range.merge({begin: start_key, begin_inclusive: true}))
|
240
|
+
end
|
241
|
+
|
242
|
+
# Sets the exclusive start key for enumeration over the KeyValue items in the collection.
|
243
|
+
# Overwrites any value given to #start.
|
244
|
+
# @param start_key [#to_s] The exclusive start of the key range.
|
245
|
+
# @return [KeyValueList] A new KeyValueList with the new range.
|
246
|
+
def after(start_key)
|
247
|
+
self.class.new(collection, range.merge({begin: start_key, begin_inclusive: false}))
|
248
|
+
end
|
249
|
+
|
250
|
+
# Sets the exclusive end key for enumeration over the KeyValue items in the collection.
|
251
|
+
# Overwrites any value given to #end.
|
252
|
+
# @param end_key [#to_s] The exclusive end of the key range.
|
253
|
+
# @return [KeyValueList] A new KeyValueList with the new range.
|
254
|
+
def before(end_key)
|
255
|
+
self.class.new(collection, range.merge({end: end_key, end_inclusive: false}))
|
256
|
+
end
|
257
|
+
|
258
|
+
# Sets the inclusive end key for enumeration over the KeyValue items in the collection.
|
259
|
+
# Overwrites any value given to #before.
|
260
|
+
# @param end_key [#to_s] The inclusive end of the key range.
|
261
|
+
# @return [KeyValueList] A new KeyValueList with the new range.
|
262
|
+
def end(end_key)
|
263
|
+
self.class.new(collection, range.merge({end: end_key, end_inclusive: true}))
|
264
|
+
end
|
265
|
+
|
266
|
+
include Enumerable
|
267
|
+
|
268
|
+
# Lazily iterates over each KeyValue item in the collection. Used as the basis for Enumerable methods.
|
269
|
+
# Items are provided in lexicographically sorted order by key name.
|
270
|
+
# @yieldparam [Orchestrate::KeyValue] key_value The KeyValue item
|
271
|
+
# @example
|
272
|
+
# keys = collection.after(:foo).take(20).map(&:key)
|
273
|
+
# # returns the first 20 keys in the collection that occur after "foo"
|
274
|
+
def each
|
275
|
+
return enum_for(:each) unless block_given?
|
276
|
+
params = {}
|
277
|
+
if range[:begin]
|
278
|
+
begin_key = range[:begin_inclusive] ? :start : :after
|
279
|
+
params[begin_key] = range[:begin]
|
280
|
+
end
|
281
|
+
if range[:end]
|
282
|
+
end_key = range[:end_inclusive] ? :end : :before
|
283
|
+
params[end_key] = range[:end]
|
284
|
+
end
|
285
|
+
params[:limit] = range[:limit]
|
286
|
+
response = collection.app.client.list(collection.name, params)
|
287
|
+
raise ResultsNotReady.new if collection.app.client.http.parallel_manager
|
288
|
+
loop do
|
289
|
+
response.results.each do |doc|
|
290
|
+
yield KeyValue.new(collection, doc, response.request_time)
|
291
|
+
end
|
292
|
+
break unless response.next_link
|
293
|
+
response = response.next_results
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# Returns the first n items. Equivalent to Enumerable#take. Sets the
|
298
|
+
# `limit` parameter on the query to Orchestrate, so we don't ask for more than is needed.
|
299
|
+
# @param count [Integer] The number of items to limit to.
|
300
|
+
# @return [Array]
|
301
|
+
def take(count)
|
302
|
+
count = 1 if count < 1
|
303
|
+
range[:limit] = count > 100 ? 100 : count
|
304
|
+
super(count)
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|
310
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
module Orchestrate
|
2
|
+
# Key/Value pairs are pieces of data identified by a unique key for
|
3
|
+
# a collection and have corresponding value.
|
4
|
+
class KeyValue
|
5
|
+
|
6
|
+
# Instantiates and loads a KeyValue item.
|
7
|
+
# @param collection [Orchestrate::Collection] The collection to which the KeyValue belongs.
|
8
|
+
# @param key [#to_s] The key name.
|
9
|
+
# @return Orchestrate::KeyValue The KeyValue item.
|
10
|
+
# @raise Orchestrate::API::NotFound if there is no value for the provided key.
|
11
|
+
def self.load(collection, key)
|
12
|
+
kv = new(collection, key)
|
13
|
+
kv.reload
|
14
|
+
kv
|
15
|
+
end
|
16
|
+
|
17
|
+
# Instantiate a KeyValue from a PUT or POST request and known value
|
18
|
+
# @param collection [Orchestrate::Collection] The collection to which the KeyValue belongs.
|
19
|
+
# @param key [#to_s] The key name.
|
20
|
+
# @param value [#to_json] The key's value.
|
21
|
+
# @param response [Orchestrate::API::Response] The response that is associated with the PUT/POST.
|
22
|
+
# @return Orchestrate::KeyValue The KeyValue item.
|
23
|
+
def self.from_bodyless_response(collection, key, value, response)
|
24
|
+
kv = new(collection, key, response)
|
25
|
+
kv.value = value
|
26
|
+
kv
|
27
|
+
end
|
28
|
+
|
29
|
+
# The collection this KeyValue belongs to.
|
30
|
+
# @return [Orchestrate::Collection]
|
31
|
+
attr_reader :collection
|
32
|
+
|
33
|
+
# The name of the collection this KeyValue belongs to.
|
34
|
+
# @return [String]
|
35
|
+
attr_reader :collection_name
|
36
|
+
|
37
|
+
# The key for this KeyValue.
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :key
|
40
|
+
|
41
|
+
# For comparison purposes only, the 'address' of this KeyValue item.
|
42
|
+
# Represented as "[collection_name]/[key]"
|
43
|
+
# @return [String]
|
44
|
+
attr_reader :id
|
45
|
+
|
46
|
+
# The ref for the current value for this KeyValue.
|
47
|
+
# @return [String]
|
48
|
+
attr_reader :ref
|
49
|
+
|
50
|
+
# If known, the time at which this ref was created.
|
51
|
+
# @return [Time, nil]
|
52
|
+
attr_reader :reftime
|
53
|
+
|
54
|
+
# The value for the KeyValue at this ref.
|
55
|
+
# @return [#to_json]
|
56
|
+
attr_accessor :value
|
57
|
+
|
58
|
+
# Whether the KeyValue has been loaded from Orchestrate or not.
|
59
|
+
# @return boolean
|
60
|
+
attr_reader :loaded
|
61
|
+
|
62
|
+
# When the KeyValue was last loaded from Orchestrate.
|
63
|
+
# @return [Time]
|
64
|
+
attr_reader :last_request_time
|
65
|
+
|
66
|
+
# Instantiates a new KeyValue item. You generally don't want to call this yourself, but rather use
|
67
|
+
# the methods on Orchestrate::Collection to load a KeyValue.
|
68
|
+
# @param coll [Orchestrate::Collection] The collection to which this KeyValue belongs.
|
69
|
+
# @param key_name_or_listing [Hash] A listing result from Client#list
|
70
|
+
# @param key_name_or_listing [#to_s] The name of the key
|
71
|
+
# @param response_or_request_time [nil, Time, Orchestrate::API::Response]
|
72
|
+
# If key_name_or_listing is a listing, and this value is a Time, used to set last_request_time.
|
73
|
+
# Otherwise if an API::Request, used to load attributes and value.
|
74
|
+
# @return Orchestrate::KeyValue
|
75
|
+
def initialize(coll, key_name_or_listing, response_or_request_time=nil)
|
76
|
+
@collection = coll
|
77
|
+
@collection_name = coll.name
|
78
|
+
@app = coll.app
|
79
|
+
if key_name_or_listing.kind_of?(Hash)
|
80
|
+
path = key_name_or_listing.fetch('path')
|
81
|
+
@key = path.fetch('key')
|
82
|
+
@ref = path.fetch('ref')
|
83
|
+
@reftime = Time.at(key_name_or_listing.fetch('reftime') / 1000.0)
|
84
|
+
@value = key_name_or_listing.fetch('value')
|
85
|
+
@last_request_time = response_or_request_time if response_or_request_time.kind_of?(Time)
|
86
|
+
else
|
87
|
+
@key = key_name_or_listing.to_s
|
88
|
+
end
|
89
|
+
@id = "#{collection_name}/#{key}"
|
90
|
+
load_from_response(response_or_request_time) if response_or_request_time.kind_of?(API::Response)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Equivalent to `String#==`. Compares by key and collection.
|
94
|
+
# @param other [Orchestrate::KeyValue] the KeyValue to compare against.
|
95
|
+
# @return [true, false]
|
96
|
+
def ==(other)
|
97
|
+
other.kind_of?(Orchestrate::KeyValue) && \
|
98
|
+
other.collection == collection && \
|
99
|
+
other.key == key
|
100
|
+
end
|
101
|
+
alias :eql? :==
|
102
|
+
|
103
|
+
# Equivalent to `String#<=>`. Compares by key and collection.
|
104
|
+
# @param other [Orchestrate::KeyValue] the KeyValue to compare against.
|
105
|
+
# @return [nil, -1, 0, 1]
|
106
|
+
def <=>(other)
|
107
|
+
return nil unless other.kind_of?(Orchestrate::KeyValue)
|
108
|
+
return nil unless other.collection == collection
|
109
|
+
other.key <=> key
|
110
|
+
end
|
111
|
+
|
112
|
+
# @return Pretty-Printed string representation of the KeyValue
|
113
|
+
def to_s
|
114
|
+
"#<Orchestrate::KeyValue id=#{id} ref=#{ref} last_request_time=#{last_request_time}>"
|
115
|
+
end
|
116
|
+
alias :inspect :to_s
|
117
|
+
|
118
|
+
# If the KeyValue has been loaded or not.
|
119
|
+
# @return [true, false] loaded
|
120
|
+
def loaded?
|
121
|
+
!! last_request_time
|
122
|
+
end
|
123
|
+
|
124
|
+
# Reload this KeyValue item from Orchestrate.
|
125
|
+
# @raise Orchestrate::API::NotFound if the KeyValue no longer exists.
|
126
|
+
def reload
|
127
|
+
load_from_response(@app.client.get(collection_name, key))
|
128
|
+
end
|
129
|
+
|
130
|
+
# @!group Attribute accessors
|
131
|
+
|
132
|
+
# Get an attribute from the KeyValue item's value.
|
133
|
+
# @param attr_name [#to_s] The name of the attribute.
|
134
|
+
# @return [nil, true, false, Numeric, String, Array, Hash] the value for the attribute.
|
135
|
+
def [](attr_name)
|
136
|
+
value[attr_name.to_s]
|
137
|
+
end
|
138
|
+
|
139
|
+
# Set a value to an attribute on the KeyValue item's value.
|
140
|
+
# @param attr_name [#to_s] The name of the attribute.
|
141
|
+
# @param attr_value [#to_json] The new value for the attribute.
|
142
|
+
# @return [attr_value]
|
143
|
+
def []=(attr_name, attr_value)
|
144
|
+
value[attr_name.to_s] = attr_value
|
145
|
+
end
|
146
|
+
|
147
|
+
# @!endgroup
|
148
|
+
#
|
149
|
+
# @!group Persistence
|
150
|
+
|
151
|
+
# Saves the KeyValue item to Orchestrate using 'If-Match' with the current ref.
|
152
|
+
# Sets the new ref for this value to the ref attribute.
|
153
|
+
# Returns false on failure to save, and rescues from all Orchestrate::API errors.
|
154
|
+
# @return [true, false]
|
155
|
+
def save
|
156
|
+
begin
|
157
|
+
save!
|
158
|
+
rescue API::RequestError, API::ServiceError
|
159
|
+
false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Saves the KeyValue item to Orchestrate using 'If-Match' with the current ref.
|
164
|
+
# Sets the new ref for this value to the ref attribute.
|
165
|
+
# Raises an exception on failure to save.
|
166
|
+
# @return [true]
|
167
|
+
# @raise [Orchestrate::API::VersionMismatch] If the KeyValue item has been updated with a new ref since this KeyValue was loaded.
|
168
|
+
# @raise [Orchestrate::API::RequestError, Orchestrate::API::ServiceError] If there are any other problems with saving.
|
169
|
+
def save!
|
170
|
+
begin
|
171
|
+
load_from_response(@app.client.put(collection_name, key, value, ref))
|
172
|
+
true
|
173
|
+
rescue API::IndexingConflict => e
|
174
|
+
@ref = e.response.headers['Location'].split('/').last
|
175
|
+
@last_request_time = Time.parse(e.response.headers['Date'])
|
176
|
+
true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# Deletes the KeyValue item from Orchestrate using 'If-Match' with the current ref.
|
181
|
+
# Returns false if the item failed to delete because a new ref had been created since this KeyValue was loaded.
|
182
|
+
# @return [true, false]
|
183
|
+
def destroy
|
184
|
+
begin
|
185
|
+
destroy!
|
186
|
+
rescue API::VersionMismatch
|
187
|
+
false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Deletes a KeyValue item from Orchestrate using 'If-Match' with the current ref.
|
192
|
+
# @raise [Orchestrate::API::VersionMismatch] If the KeyValue item has been updated with a new ref since this KeyValue was loaded.
|
193
|
+
def destroy!
|
194
|
+
response = @app.client.delete(collection_name, key, ref)
|
195
|
+
@ref = nil
|
196
|
+
@last_request_time = response.request_time
|
197
|
+
true
|
198
|
+
end
|
199
|
+
|
200
|
+
# Deletes a KeyValue item and its entire Ref history from Orchestrate using 'If-Match' with the current ref.
|
201
|
+
# Returns false if the item failed to delete because a new ref had been created since this KeyValue was loaded.
|
202
|
+
# @return [true, false]
|
203
|
+
def purge
|
204
|
+
begin
|
205
|
+
purge!
|
206
|
+
rescue API::VersionMismatch
|
207
|
+
false
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Deletes a KeyValue item and its entire Ref history from Orchestrate using 'If-Match' with the current ref.
|
212
|
+
# @raise [Orchestrate::API::VersionMismatch] If the KeyValue item has been updated with a new ref since this KeyValue was loaded.
|
213
|
+
def purge!
|
214
|
+
response = @app.client.purge(collection_name, key, ref)
|
215
|
+
@ref = nil
|
216
|
+
@last_request_time = response.request_time
|
217
|
+
true
|
218
|
+
end
|
219
|
+
|
220
|
+
# @!engroup persistence
|
221
|
+
|
222
|
+
private
|
223
|
+
def load_from_response(response)
|
224
|
+
response.on_complete do
|
225
|
+
@ref = response.ref
|
226
|
+
@value = response.body unless response.body.respond_to?(:strip) && response.body.strip.empty?
|
227
|
+
@last_request_time = response.request_time
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|