arango-driver 3.5.0.alpha0

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 (72) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +1073 -0
  4. data/arango_opal.js +15 -0
  5. data/lib/arango-driver.rb +61 -0
  6. data/lib/arango.rb +96 -0
  7. data/lib/arango/aql.rb +188 -0
  8. data/lib/arango/collection.rb +575 -0
  9. data/lib/arango/collection/documents.rb +122 -0
  10. data/lib/arango/collection/edges.rb +149 -0
  11. data/lib/arango/collection/importing.rb +57 -0
  12. data/lib/arango/collection/indexes.rb +53 -0
  13. data/lib/arango/collection/replication.rb +24 -0
  14. data/lib/arango/collection/user.rb +28 -0
  15. data/lib/arango/cursor.rb +67 -0
  16. data/lib/arango/database.rb +188 -0
  17. data/lib/arango/database/analyzer.rb +21 -0
  18. data/lib/arango/database/aql_functions.rb +54 -0
  19. data/lib/arango/database/aql_queries.rb +114 -0
  20. data/lib/arango/database/aql_query_cache.rb +27 -0
  21. data/lib/arango/database/collections.rb +100 -0
  22. data/lib/arango/database/foxx_services.rb +103 -0
  23. data/lib/arango/database/graph_access.rb +27 -0
  24. data/lib/arango/database/http_route.rb +9 -0
  25. data/lib/arango/database/replication.rb +96 -0
  26. data/lib/arango/database/stream_transactions.rb +25 -0
  27. data/lib/arango/database/tasks.rb +67 -0
  28. data/lib/arango/database/transactions.rb +15 -0
  29. data/lib/arango/database/user.rb +26 -0
  30. data/lib/arango/database/view_access.rb +37 -0
  31. data/lib/arango/document.rb +443 -0
  32. data/lib/arango/edge.rb +164 -0
  33. data/lib/arango/error.rb +97 -0
  34. data/lib/arango/error_db.rb +27 -0
  35. data/lib/arango/foxx.rb +255 -0
  36. data/lib/arango/graph.rb +202 -0
  37. data/lib/arango/graph/basics.rb +39 -0
  38. data/lib/arango/graph/edge_access.rb +56 -0
  39. data/lib/arango/graph/vertex_access.rb +33 -0
  40. data/lib/arango/helper/collection_assignment.rb +13 -0
  41. data/lib/arango/helper/database_assignment.rb +14 -0
  42. data/lib/arango/helper/request_method.rb +45 -0
  43. data/lib/arango/helper/return.rb +21 -0
  44. data/lib/arango/helper/satisfaction.rb +28 -0
  45. data/lib/arango/helper/server_assignment.rb +13 -0
  46. data/lib/arango/helper/traversal.rb +12 -0
  47. data/lib/arango/index.rb +103 -0
  48. data/lib/arango/replication.rb +231 -0
  49. data/lib/arango/request.rb +92 -0
  50. data/lib/arango/request_batch.rb +174 -0
  51. data/lib/arango/result.rb +130 -0
  52. data/lib/arango/search_view.rb +23 -0
  53. data/lib/arango/server.rb +68 -0
  54. data/lib/arango/server/administration.rb +296 -0
  55. data/lib/arango/server/agency.rb +23 -0
  56. data/lib/arango/server/async.rb +51 -0
  57. data/lib/arango/server/batch.rb +35 -0
  58. data/lib/arango/server/config.rb +76 -0
  59. data/lib/arango/server/databases.rb +71 -0
  60. data/lib/arango/server/monitoring.rb +17 -0
  61. data/lib/arango/server/opal_support.rb +95 -0
  62. data/lib/arango/server/tasks.rb +69 -0
  63. data/lib/arango/server/user.rb +22 -0
  64. data/lib/arango/task.rb +223 -0
  65. data/lib/arango/transaction.rb +113 -0
  66. data/lib/arango/traversal.rb +212 -0
  67. data/lib/arango/user.rb +174 -0
  68. data/lib/arango/version.rb +3 -0
  69. data/lib/arango/vertex.rb +112 -0
  70. data/lib/arango/view.rb +124 -0
  71. data/lib/arango/view/basics.rb +25 -0
  72. metadata +296 -0
@@ -0,0 +1,13 @@
1
+ module Arango
2
+ module Helper
3
+ module ServerAssignment
4
+
5
+ protected
6
+
7
+ def assign_server(server)
8
+ satisfy_class?(server, [Arango::Server])
9
+ @server = server
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Arango
2
+ module Helper
3
+ module Traversal
4
+ def traversal(body: {}, direction: nil, edge_collection: nil, expander: nil, filter: nil, init: nil, item_order: nil, max_depth: nil,
5
+ max_iterations: nil, min_depth: nil, order: nil, sort: nil, strategy: nil, uniqueness: nil, visitor: nil)
6
+ Arango::Traversal.new(body: body, direction: direction, edge_collection: edge_collection, expander: expander, filter: filter, init: init,
7
+ item_order: item_order, max_depth: max_depth, max_iterations: max_iterations, min_depth: min_depth, order: order,
8
+ sort: sort, strategy: strategy, uniqueness: uniqueness, vertex: self, visitor: visitor)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,103 @@
1
+ # === INDEXES ===
2
+
3
+ module Arango
4
+ class Index
5
+ include Arango::Helper::Satisfaction
6
+ include Arango::Helper::Return
7
+ include Arango::Helper::CollectionAssignment
8
+
9
+ def initialize(collection:, fields:, body: {}, cache_name: nil, deduplicate: nil, geo_json: nil, id: nil, min_length: nil, sparse: nil,
10
+ type: "hash", unique: nil)
11
+ assign_collection(collection)
12
+ unless cache_name.nil?
13
+ @cache_name = cache_name
14
+ @server.cache.save(:index, cache_name, self)
15
+ end
16
+ body[:type] ||= type
17
+ body[:id] ||= id
18
+ body[:sparse] ||= sparse
19
+ body[:unique] ||= unique
20
+ body[:fields] ||= fields.is_a?(String) ? [fields] : fields
21
+ body[:deduplicate] ||= deduplicate
22
+ body[:geoJson] ||= geo_json
23
+ body[:minLength] ||= min_length
24
+
25
+ assign_attributes(body)
26
+ end
27
+
28
+ # === DEFINE ===
29
+
30
+ attr_accessor :cache_name, :deduplicate, :fields, :geo_json, :id, :key, :min_length, :sparse, :unique
31
+ attr_reader :collection, :database, :server, :type
32
+
33
+ def type=(type)
34
+ satisfy_category?(type, %w[hash skiplist persistent geo fulltext primary])
35
+ @type = type
36
+ end
37
+ alias assign_type type=
38
+
39
+ def body=(result)
40
+ @body = result
41
+ @id = result[:id] || @id
42
+ @key = @id&.split("/")&.dig(1)
43
+ @type = assign_type(result[:type] || @type)
44
+ @unique = result[:unique] || @unique
45
+ @fields = result[:fields] || @fields
46
+ @sparse = result[:sparse] || @sparse
47
+ @geo_json = result[:geoJson] || @geo_json
48
+ @min_length = result[:minLength] || @min_length
49
+ @deduplicate = result[:deduplicate] || @deduplicate
50
+ if @server.active_cache && @cache_name.nil?
51
+ @cache_name = "#{@database.name}/#{@collection.name}/#{@id}"
52
+ @server.cache.save(:index, @cache_name, self)
53
+ end
54
+ end
55
+ alias assign_attributes body=
56
+
57
+ # === DEFINE ===
58
+
59
+ def to_h
60
+ {
61
+ key: @key,
62
+ id: @id,
63
+ body: @body,
64
+ type: @type,
65
+ sparse: @sparse,
66
+ unique: @unique,
67
+ fields: @fields,
68
+ idCache: @idCache,
69
+ geoJson: @geo_json,
70
+ minLength: @min_length,
71
+ deduplicate: @deduplicate,
72
+ collection: @collection.name
73
+ }.delete_if{|k,v| v.nil?}
74
+ end
75
+
76
+ # === COMMANDS ===
77
+
78
+ def retrieve
79
+ result = @database.request("GET", "_api/index/#{@id}")
80
+ return_element(result)
81
+ end
82
+
83
+ def create
84
+ body = {
85
+ fields: @fields,
86
+ unique: @unique,
87
+ type: @type,
88
+ id: @id,
89
+ geoJson: @geo_json,
90
+ minLength: @min_length,
91
+ deduplicate: @deduplicate
92
+ }
93
+ query = { collection: @collection.name }
94
+ result = @database.request("POST", "_api/index", body: body, query: query)
95
+ return_element(result)
96
+ end
97
+
98
+ def destroy
99
+ result = @database.request("DELETE", "_api/index/#{@id}")
100
+ return_delete(result)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,231 @@
1
+ # === REPLICATION ===
2
+
3
+ module Arango
4
+ class Replication
5
+ include Arango::Helper::Satisfaction
6
+
7
+ def initialize(master:, slave:, adaptive_polling: nil, auto_resync: nil, auto_resync_retries: nil, chunk_size: nil, connect_timeout: nil,
8
+ connection_retry_wait_time: nil, idle_max_wait_time: nil, idle_min_wait_time: nil, include_system: true, incremental: nil,
9
+ initial_sync_max_wait_time: nil, max_connect_retries: nil, request_timeout: nil, require_from_present: nil,
10
+ restrict_collections: nil, restrict_type: nil, verbose: nil)
11
+ @adaptive_polling = adaptive_polling
12
+ @auto_resync = auto_resync
13
+ @auto_resync_retries = auto_resync_retries
14
+ @chunk_size = chunk_size
15
+ @connect_timeout = connect_timeout
16
+ @connection_retry_wait_time = connection_retry_wait_time
17
+ @idle_max_wait_time = idle_max_wait_time
18
+ @idle_min_wait_time = idle_min_wait_time
19
+ @include_system = include_system
20
+ @incremental = incremental
21
+ @initial_sync_max_wait_time = initial_sync_max_wait_time,
22
+ @max_connect_retries = max_connect_retries
23
+ @request_timeout = request_timeout
24
+ @require_from_present = require_from_present
25
+ @verbose = verbose
26
+ assign_master(master)
27
+ assign_restrict_collections(restrict_collections)
28
+ assign_restrict_type(restrict_type)
29
+ assign_slave(slave)
30
+ end
31
+
32
+ attr_accessor :adaptive_polling, :auto_resync, :auto_resync_retries, :chunk_size, :connect_timeout, :connection_retry_wait_time, :endpoint,
33
+ :idle_max_wait_time, :idle_min_wait_time, :include_system, :incremental, :initial_sync_max_wait_time, :max_connect_retries,
34
+ :password, :request_timeout, :require_from_present, :username, :verbose
35
+ attr_reader :master, :restrict_collections, :restrict_type, :slave
36
+
37
+ def master=(master)
38
+ satisfy_class?(master, [Arango::Database])
39
+ @master = master
40
+ @master_server = @master.server
41
+ end
42
+ alias assign_master master=
43
+
44
+ def slave=(slave)
45
+ satisfy_class?(slave, [Arango::Database])
46
+ @slave = slave
47
+ @slave_server = @slave.server
48
+ end
49
+ alias assign_slave slave=
50
+
51
+ def restrict_type=(restrict_type)
52
+ satisfy_category?(restrict_type, ["include", "exclude", nil])
53
+ @restrict_type = restrict_type
54
+ end
55
+ alias assign_restrict_type restrict_type=
56
+
57
+ def restrict_collections=(restrict_collections)
58
+ if restrict_collections.nil?
59
+ @restrict_collections = nil
60
+ else
61
+ satisfy_class?(restrict_collections, [Arango::Collection, String], true)
62
+ @restrict_collections = restrict_collections.map do |v|
63
+ case v
64
+ when String
65
+ v
66
+ when Arango::Collection
67
+ v.name
68
+ end
69
+ end
70
+ end
71
+ end
72
+ alias assign_restrict_collections restrict_collections=
73
+
74
+
75
+ def to_h
76
+ master
77
+ {
78
+ master: {
79
+ database: @master.name,
80
+ username: @master_server.username,
81
+ endpoint: @master_server.endpoint
82
+ },
83
+ slave: {
84
+ database: @slave.name,
85
+ username: @slave_server.username,
86
+ endpoint: @slave_server.endpoint
87
+ },
88
+ options: {
89
+ adaptivePolling: @adaptive_polling,
90
+ autoResync: @auto_resync,
91
+ autoResyncRetries: @auto_resync_retries,
92
+ chunkSize: @chunk_size,
93
+ connectionRetryWaitTime: @connection_retry_wait_time,
94
+ connectTimeout: @connect_timeout,
95
+ idleMaxWaitTime: @idle_max_wait_time,
96
+ idleMinWaitTime: @idle_min_wait_time,
97
+ includeSystem: @include_system,
98
+ incremental: @incremental,
99
+ initialSyncMaxWaitTime: @initial_sync_max_wait_time,
100
+ maxConnectRetries: @max_connect_retries,
101
+ requestTimeout: @request_timeout,
102
+ requireFromPresent: @require_from_present,
103
+ restrictCollections: @restrict_collections,
104
+ restrictType: @restrict_type,
105
+ verbose: @verbose
106
+ }.delete_if{|k,v| v.nil?}
107
+ }
108
+ end
109
+
110
+ # SYNCRONISATION
111
+
112
+ def sync
113
+ body = {
114
+ username: @master_server.username,
115
+ password: @master_server.password,
116
+ database: @master.name,
117
+ endpoint: @master_server.endpoint,
118
+ includeSystem: @include_system,
119
+ incremental: @incremental,
120
+ initialSyncMaxWaitTime: @initial_sync_max_wait_time,
121
+ restrictCollections: @restrict_collections,
122
+ restrictType: @restrict_type
123
+ }
124
+ @slave.request("PUT", "_api/replication/sync", body: body)
125
+ end
126
+
127
+ # ENSLAVING
128
+
129
+ def enslave
130
+ body = {
131
+ username: @master_server.username,
132
+ password: @master_server.password,
133
+ database: @database.name,
134
+ endpoint: @server.endpoint,
135
+ adaptivePolling: @adaptive_polling,
136
+ autoResync: @auto_resync,
137
+ autoResyncRetries: @auto_resync_retries,
138
+ chunkSize: @chunk_size,
139
+ connectionRetryWaitTime: @connection_retry_wait_time,
140
+ connectTimeout: @connect_timeout,
141
+ idleMaxWaitTime: @idle_max_wait_time,
142
+ idleMinWaitTime: @idle_min_wait_time,
143
+ includeSystem: @include_system,
144
+ initialSyncMaxWaitTime: @initial_sync_max_wait_time,
145
+ maxConnectRetries: @max_connect_retries,
146
+ requestTimeout: @request_timeout,
147
+ requireFromPresent: @require_from_present,
148
+ restrictCollections: @restrict_collections,
149
+ restrictType: @restrict_type,
150
+ verbose: @verbose
151
+ }
152
+ @slave.request("PUT", "_api/replication/make-slave", body: body)
153
+ end
154
+
155
+ # REPLICATION
156
+
157
+ def start(from: nil)
158
+ @slave.request("PUT", "_api/replication/applier-start", query: {from: from})
159
+ end
160
+
161
+ def stop
162
+ @slave.request("PUT", "_api/replication/applier-stop")
163
+ end
164
+
165
+ def state
166
+ @slave.request("GET", "_api/replication/applier-state")
167
+ end
168
+
169
+ def configuration
170
+ @slave.request("GET", "_api/replication/applier-config")
171
+ end
172
+
173
+ def modify
174
+ body = {
175
+ username: @master_server.username,
176
+ password: @master_server.password,
177
+ database: @master.name,
178
+ endpoint: @master_server.endpoint,
179
+ adaptivePolling: @adaptive_polling,
180
+ autoResync: @auto_resync,
181
+ autoResyncRetries: @auto_resync_retries,
182
+ autoStart: @auto_start, # TODO
183
+ chunkSize: @chunk_size,
184
+ connectionRetryWaitTime: @connection_retry_wait_time,
185
+ connectTimeout: @connect_timeout,
186
+ idleMaxWaitTime: @idle_max_wait_time,
187
+ idleMinWaitTime: @idle_min_wait_time,
188
+ includeSystem: @include_system,
189
+ initialSyncMaxWaitTime: @initial_sync_max_wait_time,
190
+ maxConnectRetries: @max_connect_retries,
191
+ requestTimeout: @request_timeout,
192
+ requireFromPresent: @require_from_present,
193
+ restrictCollections: @restrict_collections,
194
+ restrictType: @restrict_type,
195
+ verbose: @verbose
196
+ }
197
+ @slave.request("PUT", "_api/replication/applier-config", body: body)
198
+ end
199
+ alias modify_replication modify
200
+
201
+ # LOGGER
202
+
203
+ def logger
204
+ @slave.request("GET", "_api/replication/logger-state")
205
+ end
206
+
207
+ def logger_follow(from: nil, to: nil, chunk_size: nil, include_system: nil)
208
+ query = {
209
+ from: from,
210
+ to: to,
211
+ chunkSize: chunk_size,
212
+ includeSystem: include_system
213
+ }
214
+ @slave.request("GET", "_api/replication/logger-follow", query: query)
215
+ end
216
+
217
+ def logger_first_tick
218
+ @slave.request("GET", "_api/replication/logger-first-tick", key: :firstTick)
219
+ end
220
+
221
+ def logger_range_tick
222
+ @slave.request("GET", "_api/replication/logger-tick-ranges")
223
+ end
224
+
225
+ # SERVER-ID
226
+
227
+ def server_id
228
+ @slave.request("GET", "_api/replication/server-id", key: :serverId)
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,92 @@
1
+ module Arango
2
+ class Request
3
+ def initialize(base_uri:, options:)
4
+ @base_uri = base_uri
5
+ @default_options = options
6
+ end
7
+
8
+ attr_accessor :base_uri, :default_options
9
+
10
+ def request(get: nil, head: nil, patch: nil, post: nil, put: nil, delete: nil,
11
+ db: nil, body: {}, headers: nil, query: nil, keep_null: false, block: nil)
12
+ # TODO uri safety, '..', etc., maybe arango is guarded? not sure.
13
+
14
+ if body.class == Hash
15
+ body.delete_if{|_,v| v.nil?} unless keep_null
16
+ body = Oj.dump(body, mode: :json)
17
+ elsif body.class == Array
18
+ body = Oj.dump(body, mode: :json)
19
+ end
20
+
21
+ options = @default_options.merge({ body: body })
22
+
23
+ if query
24
+ query.delete_if{|_,v| v.nil?}
25
+ options[:params] = query
26
+ end
27
+
28
+ if headers
29
+ headers.delete_if{|_,v| v.nil?}
30
+ options[:headers] = {} unless options.key?(:headers)
31
+ options[:headers] = options[:headers].merge(headers)
32
+ end
33
+
34
+ options.delete_if{|_,v| v.nil? || v.empty?}
35
+
36
+ dbcontext = db ? "_db/#{db}/" : nil
37
+
38
+ #STDERR.puts "ROPTS #{options} P g #{get} u #{put} s #{post} d #{delete} c #{patch} h #{head}"
39
+
40
+ begin
41
+ response = if get then Typhoeus.get("#{@base_uri}/#{dbcontext}#{get}", options)
42
+ elsif head then Typhoeus.head("#{@base_uri}/#{dbcontext}#{head}", options)
43
+ elsif patch then Typhoeus.patch("#{@base_uri}/#{dbcontext}#{patch}", options)
44
+ elsif post then Typhoeus.post("#{@base_uri}/#{dbcontext}#{post}", options)
45
+ elsif put then Typhoeus.put("#{@base_uri}/#{dbcontext}#{put}", options)
46
+ elsif delete then Typhoeus.delete("#{@base_uri}/#{dbcontext}#{delete}", options)
47
+ end
48
+ rescue Exception => e
49
+ raise Arango::Error.new err: :impossible_to_connect_with_database, data: { error: e.message }
50
+ end
51
+
52
+ if headers && headers.key?("Content-Type") && headers["Content-Type"].start_with?("multipart/form-data")
53
+ return response.response_body
54
+ end
55
+
56
+ begin
57
+ json_result = unless response.response_body.empty?
58
+ Oj.load(response.response_body, mode: :json, symbol_keys: true)
59
+ else
60
+ {}
61
+ end
62
+ result = Arango::Result.new(json_result)
63
+ result.response_code = response.response_code
64
+ rescue Exception => e
65
+ raise Arango::Error.new err: :impossible_to_parse_arangodb_response,
66
+ data: { response: response.response_body, request: JSON.pretty_generate(options) }
67
+ end
68
+
69
+ if !result.is_array? && result.error?
70
+ raise Arango::ErrorDB.new(message: result.error_message, code: result.code, data: result.to_h, error_num: result.error_num, request: options)
71
+ end
72
+
73
+ block ? block.call(result) : result
74
+ end
75
+
76
+ def download(url:, path:, body: {}, headers: {}, query: {})
77
+ send_url = "#{@base_uri}/"
78
+ send_url += url
79
+ body.delete_if{|_,v| v.nil?}
80
+ query.delete_if{|_,v| v.nil?}
81
+ headers.delete_if{|_,v| v.nil?}
82
+ body = Oj.dump(body, mode: :json)
83
+ options = @default_options.merge({body: body, query: query, headers: headers, stream_body: true})
84
+ File.open(path, "w") do |file|
85
+ file.binmode
86
+ Typhoeus.post(send_url, options) do |fragment|
87
+ file.write(fragment)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end