arcadedb 0.3.1 → 0.4

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.
@@ -0,0 +1,194 @@
1
+ ##
2
+ ## This example realises a bidirectional 1:n relation using Edges & Vertices
3
+ #
4
+ ## The schema is implemented in modelfiles located in spec/model
5
+ ## /spec/models/ex/human.rb # Vertex
6
+ ## /spec/models/ex/depend_on.rb # Edge
7
+ #
8
+ # This script runs in the test environment.
9
+ ##
10
+ require 'bundler/setup'
11
+ require 'zeitwerk'
12
+ require 'arcade'
13
+
14
+ include Arcade
15
+ ## require modelfiles
16
+ loader = Zeitwerk::Loader.new
17
+ loader.push_dir ("#{__dir__}/../spec/model")
18
+ loader.setup
19
+
20
+ ## clear test database
21
+
22
+ databases = Arcade::Api.databases
23
+ if databases.include?(Arcade::Config.database[:test])
24
+ Arcade::Api.drop_database Arcade::Config.database[:test]
25
+ end
26
+ Arcade::Api.create_database Arcade::Config.database[:test]
27
+
28
+ ## Universal Database handle
29
+ DB = Arcade::Init.connect 'test'
30
+
31
+ ## ------------------------------------------------------ End Setup ------------------------------------- ##
32
+ ##
33
+ ## We are realising a self referencing relation
34
+ ## parent <--> children
35
+ #
36
+
37
+
38
+ Ex::Human.create_type # initialize the database
39
+ Ex::DependOn.create_type
40
+
41
+ nodes = %w( Guthorn Fulkerson Sniezek Tomasulo Portwine Keala Revelli Jacks Gorby Alcaoa ).map do | name |
42
+ Ex::Human.insert name: name, birth: 2022 - rand(99), married: rand(2)==1
43
+ end
44
+
45
+ puts Ex::Human.count.to_s + " Human Vertices created"
46
+
47
+ puts "------------------------------ get a sorted list of married humans ---------------------------------"
48
+ puts
49
+
50
+ merried = Ex::Human.query( where: { married: true })
51
+ merried.order 'birth'
52
+ new_merried = Query.new projection: 'name, 2022-birth as age ', from: merried # merge two queries
53
+ puts new_merried.query
54
+
55
+ puts "------------------------------ and one for not married humans ---------------------------------"
56
+ puts
57
+
58
+ singles = Ex::Human.query( where: { married: false })
59
+ singles.order 'birth'
60
+ new_singles = Query.new projection: 'name, 2022-birth as age ', from: singles # merge two queries
61
+ puts new_singles.query
62
+
63
+
64
+ puts "------------------------------ connect married humans with children ------------------------------"
65
+ children = singles.query.allocate_model
66
+
67
+ begin
68
+ children_enumerator = children.each
69
+ merried.query.allocate_model.map do | parent |
70
+ parent.assign via: Ex::DependOn, vertex: children_enumerator.next
71
+ end
72
+ rescue StopIteration
73
+ puts "No more children"
74
+ end
75
+
76
+ # Ex::Human.parents is essential
77
+ # EX::Human.query projection: 'out()' , whee: { married: true }
78
+ # Ex::Human.children is essential
79
+ # EX::Human.query projection: 'out()' , whee: { married: true }
80
+ puts "--------------------------- Parent and Children ---------------------------------------------------"
81
+ puts
82
+ puts "%10s %7s %10s %30s " % ["Parent", "Age", "Child", "sorted by Child"]
83
+ puts "- " * 50
84
+ Ex::Human.parents( order: 'name' ).each do |parent| # note: order: 'name' is included
85
+ # in the query
86
+ puts "%10s %7d %10s " % [parent.name, 2022 - parent.birth, parent.out.first.name]
87
+ end
88
+
89
+ puts "--------------------------- child and parent -----------------------------------------------------"
90
+ puts
91
+ puts "%10s %7s %10s %30s " % ["Child", "Age", "Parent", "sorted by Parent"]
92
+ puts "- " * 50
93
+ Ex::Human.children( order: 'name' ).each do |child|
94
+ puts "%10s %7d %10s " % [child.name, 2022 - child.birth, child.in.first.name]
95
+ end
96
+
97
+ puts "--------------------------- Add child to a parent -----------------------------------------------"
98
+ puts
99
+
100
+ Ex::Human.parents.first.assign via: Ex::DependOn, vertex: Ex::Human.insert( name: "TestBaby", birth: 2022, married: false)
101
+
102
+ puts "Parent: " + Ex::Human.parents.first.to_human
103
+ puts "Children: \n " + Ex::Human.parents.first.out.to_human.join("\n ")
104
+
105
+ ## Expected output
106
+ __END__
107
+
108
+ Using default database credentials and settings fron /home/ubuntu/workspace/arcadedb
109
+ 27.04.(18:35:05) INFO->Q: create vertex type ex_human
110
+ 27.04.(18:35:05) INFO->Q: CREATE PROPERTY ex_human.name STRING
111
+ 27.04.(18:35:05) INFO->Q: CREATE PROPERTY ex_human.married BOOLEAN
112
+ 27.04.(18:35:05) INFO->Q: CREATE INDEX `Example[human]` ON ex_human ( name ) UNIQUE
113
+ 27.04.(18:35:05) INFO->Q: create edge type ex_depend_on
114
+ 27.04.(18:35:05) INFO->Q: CREATE INDEX depends_out_in ON ex_depend_on (`@out`, `@in`) UNIQUE
115
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Guthorn","birth":1962,"married":false}
116
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Fulkerson","birth":1962,"married":true}
117
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Sniezek","birth":1972,"married":true}
118
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Tomasulo","birth":1953,"married":false}
119
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Portwine","birth":1975,"married":true}
120
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Keala","birth":1961,"married":false}
121
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Revelli","birth":1948,"married":true}
122
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Jacks","birth":1993,"married":true}
123
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Gorby","birth":1979,"married":false}
124
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"Alcaoa","birth":1960,"married":false}
125
+ 27.04.(18:35:05) INFO->Q: select count(*) from ex_human
126
+ 10 Human Vertices created
127
+ ------------------------------ get a sorted list of married humans ---------------------------------
128
+
129
+ 27.04.(18:35:05) INFO->Q: select name, 2022-birth as age from ( select from ex_human where married = true order by birth )
130
+ {:name=>"Revelli", :age=>74}
131
+ {:name=>"Fulkerson", :age=>60}
132
+ {:name=>"Sniezek", :age=>50}
133
+ {:name=>"Portwine", :age=>47}
134
+ {:name=>"Jacks", :age=>29}
135
+ ------------------------------ and one for not married humans ---------------------------------
136
+
137
+ 27.04.(18:35:05) INFO->Q: select name, 2022-birth as age from ( select from ex_human where married = false order by birth )
138
+ {:name=>"Tomasulo", :age=>69}
139
+ {:name=>"Alcaoa", :age=>62}
140
+ {:name=>"Keala", :age=>61}
141
+ {:name=>"Guthorn", :age=>60}
142
+ {:name=>"Gorby", :age=>43}
143
+ ------------------------------ connect married humans with children ------------------------------
144
+ 27.04.(18:35:05) INFO->Q: select from ex_human where married = false order by birth
145
+ 27.04.(18:35:05) INFO->Q: select from ex_human where married = true order by birth
146
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #19:0 to #10:0 CONTENT {"set":{}}
147
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #4:0 to #4:1 CONTENT {"set":{}}
148
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #7:0 to #16:0 CONTENT {"set":{}}
149
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #13:0 to #1:0 CONTENT {"set":{}}
150
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #22:0 to #1:1 CONTENT {"set":{}}
151
+ --------------------------- Parent and Children ---------------------------------------------------
152
+
153
+ Parent Age Child sorted by Child
154
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
155
+ 27.04.(18:35:05) INFO->Q: select in() from ex_human where married = false order by name
156
+ 27.04.(18:35:05) INFO->Q: select out() from #4:0
157
+ Fulkerson 60 Alcaoa
158
+ 27.04.(18:35:05) INFO->Q: select out() from #22:0
159
+ Jacks 29 Gorby
160
+ 27.04.(18:35:05) INFO->Q: select out() from #13:0
161
+ Portwine 47 Guthorn
162
+ 27.04.(18:35:05) INFO->Q: select out() from #7:0
163
+ Sniezek 50 Keala
164
+ 27.04.(18:35:05) INFO->Q: select out() from #19:0
165
+ Revelli 74 Tomasulo
166
+ --------------------------- child and parent -----------------------------------------------------
167
+
168
+ Child Age Parent sorted by Parent
169
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
170
+ 27.04.(18:35:05) INFO->Q: select out() from ex_human where married = true order by name
171
+ 27.04.(18:35:05) INFO->Q: select in() from #4:1
172
+ Alcaoa 62 Fulkerson
173
+ 27.04.(18:35:05) INFO->Q: select in() from #1:1
174
+ Gorby 43 Jacks
175
+ 27.04.(18:35:05) INFO->Q: select in() from #1:0
176
+ Guthorn 60 Portwine
177
+ 27.04.(18:35:05) INFO->Q: select in() from #10:0
178
+ Tomasulo 69 Revelli
179
+ 27.04.(18:35:05) INFO->Q: select in() from #16:0
180
+ Keala 61 Sniezek
181
+ --------------------------- Add child to a parent -----------------------------------------------
182
+
183
+ 27.04.(18:35:05) INFO->Q: select in() from ex_human where married = false
184
+ 27.04.(18:35:05) INFO->Q: INSERT INTO ex_human CONTENT {"name":"TestBaby","birth":2022,"married":false}
185
+ 27.04.(18:35:05) INFO->Q: create edge ex_depend_on from #13:0 to #7:1 CONTENT {"set":{}}
186
+ 27.04.(18:35:05) INFO->Q: select in() from ex_human where married = false
187
+ Parent: <ex_human[#13:0]: {0->}{->2}}, birth: 1975, married: true, name: Portwine>
188
+ 27.04.(18:35:05) INFO->Q: select in() from ex_human where married = false
189
+ 27.04.(18:35:05) INFO->Q: select out() from #13:0
190
+ Children:
191
+ <ex_human[#1:0]: {->}{->}}, birth: 1962, married: false, name: Guthorn>
192
+ <ex_human[#7:1]: {->}{->}}, birth: 2022, married: false, name: TestBaby>
193
+
194
+
@@ -0,0 +1,257 @@
1
+ module Arcade
2
+ module Api
3
+ extend Primitives
4
+ =begin
5
+ This is a simple admin interface
6
+
7
+ $ Arcade::Api.databases # returns an Array of known databases
8
+ $ Arcade::Api.create_database <a string> # returns true if succesfull
9
+ $ Arcade::Api.drop_database <a string> # returns true if successfull
10
+
11
+ $ Arcade::Api.create_document <database>, <type>, attributes
12
+ $ Arcade::Api.execute( <database> ) { <query> }
13
+ $ Arcade::Api.query( <database> ) { <query> }
14
+ $ Arcade::Api.get_record <database>, rid # returns a hash
15
+
16
+
17
+ <query> is either a string
18
+ or a hash { :query => " ",
19
+ :language => one of :sql, :cypher, :gmelion: :neo4j ,
20
+ :params => a hash of parameters,
21
+ :limit => a number ,
22
+ :serializer: one of :graph, :record }
23
+
24
+ =end
25
+
26
+ # ------------------------------ Service methods ------------------------------------------------- #
27
+ # ------------------------------ ------------------------------------------------- #
28
+ # ------------------------------ databases ------------------------------------------------- #
29
+ # returns an array of databases present on the database-server #
30
+
31
+ def self.databases
32
+ get_data 'databases'
33
+ end
34
+
35
+ # ------------------------------ create database ------------------------------------------------- #
36
+ # creates a database if not present #
37
+ def self.create_database name
38
+ return if databases.include?( name.to_s )
39
+ payload = { "command" => "create database #{name}" }
40
+ post_data "server", payload
41
+ rescue HTTPX::HTTPError => e
42
+ logger.fatal "Create database #{name} through \"POST create/#{name}\" failed"
43
+ logger.fatal e
44
+ raise
45
+ end
46
+
47
+ # ------------------------------ drop database ------------------------------------------------- #
48
+ # deletes the given database #
49
+ def self.drop_database name
50
+ return unless databases.include?( name.to_s )
51
+ payload = {"command" => "drop database #{name}" }
52
+ post_data "server", payload
53
+ rescue HTTPX::HTTPError => e
54
+ logger.fatal "Drop database #{name} through \"POST drop database/#{name}\" failed"
55
+ raise
56
+ end
57
+ # ------------------------------ create document ------------------------------------------------- #
58
+ # adds a document to the specified database table
59
+ #
60
+ # specify database-fields as hash-type parameters
61
+ #
62
+ # i.e Arcade::Api.create_document 'devel', 'documents', name: 'herta meyer', age: 56, sex: 'f'
63
+ #
64
+ # returns the rid of the inserted dataset
65
+ #
66
+ def self.create_document database, type, **attributes
67
+ payload = { "@type" => type }.merge( attributes )
68
+ logger.debug "C: #{payload}"
69
+ options = if session.nil?
70
+ payload
71
+ else
72
+ payload.merge headers: { "arcadedb-session-id" => session }
73
+ end
74
+ post_data "document/#{database}", options
75
+ end
76
+
77
+ # ------------------------------ execute ------------------------------------------------- #
78
+ # executes a sql-query in the specified database
79
+ #
80
+ # the query is provided as block
81
+ #
82
+ # returns an Array of results (if propriate)
83
+ # i.e
84
+ # Arcade::Api.execute( "devel" ) { 'select from test ' }
85
+ # =y [{"@rid"=>"#57:0", "@type"=>"test", "name"=>"Hugo"}, {"@rid"=>"#60:0", "@type"=>"test", "name"=>"Hubert"}]
86
+ #
87
+ def self.execute database, query=nil, session_id= nil
88
+ pl = query.nil? ? provide_payload(yield) : provide_payload(query)
89
+ if session_id.nil? && session.nil?
90
+ post_data "command/#{database}" , pl
91
+ else
92
+ post_transaction "command/#{database}" , pl, session_id || session
93
+ end
94
+ end
95
+
96
+ # ------------------------------ query ------------------------------------------------- #
97
+ # same for idempotent queries
98
+ def self.query database, query
99
+ post_data "query/#{database}" , provide_payload(query)
100
+ end
101
+
102
+ # ------------------------------ get_record ------------------------------------------------- #
103
+ # fetches a record by providing database and rid
104
+ # and returns the result as hash
105
+ #
106
+ # > Api.get_record 'devel', '225:6'
107
+ # > Api.get_record 'devel', 225, 6
108
+ # > Api.get_record 'devel', '#225:6'
109
+ # => {:@out=>0, :@rid=>"#225:6", :@in=>0, :@type=>"my_names", :name=>"Zaber", :@cat=>"v"}
110
+
111
+ def self.get_record database, *rid
112
+ rid = rid.join(':')
113
+ rid = rid[1..-1] if rid[0]=="#"
114
+ if rid.rid?
115
+ get_data "document/#{database}/#{rid}"
116
+ else
117
+ raise Error "Get requires a rid input"
118
+ end
119
+ end
120
+
121
+ # ------------------------------ property ------------------------------------------------- #
122
+ # Adds properties to the type
123
+ #
124
+ # call via
125
+ # Api.property <database>, <type>, name1: a_format , name2: a_format
126
+ #
127
+ # Format is one of
128
+ # Boolean, Integer, Short, Long, Float, Double, String
129
+ # Datetime, Binary, Byte, Decimal, Link
130
+ # Embedded, EmbeddedList, EmbeddedMap
131
+ #
132
+ # In case of an Error, anything is rolled back and nil is returned
133
+ #
134
+ def self.property database, type, **args
135
+
136
+ begin_transaction database
137
+ success = args.map do | name, format |
138
+ r= execute(database) {" create property #{type.to_s}.#{name.to_s} #{format.to_s} " } &.first
139
+ puts "R: #{r.inspect}"
140
+ if r.nil?
141
+ false
142
+ else
143
+ r[:operation] == 'create property'
144
+ end
145
+ end.uniq
146
+ if success == [true]
147
+ commit database
148
+ true
149
+ else
150
+ rollback database
151
+ end
152
+
153
+
154
+ end
155
+
156
+ # ------------------------------ index ------------------------------------------------- #
157
+ def self.index database, type, name , *properties
158
+ properties = properties.map( &:to_s )
159
+ unique_requested = "unique" if properties.delete("unique")
160
+ unique_requested = "notunique" if properties.delete("notunique" )
161
+ automatic = true if
162
+ properties << name if properties.empty?
163
+ # puts " create index #{type.to_s}[#{name.to_s}] on #{type} ( #{properties.join(',')} ) #{unique_requested}"
164
+ # VV 22.10: providing an index-name raises an Error ( Encountered " "(" "( "" at line 1, column 44. Was expecting one of: <EOF> <SCHEMA> ... <NULL_STRATEGY> ... ";" ... "," ... )) )
165
+ # named indices droped for now
166
+ success = execute(database) {" create index IF NOT EXISTS on #{type} (#{properties.join(', ')}) #{unique_requested}" } &.first
167
+ # puts "success: #{success}"
168
+ success[:operation] == 'create index'
169
+
170
+ end
171
+
172
+
173
+ private
174
+
175
+ def self.logger
176
+ Database.logger
177
+ end
178
+
179
+ def self.session
180
+ @session_id
181
+ end
182
+
183
+ def self. provide_payload( the_yield, action: :post )
184
+ unless the_yield.is_a? Hash
185
+ logger.info "Q: #{the_yield}"
186
+ the_yield = { :query => the_yield }
187
+ end
188
+ { language: 'sql' }.merge(
189
+ the_yield.map do | key, value |
190
+ case key
191
+ when :query
192
+ action == :post ? [ :command, value ] : [ :query, value ]
193
+ when :limit
194
+ [ :limit , value ]
195
+ when :params
196
+ if value.is_a? Hash
197
+ [ :params, value ]
198
+ end
199
+ # serializer (optional) specify the serializer used for the result:
200
+ # graph: returns as a graph separating vertices from edges
201
+ # record: returns everything as records
202
+ # by default it’s like record but with additional metadata for vertex records,
203
+ # such as the number of outgoing edges in @out property and total incoming edges
204
+ # in @in property. This serialzier is used by Studio
205
+ when :serializer
206
+ if [:graph, :record].include? value.to_sym
207
+ [ :serializer, value.to_sym ]
208
+ end
209
+ when :language
210
+ if [:sql, :cypher, :gremlin, :neo4j ].include? value.to_sym
211
+ [ :language, value.to_sym ]
212
+ end
213
+ end # case
214
+ end .to_h ) # map
215
+ end
216
+
217
+
218
+
219
+ # returns the json-response ## retiered
220
+ def self.analyse_result r, command
221
+ if r.success?
222
+ return nil if r.status == 204 # no content
223
+ result = JSON.parse( r.response_body, symbolize_names: true )[:result]
224
+ if result == [{}]
225
+ []
226
+ else
227
+ result
228
+ end
229
+ elsif r.timed_out?
230
+ raise Error "Timeout Error", caller
231
+ []
232
+ elsif r.response_code > 0
233
+ logger.error "Execution Failure – Code: #{ r.response_code } – #{r.status_message} "
234
+ error_message = JSON.parse( r.response_body, symbolize_names: true )
235
+ logger.error "ErrorMessage: #{ error_message[:detail]} "
236
+ if error_message[:detail] =~ /Duplicated key/
237
+ raise IndexError, error_message[:detail]
238
+ else
239
+ # available fields: :detail, :exception, error
240
+ puts error_message[:detail]
241
+ #raise error_message[:detail], caller
242
+ end
243
+ end
244
+ end
245
+ def self.auth
246
+ @a ||= { httpauth: :basic,
247
+ username: Config.admin[:user],
248
+ password: Config.admin[:pass] }
249
+ end
250
+
251
+ # not tested
252
+ def self.delete_data command
253
+ result = HTTPX.delete Config.base_uri + command, auth
254
+ analyse_result(result, command)
255
+ end
256
+ end
257
+ end
@@ -0,0 +1,98 @@
1
+ module Arcade
2
+ module Api
3
+ module Primitives
4
+
5
+ # This module handles the interaction with the database through HTTPX
6
+ #
7
+ # ------------------------------ http ------------------------------------------------------------ #
8
+ # persistent http handle to the database
9
+
10
+ def http
11
+ break_on = -> (response) { response.status == 500 }
12
+ @http ||= HTTPX.plugin(:basic_auth).basic_auth(auth[:username], auth[:password])
13
+ .plugin(:persistent)
14
+ .plugin(:circuit_breaker)
15
+ # .plugin(:circuit_breaker, circuit_breaker_break_on: break_on)
16
+ end
17
+
18
+ # ------------------------------ get data -------------------------------------------------------- #
19
+ def get_data command
20
+ response = http.get( Config.base_uri + command )
21
+ response.raise_for_status
22
+
23
+ JSON.parse( response.body, symbolize_names: true )[:result]
24
+ # alternative to `raise for status `
25
+ # case response = http.basic_auth(auth[:username], auth[:password]).get( Config.base_uri + command )
26
+ # in { status: 200..203, body: }
27
+ # puts "success: #{JSON.parse(body, symbolize_names: true)[:result]}"
28
+ # in { status: 400..499, body: }
29
+ # puts "client error: #{body.json}"
30
+ # in { status: 500.., body: }
31
+ # puts "server error: #{body.to_s}"
32
+ # in { error: error }
33
+ # puts "error: #{error.message}"
34
+ # else
35
+ # raise "unexpected: #{response}"
36
+ # end
37
+ # puts "result : #{response}"
38
+ # puts "code: #{response.status}"
39
+ # analyse_result(response, command)
40
+ end
41
+
42
+ # ------------------------------ post data -------------------------------------------------------- #
43
+ def post_data command, payload
44
+ # http = HTTPX.plugin(:basic_auth)
45
+ # .basic_auth(auth[:username], auth[:password])
46
+ response = http.post( Config.base_uri + command, json: payload )
47
+ response.raise_for_status
48
+ JSON.parse( response.body, symbolize_names: true )[:result]
49
+ end
50
+
51
+ # ------------------------------ transaction ------------------------------------------------- #
52
+ #
53
+ def begin_transaction database
54
+ result = http.post Config.base_uri + "begin/#{database}"
55
+ @session_id = result.headers["arcadedb-session-id"]
56
+ # returns the session-id
57
+ end
58
+
59
+ # ------------------------------ post transaction ------------------------------------------------- #
60
+ def post_transaction command, params, session_id= @session_id
61
+ # http = HTTPX.plugin(:basic_auth)
62
+ # .basic_auth(auth[:username], auth[:password])
63
+ # .with( headers: { "arcadedb-session-id"=>session }, debug_level: 1)
64
+ http_a = http.with( headers: { "arcadedb-session-id" => session_id } , debug_level: 1)
65
+ response = http_a.post( Config.base_uri + command, json: params )
66
+ response.raise_for_status
67
+ JSON.parse( response.body, symbolize_names: true )[:result]
68
+
69
+ end
70
+
71
+ # ------------------------------ commit ------------------------------------------------- #
72
+ def commit database, session_id = @session_id
73
+ http_a = http.with( headers: { "arcadedb-session-id" => session_id } , debug_level: 1)
74
+ response = http_a.post( Config.base_uri + "commit/#{database}" )
75
+ response.raise_for_status
76
+ @session_id = nil
77
+ response.status # returns 204 --> success
78
+ # 403 --> incalid credentials
79
+ # 500 --> Transaction not begun
80
+
81
+ end
82
+
83
+ # ------------------------------ rollback ------------------------------------------------- #
84
+ def rollback database, session_id = @session_id, publish_error=true
85
+ # http = HTTPX.plugin(:basic_auth)
86
+ # .basic_auth(auth[:username], auth[:password])
87
+ # .with( headers: { "arcadedb-session-id"=>session_id }, debug_level: 1)
88
+ http_a = http.with( headers: { "arcadedb-session-id" => session_id } , debug_level: 1)
89
+ response = http_a.post( Config.base_uri + "rollback/#{database}" )
90
+ response.raise_for_status
91
+ @session_id = nil
92
+ logger.error "A Transaction has been rolled back" # if publish_error
93
+ response.status
94
+ end
95
+ end
96
+ end
97
+ end
98
+