arangorb 0.1.0 → 1.0.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/ArangoRB.gemspec +2 -2
  3. data/README.md +418 -123
  4. data/lib/ArangoRB_AQL.rb +90 -103
  5. data/lib/ArangoRB_Col.rb +476 -159
  6. data/lib/ArangoRB_DB.rb +305 -79
  7. data/lib/ArangoRB_Doc.rb +112 -114
  8. data/lib/ArangoRB_Edg.rb +81 -62
  9. data/lib/ArangoRB_Gra.rb +125 -76
  10. data/lib/ArangoRB_Index.rb +144 -0
  11. data/lib/ArangoRB_Ser.rb +439 -18
  12. data/lib/ArangoRB_Task.rb +136 -0
  13. data/lib/ArangoRB_Tra.rb +47 -42
  14. data/lib/ArangoRB_Tran.rb +48 -0
  15. data/lib/ArangoRB_User.rb +152 -0
  16. data/lib/ArangoRB_Ver.rb +74 -57
  17. data/lib/arangorb.rb +4 -0
  18. data/spec/arangoRB_helper.rb +2 -9
  19. data/spec/arangoRestart_helper.rb +14 -0
  20. data/spec/lib/{arangoAQL_helper.rb → 0.1.0/arangoAQL_helper.rb} +2 -21
  21. data/spec/lib/{arangoC_helper.rb → 0.1.0/arangoC_helper.rb} +40 -19
  22. data/spec/lib/{arangoDB_helper.rb → 0.1.0/arangoDB_helper.rb} +13 -13
  23. data/spec/lib/{arangoDoc_helper.rb → 0.1.0/arangoDoc_helper.rb} +10 -23
  24. data/spec/lib/0.1.0/arangoE_helper.rb +50 -0
  25. data/spec/lib/{arangoG_helper.rb → 0.1.0/arangoG_helper.rb} +7 -21
  26. data/spec/lib/0.1.0/arangoS_helper.rb +37 -0
  27. data/spec/lib/0.1.0/arangoT_helper.rb +48 -0
  28. data/spec/lib/{arangoV_helper.rb → 0.1.0/arangoV_helper.rb} +6 -22
  29. data/spec/lib/1.0.0/arangoC_helper.rb +73 -0
  30. data/spec/lib/1.0.0/arangoDB_helper.rb +81 -0
  31. data/spec/lib/1.0.0/arangoI_helper.rb +43 -0
  32. data/spec/lib/1.0.0/arangoS_helper.rb +196 -0
  33. data/spec/lib/1.0.0/arangoTa_helper.rb +49 -0
  34. data/spec/lib/1.0.0/arangoTr_helper.rb +15 -0
  35. data/spec/lib/1.0.0/arangoU_helper.rb +72 -0
  36. data/spec/lib/arangoRB_0.1.0_helper.rb +9 -0
  37. data/spec/lib/arangoRB_1.0.0_helper.rb +6 -0
  38. data/spec/spec_helper.rb +34 -0
  39. metadata +28 -15
  40. data/spec/lib/arangoE_helper.rb +0 -70
  41. data/spec/lib/arangoS_helper.rb +0 -28
  42. data/spec/lib/arangoT_helper.rb +0 -67
data/lib/ArangoRB_Ser.rb CHANGED
@@ -1,64 +1,485 @@
1
1
  # === SERVER ===
2
2
 
3
- class ArangoS
3
+ class ArangoServer
4
4
  include HTTParty
5
+
5
6
  @@verbose = false
7
+ @@async = false
6
8
  @@database = "_system"
7
9
  @@graph = nil
8
10
  @@collection = nil
11
+ @@user = nil
12
+ @@request = {:body => {}, :headers => {}, :query => {}}
13
+ @@password = ""
14
+ @@username = "root"
15
+ @@server = "localhost"
16
+ @@port = "8529"
17
+ @@cluster = "cluster-test"
9
18
 
10
- def self.default_server(user: "root", password:, server: "localhost", port: "8529")
19
+ def self.default_server(user: @@username, password: @@password, server: @@server, port: @@port) # TESTED
11
20
  base_uri "http://#{server}:#{port}"
12
21
  basic_auth user, password
22
+ @@username = user
23
+ @@password = password
24
+ @@server = server
25
+ @@port = port
26
+ end
27
+
28
+ def self.address # TESTED
29
+ "#{@@server}:#{@@port}"
30
+ end
31
+
32
+ def self.username # TESTED
33
+ @@username
13
34
  end
14
35
 
15
- def self.verbose=(verbose)
36
+ def self.verbose=(verbose) # TESTED
16
37
  @@verbose = verbose
17
38
  end
18
39
 
19
- def self.verbose
40
+ def self.verbose # TESTED
20
41
  @@verbose
21
42
  end
22
43
 
23
- def self.database=(database)
44
+ def self.async=(async) # TESTED
45
+ @@async = async
46
+ if async == true || async == "true"
47
+ @@request[:headers] = {"x-arango-async" => "true"}
48
+ elsif async == "store"
49
+ @@request[:headers] = {"x-arango-async" => "store"}
50
+ else
51
+ @@request[:headers] = {}
52
+ end
53
+ end
54
+
55
+ def self.async # TESTED
56
+ @@async
57
+ end
58
+
59
+ def self.database=(database) # TESTED
24
60
  if database.is_a? String
25
61
  @@database = database
26
- elsif database.is_a? ArangoDB
62
+ elsif database.is_a? ArangoDatabase
27
63
  @@database = database.database
28
64
  else
29
- raise "database should be a String or an ArangoDB instance, not a #{database.class}"
65
+ raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
30
66
  end
31
67
  end
32
68
 
33
- def self.database
69
+ def self.database # TESTED
34
70
  @@database
35
71
  end
36
72
 
37
- def self.graph=(graph)
73
+ def self.graph=(graph) # TESTED
38
74
  if graph.is_a? String
39
75
  @@graph = graph
40
- elsif graph.is_a? ArangoG
41
- @@graph = graph
76
+ elsif graph.is_a? ArangoGraph
77
+ @@graph = graph.graph
42
78
  else
43
- raise "graph should be a String or an ArangoG instance, not a #{graph.class}"
79
+ raise "graph should be a String or an ArangoGraph instance, not a #{graph.class}"
44
80
  end
45
81
  end
46
82
 
47
- def self.graph
83
+ def self.graph # TESTED
48
84
  @@graph
49
85
  end
50
86
 
51
- def self.collection=(collection)
87
+ def self.collection=(collection) # TESTED
52
88
  if collection.is_a? String
53
89
  @@collection = collection
54
- elsif collection.is_a? ArangoC
55
- @@collection = collection
90
+ elsif collection.is_a? ArangoCollection
91
+ @@collection = collection.collection
56
92
  else
57
- raise "graph should be a String or an ArangoC instance, not a #{collection.class}"
93
+ raise "graph should be a String or an ArangoCollection instance, not a #{collection.class}"
58
94
  end
59
95
  end
60
96
 
61
- def self.collection
97
+ def self.collection # TESTED
62
98
  @@collection
63
99
  end
100
+
101
+ def self.user=(user)
102
+ if user.is_a? String
103
+ @@user = user
104
+ elsif user.is_a? ArangoUser
105
+ @@user = user.user
106
+ else
107
+ raise "graph should be a String or an ArangoUser instance, not a #{user.class}"
108
+ end
109
+ end
110
+
111
+ def self.user # TESTED
112
+ @@user
113
+ end
114
+
115
+ def self.request # TESTED
116
+ @@request
117
+ end
118
+
119
+ def self.cluster
120
+ @@cluster
121
+ end
122
+
123
+ def self.cluster=(cluster)
124
+ @@cluster = cluster
125
+ end
126
+
127
+ # === MONITORING ===
128
+
129
+ def self.log # TESTED
130
+ result = get("/_admin/log", @@request)
131
+ return_result result: result
132
+ end
133
+
134
+ def self.reload # TESTED
135
+ result = post("/_admin/routing/reload", @@request)
136
+ return_result result: result, caseTrue: true
137
+ end
138
+
139
+ def self.statistics description: false # TESTED
140
+ if description
141
+ result = get("/_admin/statistics-description", @@request)
142
+ else
143
+ result = get("/_admin/statistics", @@request)
144
+ end
145
+ return_result result: result
146
+ end
147
+
148
+ def self.role # TESTED
149
+ result = get("/_admin/server/role", @@request)
150
+ return_result result: result, key: "role"
151
+ end
152
+
153
+ def self.server
154
+ result = get("/_admin/server/id", @@request)
155
+ return_result result: result
156
+ end
157
+
158
+ def self.clusterStatistics dbserver:
159
+ query = {"DBserver": dbserver}
160
+ request = @@request.merge({ :query => query })
161
+ result = get("/_admin/clusterStatistics", request)
162
+ return_result result: result
163
+ end
164
+
165
+ # === LISTS ===
166
+
167
+ def self.endpoints # TESTED
168
+ result = get("/_api/endpoint", @@request)
169
+ return_result result: result
170
+ end
171
+
172
+ def self.users # TESTED
173
+ result = get("/_api/user", @@request)
174
+ if @@async == "store"
175
+ result.headers["x-arango-async-id"]
176
+ else
177
+ result = result.parsed_response
178
+ if @@verbose
179
+ return result
180
+ else
181
+ if result["error"]
182
+ return result["errorMessage"]
183
+ else
184
+ return result["result"].map{|x| ArangoUser.new(user: x["user"], active: x["active"], extra: x["extra"])}
185
+ end
186
+ end
187
+ end
188
+ end
189
+
190
+ def self.databases(user: nil) # TESTED
191
+ ArangoDatabase.databases user: user
192
+ end
193
+
194
+
195
+ def self.tasks # TESTED
196
+ result = get("/_api/tasks", @@request)
197
+ if @@async == "store"
198
+ result.headers["x-arango-async-id"]
199
+ else
200
+ result = result.parsed_response
201
+ if @@verbose
202
+ result
203
+ else
204
+ if result.is_a?(Hash) && result["error"]
205
+ result["errorMessage"]
206
+ else
207
+ result.map{|x| ArangoTask.new(id: x["id"], name: x["name"], type: x["type"], period: x["period"], created: x["created"], command: x["command"], database: x["database"])}
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ # === ASYNC ===
214
+
215
+ def self.pendingAsync # TESTED
216
+ result = get("/_api/job/pending")
217
+ return_result_async result: result
218
+ end
219
+
220
+ def self.fetchAsync(id:) # TESTED
221
+ result = put("/_api/job/#{id}")
222
+ return_result_async result: result
223
+ end
224
+
225
+ def self.retrieveAsync(type: nil, id: nil) # TESTED
226
+ result = id.nil? ? get("/_api/job/#{type}") : get("/_api/job/#{id}")
227
+ return_result_async result: result
228
+ end
229
+
230
+ def self.retrieveDoneAsync # TESTED
231
+ retrieveAsync(type: "done")
232
+ end
233
+
234
+ def self.retrievePendingAsync # TESTED
235
+ retrieveAsync(type: "pending")
236
+ end
237
+
238
+ def self.cancelAsync(id:) # TESTED
239
+ result = put("/_api/job/#{id}/cancel")
240
+ return_result_async result: result
241
+ end
242
+
243
+ def self.destroyAsync(type: nil, id: nil) # TESTED
244
+ result = id.nil? ? delete("/_api/job/#{type}") : delete("/_api/job/#{id}")
245
+ return_result_async result: result, caseTrue: true
246
+ end
247
+
248
+ def self.destroyAllAsync # TESTED
249
+ destroyAsync(type: "all")
250
+ end
251
+
252
+ def self.destroyExpiredAsync # TESTED
253
+ destroyAsync(type: "expired")
254
+ end
255
+
256
+ # === BATCH ===
257
+
258
+ def self.batch(queries:) # TESTED
259
+ headers = {
260
+ "Content-Type": "multipart/form-data",
261
+ "boundary": "XboundaryX"
262
+ }
263
+ body = ""
264
+ queries.each{|query|
265
+ body += "--XboundaryX\n"
266
+ body += "Content-Type: application/x-arango-batchpart\n"
267
+ body += "Content-Id: #{query[:id]}\n" unless query[:id].nil?
268
+ body += "\n"
269
+ body += "#{query[:type]} "
270
+ body += "#{query[:address]} HTTP/1.1\n"
271
+ body += "\n#{query[:body].to_json}\n" unless query[:body].nil?
272
+ }
273
+ body += "--XboundaryX--\n" if queries.length > 0
274
+ request = @@request.merge({ :body => body, :headers => headers })
275
+ result = post("/_api/batch", request)
276
+ return_result result: result
277
+ end
278
+
279
+ def self.destroyDumpBatch(id:, dbserver: nil) # TESTED
280
+ query = {"DBserver" => dbserver}.delete_if{|k,v| v.nil?}
281
+ request = @@request.merge({ :query => query })
282
+ result = delete("/_api/replication/batch/#{id}", request)
283
+ return true if result.nil?
284
+ return result["errorMessage"] if result["error"]
285
+ end
286
+
287
+ def self.createDumpBatch(ttl:, dbserver: nil) # TESTED
288
+ query = {"DBserver" => dbserver}.delete_if{|k,v| v.nil?}
289
+ body = { "ttl" => ttl }
290
+ request = @@request.merge({ :body => body.to_json, :query => query })
291
+ result = post("/_api/replication/batch", request)
292
+ return_result result: result, key: "id"
293
+ end
294
+
295
+ def self.prolongDumpBatch(id:, ttl:, dbserver: nil) # TESTED
296
+ query = {"DBserver" => dbserver}.delete_if{|k,v| v.nil?}
297
+ body = { "ttl" => ttl }
298
+ request = @@request.merge({ :body => body.to_json, :query => query })
299
+ result = post("/_api/replication/batch/#{id}", request)
300
+ return_result result: result, key: "id"
301
+ end
302
+
303
+ # === REPLICATION ===
304
+
305
+ def self.serverId # TESTED
306
+ result = get("/_api/replication/server-id", @@request)
307
+ return_result result: result, key: "serverId"
308
+ end
309
+
310
+ # === SHARDING ===
311
+
312
+ def self.clusterRoundtrip(cluster: @@cluster)
313
+ result = get("/_admin/#{cluster}", @@request)
314
+ return_result result: result
315
+ end
316
+
317
+ def self.executeCluster(body:, cluster: @@cluster)
318
+ request = @@request.merge({ "body" => body.to_json })
319
+ result = post("/_admin/#{cluster}", request)
320
+ return_result result: result
321
+ end
322
+
323
+ def self.executeClusterPut(body:, cluster: @@cluster)
324
+ request = @@request.merge({ "body" => body.to_json })
325
+ result = put("/_admin/#{cluster}", request)
326
+ return_result result: result
327
+ end
328
+
329
+ def self.destroyCluster(cluster: @@cluster)
330
+ result = delete("/_admin/#{cluster}", @@request)
331
+ return_result result: result, caseTrue: true
332
+ end
333
+
334
+ def self.updateCluster(body:, cluster: @@cluster)
335
+ request = @@request.merge({ "body" => body.to_json })
336
+ result = patch("/_admin/#{cluster}", request)
337
+ return_result result: result, caseTrue: true
338
+ end
339
+
340
+ def self.executeClusterHead(body:, cluster: @@cluster)
341
+ result = head("/_admin/#{cluster}", @@request)
342
+ return_result result: result
343
+ end
344
+
345
+ def self.checkPort(port:)
346
+ query = {"port": port}
347
+ request = @@request.merge({ "query" => query })
348
+ result = get("/_admin/clusterCheckPort", request)
349
+ return_result result: result
350
+ end
351
+
352
+ # === MISCELLANEOUS FUNCTIONS ===
353
+
354
+ def self.version(details: nil) # TESTED
355
+ query = {"details": details}
356
+ request = @@request.merge({ "query" => query })
357
+ result = get("/_api/version", request)
358
+ return_result result: result
359
+ end
360
+
361
+ def self.flushWAL(waitForSync: nil, waitForCollector: nil) # TESTED
362
+ body = {
363
+ "waitForSync" => waitForSync,
364
+ "waitForCollector" => waitForCollector
365
+ }.delete_if{|k,v| v.nil?}.to_json
366
+ request = @@request.merge({ :body => body })
367
+ result = put("/_admin/wal/flush", request)
368
+ return_result result: result, caseTrue: true
369
+ end
370
+
371
+ def self.propertyWAL # TESTED
372
+ result = put("/_admin/wal/properties", @@request)
373
+ return_result result: result
374
+ end
375
+
376
+ def self.changePropertyWAL(allowOversizeEntries: nil, logfileSize: nil, historicLogfiles: nil, reserveLogfiles: nil, throttleWait: nil, throttleWhenPending: nil) # TESTED
377
+ body = {
378
+ "allowOversizeEntries" => allowOversizeEntries,
379
+ "logfileSize" => allowOversizeEntries,
380
+ "historicLogfiles" => historicLogfiles,
381
+ "reserveLogfiles" => reserveLogfiles,
382
+ "throttleWait" => throttleWait,
383
+ "throttleWhenPending" => throttleWhenPending
384
+ }.delete_if{|k,v| v.nil?}.to_json
385
+ request = @@request.merge({ :body => body })
386
+ result = put("/_admin/wal/properties", request)
387
+ return_result result: result
388
+ end
389
+
390
+ def self.transactions # TESTED
391
+ result = get("/_admin/wal/transactions", @@request)
392
+ return_result result: result
393
+ end
394
+
395
+ def self.time # TESTED
396
+ result = get("/_admin/time", @@request)
397
+ return_result result: result, key: "time"
398
+ end
399
+
400
+ def self.echo # TESTED
401
+ result = get("/_admin/echo", @@request)
402
+ return_result result: result
403
+ end
404
+
405
+ # def self.longEcho body: {}
406
+ # request = @@request.merge({ :body => body.to_json })
407
+ # result = get("/_admin/long_echo", request)
408
+ # return_result result: result
409
+ # end
410
+
411
+ def self.databaseVersion # TESTED
412
+ result = get("/_admin/database/target-version", @@request)
413
+ return_result result: result, key: "version"
414
+ end
415
+
416
+ def self.sleep(duration:) # TESTED
417
+ query = {"duration": duration}
418
+ request = @@request.merge({ "query" => query })
419
+ result = get("/_admin/sleep", request)
420
+ return_result result: result, key: "duration"
421
+ end
422
+
423
+ def self.shutdown # TESTED
424
+ result = delete("/_admin/shutdown", @@request)
425
+ return_result result: result, caseTrue: true
426
+ end
427
+
428
+ def self.restart
429
+ `sudo service arangodb restart`
430
+ end
431
+
432
+ def self.test(body:)
433
+ request = @@request.merge({ "body" => body.to_json })
434
+ result = post("/_admin/test", request)
435
+ return_result result: result
436
+ end
437
+
438
+ def self.execute(body:)
439
+ request = @@request.merge({ "body" => body.to_json })
440
+ result = post("/_admin/execute", request)
441
+ return_result result: result
442
+ end
443
+
444
+ # === UTILITY ===
445
+
446
+ def self.return_result(result:, caseTrue: false, key: nil)
447
+ if @@async == "store"
448
+ result.headers["x-arango-async-id"]
449
+ else
450
+ result = result.parsed_response
451
+ if @@verbose || !result.is_a?(Hash)
452
+ result
453
+ else
454
+ if result["error"]
455
+ result["errorMessage"]
456
+ else
457
+ if caseTrue
458
+ true
459
+ elsif key.nil?
460
+ result.delete_if{|k,v| k == "error" || k == "code"}
461
+ else
462
+ result[key]
463
+ end
464
+ end
465
+ end
466
+ end
467
+ end
468
+
469
+ def self.return_result_async(result:, caseTrue: false)
470
+ result = result.parsed_response
471
+ if @@verbose || !result.is_a?(Hash)
472
+ result
473
+ else
474
+ if result["error"]
475
+ result["errorMessage"]
476
+ else
477
+ if caseTrue
478
+ true
479
+ else
480
+ result.delete_if{|k,v| k == "error" || k == "code"}
481
+ end
482
+ end
483
+ end
484
+ end
64
485
  end
@@ -0,0 +1,136 @@
1
+ # === AQL ===
2
+
3
+ class ArangoTask < ArangoServer
4
+ def initialize(database: @@database, id: nil, name: nil, type: nil, period: nil, command: nil, params: {}, created: nil) # TESTED
5
+ if database.is_a?(String)
6
+ @database = database
7
+ elsif database.is_a?(ArangoDatabase)
8
+ @database = database.database
9
+ else
10
+ raise "database should be a String or an ArangoDatabase instance, not a #{database.class}"
11
+ end
12
+ @id = id
13
+ @name = name
14
+ @type = type
15
+ @period = period
16
+ @command = command
17
+ @params = params
18
+ @created = created
19
+ end
20
+
21
+ attr_reader :id, :name, :type, :period, :created, :command, :database, :params
22
+
23
+ def retrieve # TESTED
24
+ result = self.class.get("/_db/#{@database}/_api/tasks/#{@id}")
25
+ if @@async == "store"
26
+ result.headers["x-arango-async-id"]
27
+ else
28
+ result = result.parsed_response
29
+ if @@verbose
30
+ unless result.is_a?(Hash) && result["error"]
31
+ @name = result["name"]
32
+ @type = result["type"]
33
+ @period = result["period"]
34
+ @created = result["created"]
35
+ @command = result["command"]
36
+ @database = result["database"]
37
+ end
38
+ result
39
+ else
40
+ if result.is_a?(Hash) && result["error"]
41
+ result["errorMessage"]
42
+ else
43
+ @name = result["name"]
44
+ @type = result["type"]
45
+ @period = result["period"]
46
+ @created = result["created"]
47
+ @command = result["command"]
48
+ @database = result["database"]
49
+ self
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ def self.tasks # TESTED
56
+ result = get("/_db/#{@@database}/_api/tasks", @@request)
57
+ if @@async == "store"
58
+ result.headers["x-arango-async-id"]
59
+ else
60
+ result = result.parsed_response
61
+ if @@verbose
62
+ result
63
+ else
64
+ if result.is_a?(Hash) && result["error"]
65
+ result["errorMessage"]
66
+ else
67
+ result.map{|x| ArangoTask.new(id: x["id"], name: x["name"], type: x["type"], period: x["period"], created: x["created"], command: x["command"], database: x["database"])}
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def create offset: nil # TESTED
74
+ body = {
75
+ "name" => @name,
76
+ "command" => @command,
77
+ "period" => @period,
78
+ "offset" => offset,
79
+ "params" => @params
80
+ }.delete_if{|k,v| v.nil?}.to_json
81
+ request = @@request.merge({ :body => body })
82
+ if @id.nil?
83
+ result = self.class.post("/_db/#{@database}/_api/tasks", request)
84
+ else
85
+ result = self.class.put("/_db/#{@database}/_api/tasks/#{@id}", request)
86
+ end
87
+ if @@async == "store"
88
+ result.headers["x-arango-async-id"]
89
+ else
90
+ result = result.parsed_response
91
+ if @@verbose
92
+ unless result.is_a?(Hash) && result["error"]
93
+ @id = result["id"]
94
+ @name = result["name"]
95
+ @type = result["type"]
96
+ @period = result["period"]
97
+ @created = result["created"]
98
+ @command = result["command"]
99
+ @database = result["database"]
100
+ end
101
+ result
102
+ else
103
+ if result.is_a?(Hash) && result["error"]
104
+ result["errorMessage"]
105
+ else
106
+ @id = result["id"]
107
+ @name = result["name"]
108
+ @type = result["type"]
109
+ @period = result["period"]
110
+ @created = result["created"]
111
+ @command = result["command"]
112
+ @database = result["database"]
113
+ self
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ def destroy # TESTED
120
+ result = self.class.delete("/_db/#{@database}/_api/tasks/#{@id}", @@request)
121
+ if @@async == "store"
122
+ result.headers["x-arango-async-id"]
123
+ else
124
+ result = result.parsed_response
125
+ if @@verbose
126
+ result
127
+ else
128
+ if result.is_a?(Hash) && result["error"]
129
+ result["errorMessage"]
130
+ else
131
+ true
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end