arango-driver 3.5.0.alpha0

Sign up to get free protection for your applications and to get access to all the features.
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