orchestrate 0.5.1 → 0.6.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/.yardopts +1 -0
- data/README.md +28 -20
- data/lib/orchestrate/api/errors.rb +114 -52
- data/lib/orchestrate/api/helpers.rb +48 -0
- data/lib/orchestrate/api/response.rb +111 -0
- data/lib/orchestrate/api.rb +4 -6
- data/lib/orchestrate/client.rb +290 -302
- data/lib/orchestrate/version.rb +1 -1
- data/lib/orchestrate.rb +0 -37
- data/test/orchestrate/api/collections_test.rb +28 -6
- data/test/orchestrate/api/event_test.rb +85 -20
- data/test/orchestrate/api/exceptions_test.rb +172 -0
- data/test/orchestrate/api/graph_test.rb +4 -0
- data/test/orchestrate/api/key_value_test.rb +52 -7
- data/test/orchestrate/api/response_test.rb +36 -0
- data/test/orchestrate/client_test.rb +15 -16
- data/test/test_helper.rb +4 -9
- metadata +10 -6
- data/lib/orchestrate/configuration.rb +0 -53
- data/lib/orchestrate/helpers.rb +0 -22
- data/test/orchestrate/configuration_test.rb +0 -67
data/lib/orchestrate/client.rb
CHANGED
@@ -3,359 +3,346 @@ require 'faraday_middleware'
|
|
3
3
|
|
4
4
|
module Orchestrate
|
5
5
|
|
6
|
-
# ==== Ruby Client for the Orchestrate REST *API*.
|
7
|
-
#
|
8
|
-
# The primary entry point is the #send_request method, which generates a
|
9
|
-
# Request, and returns the Response to the caller.
|
10
|
-
#
|
11
6
|
class Client
|
12
7
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
8
|
+
# @return [String] The API key provided
|
9
|
+
attr_reader :api_key
|
10
|
+
|
11
|
+
# @return [Faraday::Connection] The Faraday HTTP connection.
|
12
|
+
attr_reader :http
|
13
|
+
|
14
|
+
# @return [Proc] The block used to configure faraday.
|
15
|
+
attr_reader :faraday_configuration
|
16
|
+
|
17
|
+
# Instantiate a new Client for an Orchestrate application.
|
18
|
+
# @param api_key [#to_s] The API Key for your Orchestrate application.
|
19
|
+
# @yieldparam [Faraday::Connection] The setup for the faraday connection.
|
20
|
+
# @return Orchestrate::Client
|
21
|
+
# @todo api_key -> app_url, parse api_key from auth section of url
|
22
|
+
def initialize(api_key, &block)
|
23
|
+
@api_key = api_key
|
24
|
+
@faraday_configuration = block
|
25
|
+
@http = Faraday.new("https://api.orchestrate.io") do |faraday|
|
26
|
+
block = lambda{|f| f.adapter Faraday.default_adapter } unless block
|
27
|
+
block.call faraday
|
33
28
|
|
34
29
|
# faraday seems to want you do specify these twice.
|
35
|
-
faraday.request :basic_auth,
|
36
|
-
faraday.basic_auth
|
30
|
+
faraday.request :basic_auth, api_key, ''
|
31
|
+
faraday.basic_auth api_key, ''
|
37
32
|
|
38
33
|
# parses JSON responses
|
39
34
|
faraday.response :json, :content_type => /\bjson$/
|
40
35
|
end
|
41
36
|
end
|
42
37
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
#
|
49
|
-
# Performes a List query against the given collection. Results are sorted
|
50
|
-
# lexicographically by key name.
|
51
|
-
#
|
52
|
-
# +collection_name+:: A String or Symbol representing the name of the collection.
|
53
|
-
# +parameters+:: a Hash object containing query parameters:
|
54
|
-
# - +:limit+ - integer, number of results to return. Defaults to 10, Max 100.
|
55
|
-
# - +:start+ - string, start key of query range, including value.
|
56
|
-
# - +:after+ - string, start key of query range, excluding value.
|
57
|
-
# - +:before+ - string, end key of query range, excluding value.
|
58
|
-
# - +:end+ - string, end key of query range, including value.
|
59
|
-
#
|
60
|
-
# Note, you cannot provide *both* 'start' and 'after', or 'before' and 'end'
|
61
|
-
#
|
62
|
-
def list(collection, options={})
|
63
|
-
Orchestrate::Helpers.range_keys!('key', options)
|
64
|
-
send_request :get, [collection], { query: options }
|
38
|
+
# Tests authentication with Orchestrate.
|
39
|
+
# @return Orchestrate::API::Response
|
40
|
+
# @raise Orchestrate::API::Unauthorized if the client could not authenticate.
|
41
|
+
def ping
|
42
|
+
send_request :get, []
|
65
43
|
end
|
66
44
|
|
67
|
-
#
|
68
|
-
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
|
79
|
-
|
45
|
+
# @!group Collections
|
46
|
+
|
47
|
+
# [Search the items in
|
48
|
+
# a collection](http://orchestrate.io/docs/api/#search) using a Lucene
|
49
|
+
# Query Syntax.
|
50
|
+
# @param collection [#to_s] The name of the collection
|
51
|
+
# @param query [String] The [Lucene Query String][lucene] to query the collection with.
|
52
|
+
# [lucene]: http://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Overview
|
53
|
+
# @param options [Hash] Parameters for the query
|
54
|
+
# @option options [Integer] :limit (10) The number of results to return. Maximum 100.
|
55
|
+
# @option options [Integer] :offset (0) The starting position of the results.
|
56
|
+
# @return Orchestrate::API::CollectionResponse
|
57
|
+
# @raise Orchestrate::API::InvalidSearchParam The :limit/:offset values are not valid.
|
58
|
+
# @raise Orchestrate::API::SearchQueryMalformed if query isn't a valid Lucene query.
|
59
|
+
def search(collection, query, options={})
|
60
|
+
send_request :get, [collection], { query: options.merge({query: query}),
|
61
|
+
response: API::CollectionResponse }
|
80
62
|
end
|
81
63
|
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
# +collection_name+:: a String or Symbol representing the name of the collection.
|
88
|
-
#
|
64
|
+
# [Deletes an entire collection](http://orchestrate.io/docs/api/#collections/delete)
|
65
|
+
# @param collection [#to_s] The name of the collection
|
66
|
+
# @return Orchestrate::API::Response
|
67
|
+
# @note The Orchestrate API will return succesfully regardless of if the collection exists or not.
|
89
68
|
def delete_collection(collection)
|
90
69
|
send_request :delete, [collection], { query: {force:true} }
|
91
70
|
end
|
92
71
|
|
93
|
-
#
|
94
|
-
#
|
95
|
-
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
72
|
+
# @!endgroup
|
73
|
+
# @!group Key/Value
|
74
|
+
|
75
|
+
# [Retrieves the value assigned to a key](http://orchestrate.io/docs/api/#key/value/get).
|
76
|
+
# If a `ref` parameter is provided, [retrieves a historical value for the
|
77
|
+
# key](http://orchestrate.io/docs/api/#refs/get14)
|
78
|
+
# @param collection [#to_s] The name of the collection.
|
79
|
+
# @param key [#to_s] The name of the key.
|
80
|
+
# @param ref [#to_s] The opaque version identifier of the ref to return, if a historical value is desired.
|
81
|
+
# @return Orchestrate::API::ItemResponse
|
82
|
+
# @raise Orchestrate::API::NotFound If the key or ref doesn't exist.
|
83
|
+
# @raise Orchestrate::API::MalformedRef If the ref provided is not a valid ref.
|
106
84
|
def get(collection, key, ref=nil)
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
send_request :get, [collection, key]
|
111
|
-
end
|
85
|
+
path = [collection, key]
|
86
|
+
path.concat(['refs', ref]) if ref
|
87
|
+
send_request :get, path, { response: API::ItemResponse }
|
112
88
|
end
|
113
89
|
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
90
|
+
# [List historical refs for values of a key](http://orchestrate.io/docs/api/#refs/list15).
|
91
|
+
# Results are time-ordered newest-to-oldest and paginated.
|
92
|
+
# @param collection [#to_s] The name of the collection.
|
93
|
+
# @param key [#to_s] The name of the key.
|
94
|
+
# @param options [Hash] Parameters for the query.
|
95
|
+
# @option options [Integer] :limit (10) The number of results to return. Maximum 100.
|
96
|
+
# @option options [Integer] :offset (0) The starting position of the results.
|
97
|
+
# @option options [true, false] :values (false) Whether to return the value
|
98
|
+
# for each ref. Refs with no content (for example, deleted with `#delete`) will not have
|
99
|
+
# a value, but marked with a `'tombstone' => true` key.
|
100
|
+
# @return Orchestrate::API::CollectionResponse
|
101
|
+
# @raise Orchestrate::API::NotFound If there are no values for the provided key/collection.
|
102
|
+
# @raise Orchestrate::API::InvalidSearchParam The :limit/:offset values are not valid.
|
103
|
+
# @raise Orchestrate::API::MalformedRef If the ref provided is not a valid ref.
|
104
|
+
def list_refs(collection, key, options={})
|
105
|
+
send_request :get, [collection, key, :refs], { query: options, response: API::CollectionResponse }
|
106
|
+
end
|
107
|
+
|
108
|
+
# [Updates the value associated with
|
109
|
+
# a key](http://orchestrate.io/docs/api/#key/value/put-\(create/update\)).
|
110
|
+
# If the key does not currently have a value, will create the value.
|
111
|
+
# @param collection [#to_s] The name of the collection.
|
112
|
+
# @param key [#to_s] The name of the key.
|
113
|
+
# @param body [#to_json] The value for the key.
|
114
|
+
# @param condition [String, false, nil] Conditions for setting the value.
|
115
|
+
# If `String`, value used as `If-Match`, value will only be updated if key's current value's ref matches.
|
116
|
+
# If `false`, uses `If-None-Match` the value will only be set if there is no existent value for the key.
|
117
|
+
# If `nil` (default), value is set regardless.
|
118
|
+
# @return Orchestrate::API::ItemResponse
|
119
|
+
# @raise Orchestrate::API::BadRequest the body is not valid JSON.
|
120
|
+
# @raise Orchestrate::API::IndexingConflict One of the value's keys
|
121
|
+
# contains a value of a different type than the schema that exists for
|
122
|
+
# the collection.
|
123
|
+
# @see Orchestrate::API::IndexingConflict
|
124
|
+
# @raise Orchestrate::API::VersionMismatch A ref was provided, but it does not match the ref for the current value.
|
125
|
+
# @raise Orchestrate::API::AlreadyPresent the `false` condition was given, but a value already exists for this collection/key combo.
|
128
126
|
def put(collection, key, body, condition=nil)
|
129
127
|
headers={}
|
130
128
|
if condition.is_a?(String)
|
131
|
-
headers['If-Match'] = format_ref(condition)
|
129
|
+
headers['If-Match'] = API::Helpers.format_ref(condition)
|
132
130
|
elsif condition == false
|
133
131
|
headers['If-None-Match'] = '*'
|
134
132
|
end
|
135
|
-
send_request :put, [collection, key], { body: body, headers: headers }
|
133
|
+
send_request :put, [collection, key], { body: body, headers: headers, response: API::ItemResponse }
|
136
134
|
end
|
137
135
|
alias :put_if_unmodified :put
|
138
136
|
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
# Will create the value at the specified key only if there is no existing value for the specified key.
|
143
|
-
#
|
137
|
+
# [Creates the value for a key if none
|
138
|
+
# exists](http://orchestrate.io/docs/api/#key/value/put-\(create/update\)).
|
139
|
+
# @see #put
|
144
140
|
def put_if_absent(collection, key, body)
|
145
141
|
put collection, key, body, false
|
146
142
|
end
|
147
143
|
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
# +ref+:: if provided, used as 'If-Match', will only delete the key if the current value is the provided ref.
|
157
|
-
#
|
144
|
+
# [Sets the current value of a key to a null
|
145
|
+
# object](http://orchestrate.io/docs/api/#key/value/delete11).
|
146
|
+
# @param collection [#to_s] The name of the collection.
|
147
|
+
# @param key [#to_s] The name of the key.
|
148
|
+
# @param ref [#to_s] If specified, deletes the ref only if the current value's ref matches.
|
149
|
+
# @return Orchestrate::API::Response
|
150
|
+
# @raise Orchestrate::API::VersionMismatch if the provided ref is not the ref for the current value.
|
151
|
+
# @note previous versions of the values at this key are still available via #list_refs and #get.
|
158
152
|
def delete(collection, key, ref=nil)
|
159
153
|
headers = {}
|
160
|
-
headers['If-Match'] = format_ref(ref) if ref
|
154
|
+
headers['If-Match'] = API::Helpers.format_ref(ref) if ref
|
161
155
|
send_request :delete, [collection, key], { headers: headers }
|
162
156
|
end
|
163
157
|
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
170
|
-
# +key+:: a String or Symbol representing the key for the value.
|
171
|
-
#
|
158
|
+
# [Purges the current value and ref history associated with the
|
159
|
+
# key](http://orchestrate.io/docs/api/#key/value/delete11).
|
160
|
+
# @param collection [#to_s] The name of the collection.
|
161
|
+
# @param key [#to_s] The name of the key.
|
162
|
+
# @return Orchestrate::API::Response
|
163
|
+
# @todo take an optional ref for If-Match
|
172
164
|
def purge(collection, key)
|
173
165
|
send_request :delete, [collection, key], { query: { purge: true } }
|
174
166
|
end
|
175
167
|
|
176
|
-
#
|
177
|
-
#
|
178
|
-
|
179
|
-
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
|
191
|
-
|
192
|
-
|
168
|
+
# [List the KeyValue items in a collection](http://orchestrate.io/docs/api/#key/value/list).
|
169
|
+
# Results are sorted results lexicographically by key name and paginated.
|
170
|
+
# @param collection [#to_s] The name of the collection
|
171
|
+
# @param options [Hash] Parameters for the query
|
172
|
+
# @option options [Integer] :limit (10) The number of results to return. Maximum 100.
|
173
|
+
# @option options [String] :start The inclusive start key of the query range.
|
174
|
+
# @option options [String] :after The exclusive start key of the query range.
|
175
|
+
# @option options [String] :before The exclusive end key of the query range.
|
176
|
+
# @option options [String] :end The inclusive end key of the query range.
|
177
|
+
# @note The Orchestrate API may return an error if you include both the
|
178
|
+
# :start/:after or :before/:end keys. The client will not stop you from doing this.
|
179
|
+
# @note To include all keys in a collection, do not include any :start/:after/:before/:end parameters.
|
180
|
+
# @return Orchestrate::API::CollectionResponse
|
181
|
+
# @raise Orchestrate::API::InvalidSearchParam The :limit value is not valid.
|
182
|
+
def list(collection, options={})
|
183
|
+
API::Helpers.range_keys!('key', options)
|
184
|
+
send_request :get, [collection], { query: options, response: API::CollectionResponse }
|
185
|
+
end
|
186
|
+
|
187
|
+
# @!endgroup
|
188
|
+
# @!group Events
|
189
|
+
|
190
|
+
# [Retrieves an individual event](http://orchestrate.io/docs/api/#events/get19).
|
191
|
+
# @param collection [#to_s] The name of the collection.
|
192
|
+
# @param key [#to_s] The name of the key.
|
193
|
+
# @param event_type [#to_s] The category for the event.
|
194
|
+
# @param timestamp [Time, Date, Integer, String] The timestamp for the event.
|
195
|
+
# If a String, must match the [Timestamp specification](http://orchestrate.io/docs/api/#events/timestamps)
|
196
|
+
# and include the milliseconds portion.
|
197
|
+
# @param ordinal [Integer, #to_s] The ordinal for the event in the given timestamp.
|
198
|
+
# @return Orchestrate::API::ItemResponse
|
199
|
+
# @raise Orchestrate::API::NotFound If the requested event doesn't exist.
|
193
200
|
def get_event(collection, key, event_type, timestamp, ordinal)
|
194
|
-
|
201
|
+
timestamp = API::Helpers.timestamp(timestamp)
|
202
|
+
path = [collection, key, 'events', event_type, timestamp, ordinal]
|
203
|
+
send_request :get, path, { response: API::ItemResponse }
|
195
204
|
end
|
196
205
|
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
# +timestamp+:: an Integer or String representing a time.
|
208
|
-
# - nil - Timestamp value will be created by Orchestrate.
|
209
|
-
# - Integers are Milliseconds since Unix Epoch.
|
210
|
-
# - Strings must be formatted as per http://orchestrate.io/docs/api/#events/timestamps
|
211
|
-
# - A future version will support ruby Time objects.
|
212
|
-
#
|
206
|
+
# [Creates an event](http://orchestrate.io/docs/api/#events/post-\(create\)).
|
207
|
+
# @param collection [#to_s] The name of the collection.
|
208
|
+
# @param key [#to_s] The name of the key.
|
209
|
+
# @param event_type [#to_s] The category for the event.
|
210
|
+
# @param body [#to_json] The value for the event.
|
211
|
+
# @param timestamp [Time, Date, Integer, String, nil] The timestamp for the event.
|
212
|
+
# If omitted, the timestamp is created by Orchestrate.
|
213
|
+
# If a String, must match the [Timestamp specification](http://orchestrate.io/docs/api/#events/timestamps).
|
214
|
+
# @return Orchestrate::API::ItemResponse
|
215
|
+
# @raise Orchestrate::API::BadRequest If the body is not valid JSON.
|
213
216
|
def post_event(collection, key, event_type, body, timestamp=nil)
|
217
|
+
timestamp = API::Helpers.timestamp(timestamp)
|
214
218
|
path = [collection, key, 'events', event_type, timestamp].compact
|
215
|
-
send_request :post, path, { body: body }
|
219
|
+
send_request :post, path, { body: body, response: API::ItemResponse }
|
216
220
|
end
|
217
221
|
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
227
|
-
#
|
228
|
-
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
234
|
-
#
|
235
|
-
# - String - used as 'If-Match'. The event will only update if the event's current value matches this ref.
|
236
|
-
#
|
222
|
+
# [Updates an existing event](http://orchestrate.io/docs/api/#events/put-\(update\)).
|
223
|
+
# @param collection [#to_s] The name of the collection.
|
224
|
+
# @param key [#to_s] The name of the key.
|
225
|
+
# @param event_type [#to_s] The category for the event.
|
226
|
+
# @param timestamp [Time, Date, Integer, String, nil] The timestamp for the event.
|
227
|
+
# If a String, must match the [Timestamp specification](http://orchestrate.io/docs/api/#events/timestamps)
|
228
|
+
# and include the milliseconds portion.
|
229
|
+
# @param ordinal [Integer, #to_s] The ordinal for the event in the given timestamp.
|
230
|
+
# @param body [#to_json] The value for the event.
|
231
|
+
# @param ref [nil, #to_s] If provided, used as `If-Match`, and event will
|
232
|
+
# only update if its current value has the provided ref. If omitted,
|
233
|
+
# updates the event regardless.
|
234
|
+
# @return Orchestrate::API::ItemResponse
|
235
|
+
# @raise Orchestrate::API::NotFound The specified event doesn't exist.
|
236
|
+
# @raise Orchestrate::API::BadRequest If the body is not valid JSON.
|
237
|
+
# @raise Orchestrate::API::VersionMismatch The event's current value has a ref that does not match the provided ref.
|
238
|
+
# @raise Orchestrate::API::MalformedRef If the ref provided is not a valid ref.
|
237
239
|
def put_event(collection, key, event_type, timestamp, ordinal, body, ref=nil)
|
240
|
+
timestamp = API::Helpers.timestamp(timestamp)
|
238
241
|
path = [collection, key, 'events', event_type, timestamp, ordinal]
|
239
242
|
headers = {}
|
240
|
-
headers['If-Match'] = format_ref(ref) if ref
|
241
|
-
send_request :put, path, { body: body, headers: headers }
|
243
|
+
headers['If-Match'] = API::Helpers.format_ref(ref) if ref
|
244
|
+
send_request :put, path, { body: body, headers: headers, response: API::ItemResponse }
|
242
245
|
end
|
243
246
|
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
#
|
249
|
-
#
|
250
|
-
#
|
251
|
-
#
|
252
|
-
#
|
253
|
-
#
|
254
|
-
#
|
255
|
-
#
|
256
|
-
#
|
257
|
-
#
|
258
|
-
# +ref+::
|
259
|
-
# - +nil+ - The event will be deleted regardless.
|
260
|
-
# - String - used as 'If-Match'. The event will only be deleted if the event's current value matches this ref.
|
261
|
-
#
|
247
|
+
# [Deletes an existing event](http://orchestrate.io/docs/api/#events/delete22).
|
248
|
+
# @param collection [#to_s] The name of the collection.
|
249
|
+
# @param key [#to_s] The name of the key.
|
250
|
+
# @param event_type [#to_s] The category for the event.
|
251
|
+
# @param timestamp [Time, Date, Integer, String, nil] The timestamp for the event.
|
252
|
+
# If a String, must match the [Timestamp specification](http://orchestrate.io/docs/api/#events/timestamps)
|
253
|
+
# and include the milliseconds portion.
|
254
|
+
# @param ordinal [Integer, #to_s] The ordinal for the event in the given timestamp.
|
255
|
+
# @param ref [nil, #to_s] If provided, used as `If-Match`, and event will
|
256
|
+
# only update if its current value has the provided ref. If omitted,
|
257
|
+
# updates the event regardless.
|
258
|
+
# @return Orchestrate::API::Response
|
259
|
+
# @raise Orchestrate::API::VersionMismatch The event's current value has a ref that does not match the provided ref.
|
260
|
+
# @raise Orchestrate::API::MalformedRef If the ref provided is not a valid ref.
|
262
261
|
def purge_event(collection, key, event_type, timestamp, ordinal, ref=nil)
|
262
|
+
timestamp = API::Helpers.timestamp(timestamp)
|
263
263
|
path = [collection, key, 'events', event_type, timestamp, ordinal]
|
264
264
|
headers = {}
|
265
|
-
headers['If-Match'] = format_ref(ref) if ref
|
265
|
+
headers['If-Match'] = API::Helpers.format_ref(ref) if ref
|
266
266
|
send_request :delete, path, { query: { purge: true }, headers: headers }
|
267
267
|
end
|
268
268
|
|
269
|
-
#
|
270
|
-
#
|
271
|
-
#
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
#
|
276
|
-
#
|
277
|
-
#
|
278
|
-
#
|
279
|
-
#
|
280
|
-
#
|
281
|
-
#
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
# - A future version will support ruby Time objects.
|
290
|
-
# +ordinal+:: is optional.
|
291
|
-
#
|
292
|
-
def list_events(collection, key, event_type, parameters={})
|
293
|
-
Orchestrate::Helpers.range_keys!('event', parameters)
|
294
|
-
send_request :get, [collection, key, 'events', event_type], { query: parameters }
|
269
|
+
# [Lists events associated with a key](http://orchestrate.io/docs/api/#events/list23).
|
270
|
+
# Results are time-ordered in reverse-chronological order, and paginated.
|
271
|
+
# @param collection [#to_s] The name of the collection.
|
272
|
+
# @param key [#to_s] The name of the key.
|
273
|
+
# @param event_type [#to_s] The category for the event.
|
274
|
+
# @param options [Hash] The parameters for the query.
|
275
|
+
# @option options [Integer] :limit (10) The number of results to return. Default 100.
|
276
|
+
# @option options [Date, Time, String, Integer] :start The inclusive start of the range.
|
277
|
+
# @option options [Date, Time, String, Integer] :after The exclusive start of the range.
|
278
|
+
# @option options [Date, Time, String, Integer] :before The exclusive end of the range.
|
279
|
+
# @option options [Date, Time, String, Integer] :end The inclusive end of the range.
|
280
|
+
# @return Orchestrate::API::CollectionResponse
|
281
|
+
# @raise Orchestrate::API::NotFound If the provided collection/key doesn't exist.
|
282
|
+
def list_events(collection, key, event_type, options={})
|
283
|
+
(options.keys & [:start, :after, :before, :end]).each do |param|
|
284
|
+
options[param] = API::Helpers.timestamp(options[param])
|
285
|
+
end
|
286
|
+
API::Helpers.range_keys!('event', options)
|
287
|
+
path = [collection, key, 'events', event_type]
|
288
|
+
send_request :get, path, { query: options, response: API::CollectionResponse }
|
295
289
|
end
|
296
290
|
|
297
|
-
#
|
298
|
-
#
|
299
|
-
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
#
|
304
|
-
#
|
305
|
-
#
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
291
|
+
# @!endgroup
|
292
|
+
# @!group Graphs / Relations
|
293
|
+
|
294
|
+
# [Retrieves a relation's associated objects](http://orchestrate.io/docs/api/#graph/get26).
|
295
|
+
# @param collection [#to_s] The name of the collection.
|
296
|
+
# @param key [#to_s] The name of the key.
|
297
|
+
# @param kinds [#to_s] The relationship kinds and depth to query.
|
298
|
+
# @example Retrieves the friend's of John's family
|
299
|
+
# client.get_relations(:users, 'john', :family, :friends)
|
300
|
+
# @example If the relation facets exist in an array, use:
|
301
|
+
# relations = [:family, :friends]
|
302
|
+
# client.get_relations(:users, 'john', *relations)
|
303
|
+
# @return Orchestrate::API::CollectionResponse
|
304
|
+
# @raise Orchestrate::API::NotFound If the given collection/key doesn't exist.
|
309
305
|
def get_relations(collection, key, *kinds)
|
310
306
|
path = [collection, key, 'relations'].concat(kinds)
|
311
|
-
send_request :get, path
|
307
|
+
send_request :get, path, {response: API::CollectionResponse}
|
312
308
|
end
|
313
309
|
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
317
|
-
#
|
318
|
-
#
|
319
|
-
#
|
320
|
-
#
|
321
|
-
#
|
322
|
-
#
|
323
|
-
# +to_key+:: a String or Symbol representing the key for the related item.
|
324
|
-
#
|
310
|
+
# [Creates a relationship between two Key/Value objects](http://orchestrate.io/docs/api/#graph/put).
|
311
|
+
# Relations can span collections.
|
312
|
+
# @param collection [#to_s] The name of the collection.
|
313
|
+
# @param key [#to_s] The name of the key.
|
314
|
+
# @param kind [#to_s] The kind of relationship to create.
|
315
|
+
# @param to_collection [#to_s] The name of the collection to relate to.
|
316
|
+
# @param to_key [#to_s] The name of the key to relate to.
|
317
|
+
# @return Orchestrate::API::Response
|
318
|
+
# @raise Orchestrate::API::NotFound If either end of the relation doesn't exist.
|
325
319
|
def put_relation(collection, key, kind, to_collection, to_key)
|
326
320
|
send_request :put, [collection, key, 'relation', kind, to_collection, to_key]
|
327
321
|
end
|
328
322
|
|
329
|
-
#
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
333
|
-
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
# +kind+:: a String or Symbol value representing the relation type.
|
337
|
-
# +to_collection_name+:: a String or Symbol representing the name of the collection the related item belongs.
|
338
|
-
# +to_key+:: a String or Symbol representing the key for the related item.
|
339
|
-
#
|
323
|
+
# [Deletes a relationship between two objects](http://orchestrate.io/docs/api/#graph/delete28).
|
324
|
+
# @param collection [#to_s] The name of the collection.
|
325
|
+
# @param key [#to_s] The name of the key.
|
326
|
+
# @param kind [#to_s] The kind of relationship to delete.
|
327
|
+
# @param to_collection [#to_s] The name of the collection to relate to.
|
328
|
+
# @param to_key [#to_s] The name of the key to relate to.
|
329
|
+
# @return Orchestrate::API::Response
|
340
330
|
def delete_relation(collection, key, kind, to_collection, to_key)
|
341
331
|
path = [collection, key, 'relation', kind, to_collection, to_key]
|
342
332
|
send_request :delete, path, { query: {purge: true} }
|
343
333
|
end
|
344
334
|
|
345
|
-
#
|
346
|
-
|
347
|
-
#
|
348
|
-
#
|
349
|
-
#
|
350
|
-
# output a warning to STDERR.
|
351
|
-
#
|
352
|
-
# Example:
|
335
|
+
# @!endgroup
|
336
|
+
|
337
|
+
# Performs requests in parallel. Requires using a Faraday adapter that supports parallel requests.
|
338
|
+
# @yieldparam accumulator [Hash] A place to store the results of the parallel responses.
|
339
|
+
# @example Performing three requests at once
|
353
340
|
# responses = client.in_parallel do |r|
|
354
341
|
# r[:some_items] = client.list(:site_globals)
|
355
342
|
# r[:user] = client.get(:users, current_user_key)
|
356
343
|
# r[:user_feed] = client.list_events(:users, current_user_key, :notices)
|
357
344
|
# end
|
358
|
-
#
|
345
|
+
# @see README See the Readme for more examples.
|
359
346
|
def in_parallel(&block)
|
360
347
|
accumulator = {}
|
361
348
|
http.in_parallel do
|
@@ -364,47 +351,48 @@ module Orchestrate
|
|
364
351
|
accumulator
|
365
352
|
end
|
366
353
|
|
367
|
-
#
|
368
|
-
#
|
369
|
-
#
|
370
|
-
#
|
371
|
-
#
|
372
|
-
#
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
body = opts.fetch(:body, '')
|
383
|
-
headers = opts.fetch(:headers, {})
|
354
|
+
# Performs an HTTP request against the Orchestrate API
|
355
|
+
# @param method [Symbol] The HTTP method - :get, :post, :put, :delete
|
356
|
+
# @param path [Array<#to_s>] Path segments for the request's URI. Prepended by 'v0'.
|
357
|
+
# @param options [Hash] extra parameters
|
358
|
+
# @option options [Hash] :query ({}) Query String parameters.
|
359
|
+
# @option options [#to_json] :body ('') The request body.
|
360
|
+
# @option options [Hash] :headers ({}) Extra request headers.
|
361
|
+
# @option options [Class] :response (Orchestrate::API::Response) A subclass of Orchestrate::API::Response to instantiate and return
|
362
|
+
# @return API::Response
|
363
|
+
# @raise [Orchestrate::API::RequestError, Orchestrate::API::ServiceError] see http://orchestrate.io/docs/api/#errors
|
364
|
+
def send_request(method, path, options={})
|
365
|
+
path = ['/v0'].concat(path).join('/')
|
366
|
+
query_string = options.fetch(:query, {})
|
367
|
+
body = options.fetch(:body, '')
|
368
|
+
headers = options.fetch(:headers, {})
|
384
369
|
headers['User-Agent'] = "ruby/orchestrate/#{Orchestrate::VERSION}"
|
385
370
|
headers['Accept'] = 'application/json' if method == :get
|
386
371
|
|
387
|
-
http.send(method) do |request|
|
388
|
-
|
389
|
-
request.url url, query_string
|
372
|
+
response = http.send(method) do |request|
|
373
|
+
request.url path, query_string
|
390
374
|
if [:put, :post].include?(method)
|
391
375
|
headers['Content-Type'] = 'application/json'
|
392
376
|
request.body = body.to_json
|
393
377
|
end
|
394
378
|
headers.each {|header, value| request[header] = value }
|
395
379
|
end
|
396
|
-
end
|
397
|
-
|
398
|
-
# ------------------------------------------------------------------------
|
399
380
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
381
|
+
if ! response.success?
|
382
|
+
err_type = API::ERRORS.find do |err|
|
383
|
+
err.status == response.status && err.code == response.body['code']
|
384
|
+
end
|
385
|
+
if err_type
|
386
|
+
raise err_type.new(response)
|
387
|
+
elsif response.status >= 500
|
388
|
+
raise API::ServiceError.new(response)
|
389
|
+
elsif response.status >= 400
|
390
|
+
raise API::RequestError.new(response)
|
391
|
+
end
|
406
392
|
end
|
407
|
-
|
393
|
+
response_class = options.fetch(:response, API::Response)
|
394
|
+
response_class.new(response, self)
|
395
|
+
end
|
408
396
|
end
|
409
397
|
|
410
398
|
end
|