arangorb3 0.0.10

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.
data/lib/Server.rb ADDED
@@ -0,0 +1,486 @@
1
+ # === SERVER ===
2
+
3
+ module Arango
4
+ class Server
5
+ include Arango::Helper_Error
6
+
7
+ def initialize(username: "root", password:, server: "localhost",
8
+ warning: true, port: "8529", verbose: false, return_output: false,
9
+ async: false, active_cache: false, pool: false, size: 5, timeout: 5,
10
+ tls: false)
11
+ @tls = tls
12
+ @base_uri = "http"
13
+ @base_uri += "s" if tls
14
+ @base_uri += "://#{server}:#{port}"
15
+ @server = server
16
+ @port = port
17
+ @username = username
18
+ @password = password
19
+ @options = {body: {}, headers: {}, query: {},
20
+ basic_auth: {username: @username, password: @password }, format: :plain}
21
+ @verbose = verbose
22
+ @return_output = return_output
23
+ @warning = warning
24
+ @active_cache = active_cache
25
+ @cache = @active_cache ? Arango::Cache.new : nil
26
+ @pool = pool
27
+ @size = size
28
+ @timeout = timeout
29
+ @request = Arango::Request.new(return_output: @return_output,
30
+ base_uri: @base_uri, options: @options, verbose: @verbose, async: @async)
31
+ assign_async(async)
32
+ if @pool
33
+ @internal_request = ConnectionPool.new(size: @size, timeout: @timeout){ @request }
34
+ end
35
+ end
36
+
37
+ # === DEFINE ===
38
+
39
+ attr_reader :async, :port, :server, :base_uri, :username, :cache,
40
+ :verbose, :return_output, :active_cache, :pool, :password, :tls
41
+ attr_accessor :warning, :size, :timeout
42
+
43
+ def active_cache=(active)
44
+ satisfy_category?(active, [true, false])
45
+ @active_cache = active
46
+ if @active_cache
47
+ @cache ||= Arango::Cache.new
48
+ elsif !@cache.nil?
49
+ @cache.clear
50
+ end
51
+ end
52
+
53
+ def pool=(pool)
54
+ satisfy_category?(pool, [true, false])
55
+ return if @pool == pool
56
+ @pool = pool
57
+ if @pool
58
+ @internal_request = ConnectionPool.new(size: @size, timeout: @timeout){ @request }
59
+ else
60
+ @internal_request&.shutdown { |conn| conn.quit }
61
+ @internal_request = nil
62
+ end
63
+ end
64
+ alias changePoolStatus pool=
65
+
66
+ def restartPool
67
+ changePoolStatus(false)
68
+ changePoolStatus(true)
69
+ end
70
+
71
+ def verbose=(verbose)
72
+ satisfy_category?(verbose, [true, false])
73
+ @verbose = verbose
74
+ @request.verbose = verbose
75
+ end
76
+
77
+ def return_output=(return_output)
78
+ satisfy_category?(return_output, [true, false])
79
+ @return_output = return_output
80
+ @request.return_output = return_output
81
+ end
82
+
83
+ def username=(username)
84
+ @username = username
85
+ @options[:basic_auth][:username] = @username
86
+ @request.options = options
87
+ end
88
+
89
+ def password=(password)
90
+ @password = password
91
+ @options[:basic_auth][:password] = @password
92
+ @request.options = options
93
+ end
94
+
95
+ def port=(port)
96
+ @port = port
97
+ @base_uri = "http"
98
+ @base_uri += "s" if @tls
99
+ @base_uri += "://#{@server}:#{@port}"
100
+ @request.base_uri = @base_uri
101
+ end
102
+
103
+ def server=(server)
104
+ @server = server
105
+ @base_uri = "http"
106
+ @base_uri += "s" if @tls
107
+ @base_uri += "://#{@server}:#{@port}"
108
+ @request.base_uri = @base_uri
109
+ end
110
+
111
+ def tls=(tls)
112
+ satisfy_category?(tls, [false, true])
113
+ @tls = tls
114
+ @base_uri = "http"
115
+ @base_uri += "s" if @tls
116
+ @base_uri += "://#{@server}:#{@port}"
117
+ @request.base_uri = @base_uri
118
+ end
119
+
120
+ def async=(async)
121
+ satisfy_category?(async, ["true", "false", false, true, "store", :store])
122
+ case async
123
+ when true, "true"
124
+ @options[:headers]["x-arango-async"] = "true"
125
+ @async = true
126
+ when :store, "store"
127
+ @options[:headers]["x-arango-async"] ="store"
128
+ @async = :store
129
+ when false, "false"
130
+ @options[:headers].delete("x-arango-async")
131
+ @async = false
132
+ end
133
+ @request.async = @async
134
+ @request.options = @options
135
+ end
136
+ alias assign_async async=
137
+
138
+ # === TO HASH ===
139
+
140
+ def to_h
141
+ hash = {
142
+ "base_uri": @base_uri,
143
+ "server": @server,
144
+ "port": @port,
145
+ "username": @username,
146
+ "async": @async,
147
+ "verbose": @verbose,
148
+ "return_output": @return_output,
149
+ "warning": @warning,
150
+ "tls": @tls
151
+ }.delete_if{|k,v| v.nil?}
152
+ hash
153
+ end
154
+
155
+ # === REQUESTS ===
156
+
157
+ def request(*args)
158
+ if @pool
159
+ @internal_request.with{|request| request.request(*args)}
160
+ else
161
+ @request.request(*args)
162
+ end
163
+ end
164
+
165
+ def download(*args)
166
+ if @pool
167
+ @internal_request.with{|request| request.download(*args)}
168
+ else
169
+ @request.download(*args)
170
+ end
171
+ end
172
+
173
+ # == DATABASE ==
174
+
175
+ def [](database)
176
+ Arango::Database.new(name: database, server: self)
177
+ end
178
+
179
+ def database(name:)
180
+ Arango::Database.new(name: name, server: self)
181
+ end
182
+
183
+ def databases(user: false)
184
+ if user
185
+ result = request("GET", "_api/database/user", key: :result)
186
+ else
187
+ result = request("GET", "_api/database", key: :result)
188
+ end
189
+ return result if return_directly?(result)
190
+ result.map{|db| Arango::Database.new(name: db, server: self)}
191
+ end
192
+
193
+ # == CLUSTER ==
194
+
195
+ def checkPort(port: @port)
196
+ request("GET", "_admin/clusterCheckPort", query: {port: port.to_s})
197
+ end
198
+
199
+ # === MONITORING ===
200
+
201
+ def log(upto: nil, level: nil, start: nil, size: nil, offset: nil, search: nil, sort: nil)
202
+ satisfy_category?(upto, [nil, "fatal", 0, "error", 1, "warning", 2, "info", 3, "debug", 4])
203
+ satisfy_category?(sort, [nil, "asc", "desc"])
204
+ query = {
205
+ upto: upto, level: level, start: start, size: size,
206
+ offset: offset, search: search, sort: sort
207
+ }
208
+ request("GET", "_admin/log", query: query)
209
+ end
210
+
211
+ def loglevel
212
+ request("GET", "_admin/log/level")
213
+ end
214
+
215
+ def updateLoglevel(body:)
216
+ request("PUT", "_admin/log/level", body: body)
217
+ end
218
+
219
+ def reload
220
+ request("GET", "_admin/routing/reload")
221
+ return true
222
+ end
223
+
224
+ def available?
225
+ request("POST", "_admin/routing/availability", body: {})
226
+ end
227
+
228
+ def statistics
229
+ request("GET", "_admin/statistics")
230
+ end
231
+
232
+ def statisticsDescription
233
+ request("GET", "_admin/statistics-description")
234
+ end
235
+
236
+ def status
237
+ request("GET", "_admin/status")
238
+ end
239
+
240
+ def role
241
+ request("GET", "_admin/server/role", key: :role)
242
+ end
243
+
244
+ def serverData
245
+ request("GET", "_admin/server/id")
246
+ end
247
+
248
+ def mode
249
+ request("GET", "_admin/server/mode")
250
+ end
251
+
252
+ def updateMode(mode:)
253
+ satisfy_category?(mode, ["default", "readonly"])
254
+ body = {mode: mode}
255
+ request("PUT", "_admin/server/mode", body: mode)
256
+ end
257
+
258
+ def clusterHealth
259
+ request("GET", "_admin/health")
260
+ end
261
+
262
+ def clusterStatistics dbserver:
263
+ query = {DBserver: dbserver}
264
+ request("GET", "_admin/clusterStatistics", query: query)
265
+ end
266
+
267
+ def serverId
268
+ request("GET", "_api/replication/server-id", key: :serverId)
269
+ end
270
+
271
+ # === ENDPOINT ===
272
+
273
+ def endpoint
274
+ "tcp://#{@server}:#{@port}"
275
+ end
276
+
277
+ def endpoints
278
+ request("GET", "_api/cluster/endpoints")
279
+ end
280
+
281
+ def allEndpoints(warning: @warning)
282
+ warning_deprecated(warning, "allEndpoints")
283
+ request("GET", "_api/endpoint")
284
+ end
285
+
286
+ # === USER ===
287
+
288
+ def user(password: "", name:, extra: {}, active: nil)
289
+ Arango::User.new(server: self, password: password, name: name, extra: extra,
290
+ active: active)
291
+ end
292
+
293
+ def users
294
+ result = request("GET", "_api/user", key: :result)
295
+ return result if return_directly?(result)
296
+ result.map do |user|
297
+ Arango::User.new(name: user[:user], active: user[:active],
298
+ extra: user[:extra], server: self)
299
+ end
300
+ end
301
+
302
+ # == TASKS ==
303
+
304
+ def tasks
305
+ result = request("GET", "_api/tasks")
306
+ return result if return_directly?(result)
307
+ result.map do |task|
308
+ database = Arango::Database.new(name: task[:database], server: self)
309
+ Arango::Task.new(body: task, database: database)
310
+ end
311
+ end
312
+
313
+ # === ASYNC ===
314
+
315
+ def fetchAsync(id:)
316
+ request("PUT", "_api/job/#{id}")
317
+ end
318
+
319
+ def cancelAsync(id:)
320
+ request("PUT", "_api/job/#{id}/cancel", key: :result)
321
+ end
322
+
323
+ def destroyAsync(id:, stamp: nil)
324
+ query = {"stamp": stamp}
325
+ request("DELETE", "_api/job/#{id}", query: query, key: :result)
326
+ end
327
+
328
+ def destroyAsyncByType(type:, stamp: nil)
329
+ satisfy_category?(type, ["all", "expired"])
330
+ query = {"stamp": stamp}
331
+ request("DELETE", "_api/job/#{type}", query: query)
332
+ end
333
+
334
+ def destroyAllAsync
335
+ destroyAsyncByType(type: "all")
336
+ end
337
+
338
+ def destroyExpiredAsync
339
+ destroyAsyncByType(type: "expired")
340
+ end
341
+
342
+ def retrieveAsync(id:)
343
+ request("GET", "_api/job/#{id}")
344
+ end
345
+
346
+ def retrieveAsyncByType(type:, count: nil)
347
+ satisfy_category?(type, ["done", "pending"])
348
+ request("GET", "_api/job/#{type}", query: {count: count})
349
+ end
350
+
351
+ def retrieveDoneAsync(count: nil)
352
+ retrieveAsyncByType(type: "done", count: count)
353
+ end
354
+
355
+ def retrievePendingAsync(count: nil)
356
+ retrieveAsyncByType(type: "pending", count: count)
357
+ end
358
+
359
+ # === BATCH ===
360
+
361
+ def batch(boundary: "XboundaryX", queries: [])
362
+ Arango::Batch.new(server: self, boundary: boundary, queries: queries)
363
+ end
364
+
365
+ def createDumpBatch(ttl:, dbserver: nil)
366
+ query = { DBserver: dbserver }
367
+ body = { ttl: ttl }
368
+ result = request("POST", "_api/replication/batch",
369
+ body: body, query: query)
370
+ return result if return_directly?(result)
371
+ return result[:id]
372
+ end
373
+
374
+ def destroyDumpBatch(id:, dbserver: nil)
375
+ query = {DBserver: dbserver}
376
+ result = request("DELETE", "_api/replication/batch/#{id}", query: query)
377
+ return_delete(result)
378
+ end
379
+
380
+ def prolongDumpBatch(id:, ttl:, dbserver: nil)
381
+ query = { DBserver: dbserver }
382
+ body = { ttl: ttl }
383
+ result = request("PUT", "_api/replication/batch/#{id}",
384
+ body: body, query: query)
385
+ return result if return_directly?(result)
386
+ return true
387
+ end
388
+
389
+ # === AGENCY ===
390
+
391
+ def agencyConfig
392
+ request("GET", "_api/agency/config")
393
+ end
394
+
395
+ def agencyWrite(body:, agency_mode: nil)
396
+ satisfy_category?(agency_mode, ["waitForCommmitted", "waitForSequenced", "noWait", nil])
397
+ headers = {"X-ArangoDB-Agency-Mode": agency_mode}
398
+ request("POST", "_api/agency/write", headers: headers,
399
+ body: body)
400
+ end
401
+
402
+ def agencyRead(body:, agency_mode: nil)
403
+ satisfy_category?(agency_mode, ["waitForCommmitted", "waitForSequenced", "noWait", nil])
404
+ headers = {"X-ArangoDB-Agency-Mode": agency_mode}
405
+ request("POST", "_api/agency/read", headers: headers,
406
+ body: body)
407
+ end
408
+
409
+ # === MISCELLANEOUS FUNCTIONS ===
410
+
411
+ def version(details: nil)
412
+ query = {"details": details}
413
+ request("GET", "_api/version", query: query)
414
+ end
415
+
416
+ def engine
417
+ request("GET", "_api/engine")
418
+ end
419
+
420
+ def flushWAL(waitForSync: nil, waitForCollector: nil)
421
+ body = {
422
+ "waitForSync": waitForSync,
423
+ "waitForCollector": waitForCollector
424
+ }
425
+ result = request("PUT", "_admin/wal/flush", body: body)
426
+ return return_directly?(result) ? result: true
427
+ end
428
+
429
+ def propertyWAL
430
+ request("GET", "_admin/wal/properties")
431
+ end
432
+
433
+ def changePropertyWAL(allowOversizeEntries: nil, logfileSize: nil,
434
+ historicLogfiles: nil, reserveLogfiles: nil, throttleWait: nil,
435
+ throttleWhenPending: nil)
436
+ body = {
437
+ "allowOversizeEntries": allowOversizeEntries,
438
+ "logfileSize": allowOversizeEntries,
439
+ "historicLogfiles": historicLogfiles,
440
+ "reserveLogfiles": reserveLogfiles,
441
+ "throttleWait": throttleWait,
442
+ "throttleWhenPending": throttleWhenPending
443
+ }
444
+ request("PUT", "_admin/wal/properties", body: body)
445
+ end
446
+
447
+ def transactions
448
+ request("GET", "_admin/wal/transactions")
449
+ end
450
+
451
+ def time
452
+ request("GET", "_admin/time", key: :time)
453
+ end
454
+
455
+ def echo
456
+ request("POST", "_admin/echo", body: {})
457
+ end
458
+
459
+ def databaseVersion
460
+ request("GET", "_admin/database/target-version", key: :version)
461
+ end
462
+
463
+ def shutdown
464
+ result = request("DELETE", "_admin/shutdown")
465
+ return return_directly?(result) ? result: true
466
+ end
467
+
468
+ def test(body:)
469
+ request("POST", "_admin/test", body: body)
470
+ end
471
+
472
+ def execute(body:)
473
+ request("POST", "_admin/execute", body: body)
474
+ end
475
+
476
+ def return_directly?(result)
477
+ return @async != false || @return_direct_result
478
+ return result if result == true
479
+ end
480
+
481
+ def return_delete(result)
482
+ return result if @async != false
483
+ return return_directly?(result) ? result : true
484
+ end
485
+ end
486
+ end
data/lib/Task.rb ADDED
@@ -0,0 +1,120 @@
1
+ # === TASK ===
2
+
3
+ module Arango
4
+ class Task
5
+ include Arango::Helper_Error
6
+ include Arango::Helper_Return
7
+ include Arango::Database_Return
8
+
9
+ def self.new(*args)
10
+ hash = args[0]
11
+ super unless hash.is_a?(Hash)
12
+ database = hash[:database]
13
+ if database.is_a?(Arango::Database) && database.server.active_cache && !hash[:id].nil?
14
+ cache_name = "#{database.name}/#{hash[:id]}"
15
+ cached = database.server.cache.cache.dig(:task, cache_name)
16
+ if cached.nil?
17
+ hash[:cache_name] = cache_name
18
+ return super
19
+ else
20
+ body = hash[:body] || {}
21
+ [:name, :type, :period, :command, :params, :created].each{|k| body[k] ||= hash[k]}
22
+ cached.assign_attributes(body)
23
+ end
24
+ end
25
+ super
26
+ end
27
+
28
+ def initialize(id: nil, name: nil, type: nil, period: nil, command: nil,
29
+ params: nil, created: nil, body: {}, database:, cache_name: nil)
30
+ assign_database(database)
31
+ unless cache_name.nil?
32
+ @cache_name = cache_name
33
+ @server.cache.save(:task, cache_name, self)
34
+ end
35
+ [:id, :name, :type, :period, :command, :params, :created].each do |k|
36
+ body[k] ||= binding.local_variable_get(k)
37
+ end
38
+ assign_attributes(body)
39
+ end
40
+
41
+ # === DEFINE ===
42
+
43
+ attr_reader :server, :body, :database, :cache_name
44
+ attr_accessor :id, :name, :type, :period, :created,
45
+ :command, :params, :offset
46
+
47
+ def body=(result)
48
+ @body = result
49
+ @id = result[:id] || @id
50
+ @name = result[:name] || @name
51
+ @type = result[:type] || @type
52
+ @period = result[:period] || @period
53
+ @command = result[:command] || @command
54
+ @params = result[:params] || @params
55
+ @offset = result[:offset] || @offset
56
+ @created = result[:created] || @created
57
+ if @server.active_cache && @cache_name.nil?
58
+ @cache_name = "#{@database.name}/#{@id}"
59
+ @server.cache.save(:task, @cache_name, self)
60
+ end
61
+ end
62
+ alias assign_attributes body=
63
+
64
+ # === TO HASH ===
65
+
66
+ def to_h
67
+ {
68
+ "id": @id,
69
+ "name": @name,
70
+ "type": @type,
71
+ "period": @period,
72
+ "command": @command,
73
+ "params": @params,
74
+ "created": @created,
75
+ "cache_name": @cache_name,
76
+ "database": @database.name
77
+ }.delete_if{|k,v| v.nil?}
78
+ end
79
+
80
+ # == RETRIEVE
81
+
82
+ def retrieve
83
+ result = @database.request("GET", "_api/tasks/#{@id}")
84
+ return return_element(result)
85
+ end
86
+
87
+ def create(command: @command, period: @period, offset: @offset, params: @params)
88
+ body = {
89
+ "id": @id,
90
+ "name": @name,
91
+ "command": command,
92
+ "period": period,
93
+ "offset": offset,
94
+ "params": params,
95
+ "database": @database.name
96
+ }
97
+ result = @database.request("POST", "_api/tasks", body: body)
98
+ return return_element(result)
99
+ end
100
+
101
+ def update(command: @command, period: @period, offset: @offset,
102
+ params: @params)
103
+ body = {
104
+ "id": @id,
105
+ "name": @name,
106
+ "command": command,
107
+ "period": period,
108
+ "offset": offset,
109
+ "params": params
110
+ }
111
+ result = @database.request("PUT", "_api/tasks/#{@id}", body: body)
112
+ return return_element(result)
113
+ end
114
+
115
+ def destroy
116
+ result = @server.request("DELETE", "_api/tasks/#{@id}")
117
+ return return_directly?(result) ? result : true
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,115 @@
1
+ # === TRANSACTION ===
2
+
3
+ module Arango
4
+ class Transaction
5
+ include Arango::Helper_Error
6
+ include Arango::Helper_Return
7
+ include Arango::Database_Return
8
+
9
+ def initialize(database:, action:, write: [], read: [], params: nil,
10
+ maxTransactionSize: nil, lockTimeout: nil, waitForSync: nil, intermediateCommitCount: nil, intermedateCommitSize: nil)
11
+ assign_database(database)
12
+ @action = action
13
+ @write = return_write_or_read(write)
14
+ @read = return_write_or_read(read)
15
+ @params = params
16
+ @maxTransactionSize = maxTransactionSize
17
+ @lockTimeout = lockTimeout
18
+ @waitForSync = waitForSync
19
+ @intermediateCommitCount = intermediateCommitCount
20
+ @intermedateCommitSize = intermedateCommitSize
21
+ @result = nil
22
+ end
23
+
24
+ # === DEFINE ===
25
+
26
+ attr_reader :read, :write, :result, :server, :database
27
+ attr_accessor :action, :params, :maxTransactionSize,
28
+ :lockTimeout, :waitForSync, :intermediateCommitCount,
29
+ :intermedateCommitSize
30
+
31
+ def write=(write)
32
+ @write = return_write_or_read(write)
33
+ end
34
+
35
+ def addWrite(write)
36
+ write = return_write_or_read(write)
37
+ @write ||= []
38
+ @write << write
39
+ end
40
+
41
+ def read=(read)
42
+ @read = return_write_or_read(read)
43
+ end
44
+
45
+ def addRead(read)
46
+ read = return_write_or_read(read)
47
+ @read ||= []
48
+ @read << read
49
+ end
50
+
51
+ def return_write_or_read(value)
52
+ case value
53
+ when Array
54
+ return value.map{|x| return_collection(x)}
55
+ when String, Arango::Collection
56
+ return [return_collection(value)]
57
+ when NilClass
58
+ return []
59
+ else
60
+ raise Arango::Error.new err: :read_or_write_should_be_string_or_collections, data: {"wrong_value": value, "wrong_class": value.class}
61
+ end
62
+ end
63
+ private :return_write_or_read
64
+
65
+ def return_collection(collection, type=nil)
66
+ satisfy_class?(collection, [Arango::Collection, String])
67
+ case collection
68
+ when Arango::Collection
69
+ return collection
70
+ when String
71
+ return Arango::Collection.new(name: collection, database: @database)
72
+ end
73
+ end
74
+ private :return_collection
75
+
76
+ # === TO HASH ===
77
+
78
+ def to_h
79
+ {
80
+ "action": @action,
81
+ "result": @result,
82
+ "params": @params,
83
+ "read": @read.map{|x| x.name},
84
+ "write": @write.map{|x| x.name},
85
+ "database": @database.name
86
+ }.delete_if{|k,v| v.nil?}
87
+ end
88
+
89
+ # === EXECUTE ===
90
+
91
+ def execute(action: @action, params: @params,
92
+ maxTransactionSize: @maxTransactionSize,
93
+ lockTimeout: @lockTimeout, waitForSync: @waitForSync,
94
+ intermediateCommitCount: @intermediateCommitCount,
95
+ intermedateCommitSize: @intermedateCommitSize)
96
+ body = {
97
+ "collections": {
98
+ "read": @read.map{|x| x.name},
99
+ "write": @write.map{|x| x.name}
100
+ },
101
+ "action": action,
102
+ "params": params,
103
+ "lockTimeout": lockTimeout,
104
+ "waitForSync": waitForSync,
105
+ "maxTransactionSize": maxTransactionSize,
106
+ "intermediateCommitCount": intermediateCommitCount,
107
+ "intermedateCommitSize": intermedateCommitSize
108
+ }
109
+ result = @database.request("POST", "_api/transaction", body: body)
110
+ return result if @server.async != false
111
+ @result = result[:result]
112
+ return return_directly?(result) ? result : result[:result]
113
+ end
114
+ end
115
+ end