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/Index.rb ADDED
@@ -0,0 +1,126 @@
1
+ # === INDEXES ===
2
+
3
+ module Arango
4
+ class Index
5
+ include Arango::Helper_Error
6
+ include Arango::Helper_Return
7
+ include Arango::Collection_Return
8
+
9
+ def self.new(*args)
10
+ hash = args[0]
11
+ super unless hash.is_a?(Hash)
12
+ collection = hash[:collection]
13
+ if collection.is_a?(Arango::Collection) && collection.database.server.active_cache && !hash[:id].nil?
14
+ cache_name = "#{collection.database.name}/#{collection.name}/#{hash[:id]}"
15
+ cached = collection.database.server.cache.cache.dig(:index, cache_name)
16
+ if cached.nil?
17
+ hash[:cache_name] = cache_name
18
+ return super
19
+ else
20
+ body = hash[:body] || {}
21
+ [:type, :sparse, :unique, :fields, :deduplicate, :geoJson,
22
+ :minLength].each{|k| body[k] ||= hash[k]}
23
+ cached.assign_attributes(body)
24
+ return cached
25
+ end
26
+ end
27
+ super
28
+ end
29
+
30
+ def initialize(collection:, body: {}, id: nil, type: "hash", unique: nil,
31
+ fields:, sparse: nil, geoJson: nil, minLength: nil, deduplicate: nil,
32
+ cache_name: nil)
33
+ assign_collection(collection)
34
+ unless cache_name.nil?
35
+ @cache_name = cache_name
36
+ @server.cache.save(:index, cache_name, self)
37
+ end
38
+ body[:type] ||= type
39
+ body[:id] ||= id
40
+ body[:sparse] ||= sparse
41
+ body[:unique] ||= unique
42
+ body[:fields] ||= fields.is_a?(String) ? [fields] : fields
43
+ body[:deduplicate] ||= deduplicate
44
+ body[:geoJson] ||= geoJson
45
+ body[:minLength] ||= minLength
46
+
47
+ assign_attributes(body)
48
+ end
49
+
50
+ # === DEFINE ===
51
+
52
+ attr_accessor :id, :unique, :fields, :key, :sparse, :geoJson, :minLenght,
53
+ :deduplicate, :cache_name
54
+ attr_reader :type, :database, :collection, :server
55
+
56
+ def type=(type)
57
+ satisfy_category?(type, ["hash", "skiplist", "persistent", "geo", "fulltext", "primary"])
58
+ @type = type
59
+ end
60
+ alias assign_type type=
61
+
62
+ def body=(result)
63
+ @body = result
64
+ @id = result[:id] || @id
65
+ @key = @id&.split("/")&.dig(1)
66
+ @type = assign_type(result[:type] || @type)
67
+ @unique = result[:unique] || @unique
68
+ @fields = result[:fields] || @fields
69
+ @sparse = result[:sparse] || @sparse
70
+ @geoJson = result[:geoJson] || @geoJson
71
+ @minLength = result[:minLength] || @minLength
72
+ @deduplicate = result[:deduplicate] || @deduplicate
73
+ if @server.active_cache && @cache_name.nil?
74
+ @cache_name = "#{@database.name}/#{@collection.name}/#{@id}"
75
+ @server.cache.save(:index, @cache_name, self)
76
+ end
77
+ end
78
+ alias assign_attributes body=
79
+
80
+ # === DEFINE ===
81
+
82
+ def to_h
83
+ {
84
+ "key": @key,
85
+ "id": @id,
86
+ "body": @body,
87
+ "type": @type,
88
+ "sparse": @sparse,
89
+ "unique": @unique,
90
+ "fields": @fields,
91
+ "idCache": @idCache,
92
+ "geoJson": @geoJson,
93
+ "minLength": @minLength,
94
+ "deduplicate": @deduplicate,
95
+ "collection": @collection.name
96
+ }.delete_if{|k,v| v.nil?}
97
+ end
98
+
99
+ # === COMMANDS ===
100
+
101
+ def retrieve
102
+ result = @database.request("GET", "_api/index/#{@id}")
103
+ return_element(result)
104
+ end
105
+
106
+ def create
107
+ body = {
108
+ "fields": @fields,
109
+ "unique": @unique,
110
+ "type": @type,
111
+ "id": @id,
112
+ "geoJson": @geoJson,
113
+ "minLength": @minLength,
114
+ "deduplicate": @deduplicate
115
+ }
116
+ query = { "collection": @collection.name }
117
+ result = @database.request("POST", "_api/index", body: body, query: query)
118
+ return_element(result)
119
+ end
120
+
121
+ def destroy
122
+ result = @database.request("DELETE", "_api/index/#{@id}")
123
+ return_delete(result)
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,237 @@
1
+ # === REPLICATION ===
2
+
3
+ module Arango
4
+ class Replication
5
+ include Arango::Helper_Error
6
+
7
+ def initialize(master:, slave:, includeSystem: true,
8
+ initialSyncMaxWaitTime: nil, incremental: nil,
9
+ restrictCollections: nil, connectTimeout: nil,
10
+ autoResync: nil, idleMinWaitTime: nil, requestTimeout: nil,
11
+ requireFromPresent: nil, idleMaxWaitTime: nil, restrictType: nil,
12
+ maxConnectRetries: nil, adaptivePolling: nil,
13
+ connectionRetryWaitTime: nil, autoResyncRetries: nil, chunkSize: nil,
14
+ verbose: nil)
15
+ assign_master(master)
16
+ assign_slave(slave)
17
+ assign_restrictType(restrictType)
18
+ assign_restrictCollections(restrictCollections)
19
+ @includeSytem = includeSystem
20
+ @initialSyncMaxWaitTime = initialSyncMaxWaitTime,
21
+ @incremental = incremental
22
+ @connectTimeout = connectTimeout
23
+ @autoResync = autoResync
24
+ @idleMinWaitTime = idleMinWaitTime
25
+ @requestTimeout = requestTimeout
26
+ @requireFromPresent = requireFromPresent
27
+ @idleMaxWaitTime = idleMaxWaitTime
28
+ @maxConnectRetries = maxConnectRetries
29
+ @adaptivePolling = adaptivePolling
30
+ @connectionRetryWaitTime = connectionRetryWaitTime
31
+ @autoResyncRetries = autoResyncRetries
32
+ @chunkSize = chunkSize
33
+ @verbose = verbose
34
+ end
35
+
36
+ attr_accessor :endpoint, :username, :password, :includeSystem,
37
+ :initialSyncMaxWaitTime, :incremental, :verbose, :connectTimeout,
38
+ :autoResync, :idleMinWaitTime, :requestTimeout, :requireFromPresent,
39
+ :idleMaxWaitTime, :maxConnectRetries, :adaptivePolling,
40
+ :connectionRetryWaitTime, :autoResyncRetries, :chunkSize
41
+ attr_reader :master, :slave, :restrictType, :restrictCollections
42
+
43
+ def master=(master)
44
+ satisfy_class?(master, [Arango::Database])
45
+ @master = master
46
+ @master_server = @master.server
47
+ end
48
+ alias assign_master master=
49
+
50
+ def slave=(slave)
51
+ satisfy_class?(slave, [Arango::Database])
52
+ @slave = slave
53
+ @slave_server = @slave.server
54
+ end
55
+ alias assign_slave slave=
56
+
57
+ def restrictType=(restrictType)
58
+ satisfy_category?(restrictType, ["include", "exclude", nil])
59
+ @restrictType = restrictType
60
+ end
61
+ alias assign_restrictType restrictType=
62
+
63
+ def restrictCollections=(restrictCollections)
64
+ if restrictCollections.nil?
65
+ @restrictCollections = nil
66
+ else
67
+ satisfy_class?(restrictCollections, [Arango::Collection, String], true)
68
+ @restrictCollections = restrictCollections.map do |v|
69
+ case v
70
+ when String
71
+ v
72
+ when Arango::Collection
73
+ v.name
74
+ end
75
+ end
76
+ end
77
+ end
78
+ alias assign_restrictCollections restrictCollections=
79
+
80
+
81
+ def to_h
82
+ master
83
+ {
84
+ "master": {
85
+ "database": @master.name,
86
+ "username": @master_server.username,
87
+ "endpoint": @master_server.endpoint
88
+ },
89
+ "slave": {
90
+ "database": @slave.name,
91
+ "username": @slave_server.username,
92
+ "endpoint": @slave_server.endpoint
93
+ },
94
+ "options": {
95
+ "includeSytem": @includeSystem,
96
+ "initialSyncMaxWaitTime": @initialSyncMaxWaitTime,
97
+ "restrictType": @restrictType,
98
+ "incremental": @incremental,
99
+ "restrictCollections": @restrictCollections,
100
+ "verbose": @verbose,
101
+ "connectTimeout": @connectTimeout,
102
+ "autoResync": @autoResync,
103
+ "idleMinWaitTime": @idleMinWaitTime,
104
+ "requestTimeout": @requestTimeout,
105
+ "requireFromPresent": @requireFromPresent,
106
+ "idleMaxWaitTime": @idleMaxWaitTime,
107
+ "maxConnectRetries": @maxConnectRetries,
108
+ "adaptivePolling": @adaptivePolling,
109
+ "connectionRetryWaitTime": @connectionRetryWaitTime,
110
+ "autoResyncRetries": @autoResyncRetries,
111
+ "chunkSize": @chunkSize
112
+ }.delete_if{|k,v| v.nil?}
113
+ }
114
+ end
115
+
116
+ # SYNCRONISATION
117
+
118
+ def sync
119
+ body = {
120
+ "username": @master_server.username,
121
+ "password": @master_server.password,
122
+ "endpoint": @master_server.endpoint,
123
+ "database": @master.name,
124
+ "restrictType": @restrictType,
125
+ "incremental": @incremental,
126
+ "includeSystem": @includeSystem,
127
+ "restrictCollections": @restrictCollections,
128
+ "initialSyncMaxWaitTime": @initialSyncMaxWaitTime
129
+ }
130
+ @slave.request("PUT", "_api/replication/sync", body: body)
131
+ end
132
+
133
+ # ENSLAVING
134
+
135
+ def enslave
136
+ body = {
137
+ "username": @master_server.username,
138
+ "password": @master_server.password,
139
+ "includeSystem": @includeSystem,
140
+ "endpoint": @server.endpoint,
141
+ "initialSyncMaxWaitTime": @initialSyncMaxWaitTime,
142
+ "database": @database.name,
143
+ "verbose": verbose,
144
+ "connectTimeout": @connectTimeout,
145
+ "autoResync": @autoResync,
146
+ "idleMinWaitTime": @idleMinWaitTime,
147
+ "requestTimeout": @requestTimeout,
148
+ "requireFromPresent": @requireFromPresent,
149
+ "idleMaxWaitTime": @idleMaxWaitTime,
150
+ "restrictType": @restrictType,
151
+ "maxConnectRetries": @maxConnectRetries,
152
+ "adaptivePolling": @adaptivePolling,
153
+ "connectionRetryWaitTime": @connectionRetryWaitTime,
154
+ "restrictCollections": @restrictCollections,
155
+ "autoResyncRetries": @autoResyncRetries,
156
+ "chunkSize": @chunkSize
157
+ }
158
+ @slave.request("PUT", "_api/replication/make-slave", body: body)
159
+ end
160
+
161
+ # REPLICATION
162
+
163
+ def start(from: nil)
164
+ @slave.request("PUT", "_api/replication/applier-start", query: {from: from})
165
+ end
166
+
167
+ def stop
168
+ @slave.request("PUT", "_api/replication/applier-stop")
169
+ end
170
+
171
+ def state
172
+ @slave.request("GET", "_api/replication/applier-state")
173
+ end
174
+
175
+ def configuration
176
+ @slave.request("GET", "_api/replication/applier-config")
177
+ end
178
+
179
+ def modify
180
+ body = {
181
+ "username": @master_server.username,
182
+ "password": @master_server.password,
183
+ "endpoint": @master_server.endpoint,
184
+ "database": @master.name,
185
+ "verbose": @verbose,
186
+ "autoResync": @autoResync,
187
+ "autoStart": @autoStart,
188
+ "chunkSize": @chunkSize,
189
+ "includeSystem": @includeSystem,
190
+ "connectTimeout": @connectTimeout,
191
+ "idleMinWaitTime": @idleMinWaitTime,
192
+ "requestTimeout": @requestTimeout,
193
+ "restrictType": @restrictType,
194
+ "requireFromPresent": @requireFromPresent,
195
+ "idleMaxWaitTime": @idleMaxWaitTime,
196
+ "maxConnectRetries": @maxConnectRetries,
197
+ "adaptivePolling": @adaptivePolling,
198
+ "initialSyncMaxWaitTime": @initialSyncMaxWaitTime,
199
+ "connectionRetryWaitTime": @connectionRetryWaitTime,
200
+ "restrictCollections": @restrictCollections,
201
+ "autoResyncRetries": @autoResyncRetries
202
+ }
203
+ @slave.request("PUT", "_api/replication/applier-config", body: body)
204
+ end
205
+ alias modifyReplication modify
206
+
207
+ # LOGGER
208
+
209
+ def logger
210
+ @slave.request("GET", "_api/replication/logger-state")
211
+ end
212
+
213
+ def loggerFollow(from: nil, to: nil, chunkSize: nil, includeSystem: nil)
214
+ query = {
215
+ "from": from,
216
+ "to": to,
217
+ "chunkSize": chunkSize,
218
+ "includeSystem": includeSystem
219
+ }
220
+ @slave.request("GET", "_api/replication/logger-follow", query: query)
221
+ end
222
+
223
+ def loggerFirstTick
224
+ @slave.request("GET", "_api/replication/logger-first-tick", key: :firstTick)
225
+ end
226
+
227
+ def loggerRangeTick
228
+ @slave.request("GET", "_api/replication/logger-tick-ranges")
229
+ end
230
+
231
+ # SERVER-ID
232
+
233
+ def serverId
234
+ @slave.request("GET", "_api/replication/server-id", key: :serverId)
235
+ end
236
+ end
237
+ end
data/lib/Request.rb ADDED
@@ -0,0 +1,143 @@
1
+ module Arango
2
+ class Request
3
+ def initialize(return_output:, base_uri:, options:, verbose:, async:)
4
+ @return_output = return_output
5
+ @base_uri = base_uri
6
+ @options = options
7
+ @verbose = verbose
8
+ @async = async
9
+ end
10
+
11
+ attr_accessor :return_output, :base_uri, :options, :verbose, :async
12
+
13
+ def request(action, url, body: {}, headers: {}, query: {},
14
+ key: nil, return_direct_result: @return_output, skip_to_json: false,
15
+ keepNull: false, skip_parsing: false)
16
+ send_url = "#{@base_uri}/"
17
+ send_url += url
18
+
19
+ if body.is_a?(Hash)
20
+ body.delete_if{|k,v| v.nil?} unless keepNull
21
+ end
22
+ query.delete_if{|k,v| v.nil?}
23
+ headers.delete_if{|k,v| v.nil?}
24
+ options = @options.merge({body: body, query: query})
25
+ options[:headers].merge!(headers)
26
+
27
+ if ["GET", "HEAD", "DELETE"].include?(action)
28
+ options.delete(:body)
29
+ end
30
+
31
+ if @verbose
32
+ puts "\n===REQUEST==="
33
+ puts "#{action} #{send_url}\n"
34
+ puts JSON.pretty_generate(options)
35
+ puts "==============="
36
+ end
37
+
38
+ if !skip_to_json && !options[:body].nil?
39
+ options[:body] = Oj.dump(options[:body], mode: :json)
40
+ end
41
+ options.delete_if{|k,v| v.empty?}
42
+
43
+ begin
44
+ response = case action
45
+ when "GET"
46
+ HTTParty.get(send_url, options)
47
+ when "HEAD"
48
+ HTTParty.head(send_url, options)
49
+ when "PATCH"
50
+ HTTParty.patch(send_url, options)
51
+ when "POST"
52
+ HTTParty.post(send_url, options)
53
+ when "PUT"
54
+ HTTParty.put(send_url, options)
55
+ when "DELETE"
56
+ HTTParty.delete(send_url, options)
57
+ end
58
+ rescue Exception => e
59
+ raise Arango::Error.new err: :impossible_to_connect_with_database,
60
+ data: {"error": e.message}
61
+ end
62
+
63
+ if @verbose
64
+ puts "\n===RESPONSE==="
65
+ puts "CODE: #{response.code}"
66
+ end
67
+
68
+ case @async
69
+ when :store
70
+ val = response.headers["x-arango-async-id"]
71
+ if @verbose
72
+ puts val
73
+ puts "==============="
74
+ end
75
+ return val
76
+ when true
77
+ puts "===============" if @verbose
78
+ return true
79
+ end
80
+
81
+ if skip_parsing
82
+ val = response.parsed_response
83
+ if @verbose
84
+ puts val
85
+ puts "==============="
86
+ end
87
+ return val
88
+ end
89
+
90
+ begin
91
+ result = Oj.load(response.parsed_response, mode: :json, symbol_keys: true)
92
+ rescue Exception => e
93
+ raise Arango::Error.new err: :impossible_to_parse_arangodb_response,
94
+ data: {"response": response.parsed_response, "action": action, "url": send_url,
95
+ "request": JSON.pretty_generate(options)}
96
+ end
97
+
98
+ if @verbose
99
+ case result
100
+ when Hash, Array
101
+ puts JSON.pretty_generate(result)
102
+ else
103
+ puts "#{result}\n"
104
+ end
105
+ puts "==============="
106
+ end
107
+
108
+ case result
109
+ when Hash
110
+ if result[:error]
111
+ raise Arango::ErrorDB.new message: result[:errorMessage],
112
+ code: result[:code], data: result, errorNum: result[:errorNum],
113
+ action: action, url: send_url, request: options
114
+ elsif return_direct_result
115
+ return result
116
+ end
117
+ when Array, NilClass
118
+ return result
119
+ else
120
+ raise Arango::Error.new message: "ArangoRB didn't return a valid result",
121
+ data: {"response": response, "action": action, "url": send_url, "request": JSON.pretty_generate(options)}
122
+ end
123
+ return key.nil? ? result.delete_if{|k,v| k == :error || k == :code} : result[key]
124
+ end
125
+
126
+ def download(url:, path:, body: {}, headers: {}, query: {})
127
+ send_url = "#{@base_uri}/"
128
+ send_url += url
129
+ body.delete_if{|k,v| v.nil?}
130
+ query.delete_if{|k,v| v.nil?}
131
+ headers.delete_if{|k,v| v.nil?}
132
+ body = Oj.dump(body, mode: :json)
133
+ options = @options.merge({body: body, query: query, headers: headers, stream_body: true})
134
+ puts "\n#{action} #{send_url}\n" if @verbose
135
+ File.open(path, "w") do |file|
136
+ file.binmode
137
+ HTTParty.post(send_url, options) do |fragment|
138
+ file.write(fragment)
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end