arcadedb 0.3.3 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e052fea79d83b5cd35961dcc01af0ba617e80c3e0c26d058c5b69a3733a8edc
4
- data.tar.gz: 92ef4c2900fee458959b01becf8fc2789fce5e87fb39e1cfc25b0f0df1e08d20
3
+ metadata.gz: 1855060886e9837ef486e44f07155ae99cd242f76aceccb8a7bf4c2ab515eca0
4
+ data.tar.gz: d99f2a402eba561fcf851a3838b3bec7eee58f1a788ab9fc7e2ce1208c33611a
5
5
  SHA512:
6
- metadata.gz: f74869fa3afe8f87250e94358b2b18a1fdcfdfa092ec0ef5a0293f970f1976b755463f070f0224aa276f4df3acd5555500d800b389c8463889347f8ef2d10ee7
7
- data.tar.gz: a16c82bf62d9e30898de4e439a7fca37f470944cb92293fa11e4847146eac3a5c066447c1293d3fc73d1a078b348bdcdac21b44b10308ba9c10f141d793f17e2
6
+ metadata.gz: 78936dfe0069d531c1bcfd6191f0269ed84a44cd8e0321a37ef9d569048ff8a20d38d0a221d0b0b93f3e64f39d61a758d2978545beec86d27baf5836c3cdbf4a
7
+ data.tar.gz: 6ff4e9242c74887935074ed60810b144a08ad2dad7a6d3374bc0216f74873abb6a1b6f66428a2ed6e7fa9f49dec3ee07ebbe5cc64488744829f76eb037db286c
data/CHANGELOG.md CHANGED
@@ -12,4 +12,8 @@ All notable changes to this project will be documented in this file.
12
12
  - Support for embedded Dokuments and Maps
13
13
  - iruby support
14
14
 
15
+ ## 0.4.0 - 2023.10.28
16
+ - completely remove pg-stuff
17
+ - substitute typhoreous with HTTPX
18
+ - include dry::monards to process raw-data
15
19
 
data/Gemfile CHANGED
@@ -5,17 +5,12 @@ source "https://rubygems.org"
5
5
  #git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
6
6
  gemspec
7
7
  gem 'sdoc'
8
- gem 'dry-configurable'
9
- gem 'pry'
10
- #gem 'sequel'
11
-
12
- #gem 'mini_sql' #, path: '../mini_sql/'
13
8
  group :development, :test do
14
9
  gem "awesome_print"
15
10
  gem 'pastel'
16
11
  gem 'zeitwerk'
17
12
  gem 'terminal-table'
18
- gem 'rubocop'
13
+ # gem 'rubocop'
19
14
  gem "rspec"
20
15
  gem 'rspec-legacy_formatters'
21
16
  gem 'rspec-its'
@@ -26,5 +21,5 @@ group :development, :test do
26
21
  gem 'guard'#, :platforms => :ruby
27
22
  gem 'guard-rspec'
28
23
  gem 'rb-inotify'
29
- gem 'pry'
24
+ # gem 'pry'
30
25
  end
data/Gemfile.lock CHANGED
@@ -1,56 +1,63 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- arcadedb (0.3.2)
4
+ arcadedb (0.4)
5
+ dry-configurable
5
6
  dry-core
7
+ dry-monads
6
8
  dry-schema
7
9
  dry-struct
8
- typhoeus
10
+ httpx
9
11
 
10
12
  GEM
11
13
  remote: https://rubygems.org/
12
14
  specs:
13
15
  ast (2.4.2)
14
16
  awesome_print (1.9.2)
17
+ base64 (0.1.1)
15
18
  coderay (1.1.3)
16
- concurrent-ruby (1.1.10)
19
+ concurrent-ruby (1.2.2)
17
20
  diff-lcs (1.5.0)
18
- dry-configurable (0.15.0)
21
+ dry-configurable (1.1.0)
22
+ dry-core (~> 1.0, < 2)
23
+ zeitwerk (~> 2.6)
24
+ dry-core (1.0.1)
19
25
  concurrent-ruby (~> 1.0)
20
- dry-core (~> 0.6)
21
- dry-container (0.11.0)
22
- concurrent-ruby (~> 1.0)
23
- dry-core (0.7.1)
24
- concurrent-ruby (~> 1.0)
25
- dry-inflector (0.3.0)
26
+ zeitwerk (~> 2.6)
27
+ dry-inflector (1.0.0)
26
28
  dry-initializer (3.1.1)
27
- dry-logic (1.2.0)
29
+ dry-logic (1.5.0)
30
+ concurrent-ruby (~> 1.0)
31
+ dry-core (~> 1.0, < 2)
32
+ zeitwerk (~> 2.6)
33
+ dry-monads (1.6.0)
28
34
  concurrent-ruby (~> 1.0)
29
- dry-core (~> 0.5, >= 0.5)
30
- dry-schema (1.10.6)
35
+ dry-core (~> 1.0, < 2)
36
+ zeitwerk (~> 2.6)
37
+ dry-schema (1.13.3)
31
38
  concurrent-ruby (~> 1.0)
32
- dry-configurable (~> 0.13, >= 0.13.0)
33
- dry-core (~> 0.5, >= 0.5)
39
+ dry-configurable (~> 1.0, >= 1.0.1)
40
+ dry-core (~> 1.0, < 2)
34
41
  dry-initializer (~> 3.0)
35
- dry-logic (~> 1.2)
36
- dry-types (~> 1.5)
37
- dry-struct (1.4.0)
38
- dry-core (~> 0.5, >= 0.5)
39
- dry-types (~> 1.5)
42
+ dry-logic (>= 1.4, < 2)
43
+ dry-types (>= 1.7, < 2)
44
+ zeitwerk (~> 2.6)
45
+ dry-struct (1.6.0)
46
+ dry-core (~> 1.0, < 2)
47
+ dry-types (>= 1.7, < 2)
40
48
  ice_nine (~> 0.11)
41
- dry-types (1.5.1)
49
+ zeitwerk (~> 2.6)
50
+ dry-types (1.7.1)
42
51
  concurrent-ruby (~> 1.0)
43
- dry-container (~> 0.3)
44
- dry-core (~> 0.5, >= 0.5)
45
- dry-inflector (~> 0.1, >= 0.1.2)
46
- dry-logic (~> 1.0, >= 1.0.2)
47
- ethon (0.16.0)
48
- ffi (>= 1.15.0)
49
- ffi (1.15.5)
52
+ dry-core (~> 1.0)
53
+ dry-inflector (~> 1.0)
54
+ dry-logic (~> 1.4)
55
+ zeitwerk (~> 2.6)
56
+ ffi (1.16.3)
50
57
  formatador (1.1.0)
51
58
  given_core (3.8.2)
52
59
  sorcerer (>= 0.3.7)
53
- guard (2.18.0)
60
+ guard (2.18.1)
54
61
  formatador (>= 0.2.4)
55
62
  listen (>= 2.7, < 4.0)
56
63
  lumberjack (>= 1.0.12, < 2.0)
@@ -64,44 +71,54 @@ GEM
64
71
  guard (~> 2.1)
65
72
  guard-compat (~> 1.1)
66
73
  rspec (>= 2.99.0, < 4.0)
74
+ http-2-next (1.0.1)
75
+ httpx (1.0.2)
76
+ http-2-next (>= 1.0.1)
67
77
  ice_nine (0.11.2)
68
- listen (3.7.1)
78
+ json (2.6.3)
79
+ language_server-protocol (3.17.0.3)
80
+ listen (3.8.0)
69
81
  rb-fsevent (~> 0.10, >= 0.10.3)
70
82
  rb-inotify (~> 0.9, >= 0.9.10)
71
- lumberjack (1.2.8)
83
+ lumberjack (1.2.9)
72
84
  method_source (1.0.0)
73
85
  nenv (0.3.0)
74
86
  notiffany (0.1.3)
75
87
  nenv (~> 0.1)
76
88
  shellany (~> 0.0)
77
- parallel (1.22.1)
78
- parser (3.1.2.0)
89
+ parallel (1.23.0)
90
+ parser (3.2.2.4)
79
91
  ast (~> 2.4.1)
92
+ racc
80
93
  pastel (0.8.0)
81
94
  tty-color (~> 0.5)
82
- pry (0.14.1)
95
+ pry (0.14.2)
83
96
  coderay (~> 1.1)
84
97
  method_source (~> 1.0)
98
+ psych (5.1.1.1)
99
+ stringio
100
+ racc (1.7.1)
85
101
  rainbow (3.1.1)
86
102
  rake (13.0.6)
87
- rb-fsevent (0.11.1)
103
+ rb-fsevent (0.11.2)
88
104
  rb-inotify (0.10.1)
89
105
  ffi (~> 1.0)
90
- rdoc (6.3.3)
91
- regexp_parser (2.4.0)
92
- rexml (3.2.5)
93
- rspec (3.11.0)
94
- rspec-core (~> 3.11.0)
95
- rspec-expectations (~> 3.11.0)
96
- rspec-mocks (~> 3.11.0)
97
- rspec-collection_matchers (1.2.0)
106
+ rdoc (6.5.0)
107
+ psych (>= 4.0.0)
108
+ regexp_parser (2.8.2)
109
+ rexml (3.2.6)
110
+ rspec (3.12.0)
111
+ rspec-core (~> 3.12.0)
112
+ rspec-expectations (~> 3.12.0)
113
+ rspec-mocks (~> 3.12.0)
114
+ rspec-collection_matchers (1.2.1)
98
115
  rspec-expectations (>= 2.99.0.beta1)
99
116
  rspec-context-private (0.0.1)
100
- rspec-core (3.11.0)
101
- rspec-support (~> 3.11.0)
102
- rspec-expectations (3.11.0)
117
+ rspec-core (3.12.2)
118
+ rspec-support (~> 3.12.0)
119
+ rspec-expectations (3.12.3)
103
120
  diff-lcs (>= 1.2.0, < 2.0)
104
- rspec-support (~> 3.11.0)
121
+ rspec-support (~> 3.12.0)
105
122
  rspec-given (3.8.2)
106
123
  given_core (= 3.8.2)
107
124
  rspec (>= 2.14.0)
@@ -110,34 +127,36 @@ GEM
110
127
  rspec-expectations (>= 3.0.0)
111
128
  rspec-legacy_formatters (1.0.2)
112
129
  rspec (~> 3.0)
113
- rspec-mocks (3.11.1)
130
+ rspec-mocks (3.12.6)
114
131
  diff-lcs (>= 1.2.0, < 2.0)
115
- rspec-support (~> 3.11.0)
116
- rspec-support (3.11.0)
117
- rubocop (1.29.1)
132
+ rspec-support (~> 3.12.0)
133
+ rspec-support (3.12.1)
134
+ rubocop (1.57.1)
135
+ base64 (~> 0.1.1)
136
+ json (~> 2.3)
137
+ language_server-protocol (>= 3.17.0)
118
138
  parallel (~> 1.10)
119
- parser (>= 3.1.0.0)
139
+ parser (>= 3.2.2.4)
120
140
  rainbow (>= 2.2.2, < 4.0)
121
141
  regexp_parser (>= 1.8, < 3.0)
122
142
  rexml (>= 3.2.5, < 4.0)
123
- rubocop-ast (>= 1.17.0, < 2.0)
143
+ rubocop-ast (>= 1.28.1, < 2.0)
124
144
  ruby-progressbar (~> 1.7)
125
- unicode-display_width (>= 1.4.0, < 3.0)
126
- rubocop-ast (1.18.0)
127
- parser (>= 3.1.1.0)
128
- ruby-progressbar (1.11.0)
129
- sdoc (2.3.1)
130
- rdoc (>= 5.0, < 6.4.0)
145
+ unicode-display_width (>= 2.4.0, < 3.0)
146
+ rubocop-ast (1.29.0)
147
+ parser (>= 3.2.1.0)
148
+ ruby-progressbar (1.13.0)
149
+ sdoc (2.6.1)
150
+ rdoc (>= 5.0)
131
151
  shellany (0.0.1)
132
152
  sorcerer (2.0.1)
153
+ stringio (3.0.8)
133
154
  terminal-table (3.0.2)
134
155
  unicode-display_width (>= 1.1.1, < 3)
135
- thor (1.2.1)
156
+ thor (1.3.0)
136
157
  tty-color (0.6.0)
137
- typhoeus (1.4.0)
138
- ethon (>= 0.9.0)
139
- unicode-display_width (2.1.0)
140
- zeitwerk (2.5.4)
158
+ unicode-display_width (2.5.0)
159
+ zeitwerk (2.6.12)
141
160
 
142
161
  PLATFORMS
143
162
  x86_64-linux
@@ -146,7 +165,6 @@ DEPENDENCIES
146
165
  arcadedb!
147
166
  awesome_print
148
167
  bundler (~> 2)
149
- dry-configurable
150
168
  guard
151
169
  guard-rspec
152
170
  pastel
data/arcade.yml CHANGED
@@ -1,8 +1,4 @@
1
1
  ---
2
- ## absolute path to the oetl-script
3
- :pg:
4
- :host: 10.247.8.109 # hierdevel
5
- :port: 5432
6
2
  :environment:
7
3
  :test:
8
4
  dbname: playground
data/arcadedb.gemspec CHANGED
@@ -23,13 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 2"
24
24
  spec.add_development_dependency "rake", "~> 13.0"
25
25
  spec.add_development_dependency "rspec", "~> 4.0"
26
- # 'activesupport', '>= 6.0'
27
- # spec.add_dependency 'activemodel'
28
- spec.add_dependency "typhoeus"
26
+ spec.add_dependency "httpx"
29
27
  spec.add_dependency 'dry-schema'
30
28
  spec.add_dependency 'dry-struct'
31
29
  spec.add_dependency 'dry-core'
32
- ## Database-Access via Postgres is not implemented
33
- # spec.add_dependency 'pg'
34
- # spec.add_dependency 'mini_sql'
30
+ spec.add_dependency 'dry-configurable'
31
+ # spec.add_dependency 'dry-monads' # future use
35
32
  end
data/bin/console CHANGED
@@ -11,7 +11,7 @@ require 'terminal-table'
11
11
  require 'zeitwerk'
12
12
  require 'pastel'
13
13
  require 'arcade'
14
- require 'pry'
14
+ #require 'pry'
15
15
  #begin
16
16
 
17
17
 
@@ -118,9 +118,9 @@ DB = Arcade::Init.connect e
118
118
  require 'irb'
119
119
  ARGV.clear
120
120
  #begin
121
- #IRB.start(__FILE__)
121
+ IRB.start(__FILE__)
122
122
  #rescue ArgumentError => e
123
123
  # puts e
124
124
  ## retry
125
125
  #end
126
- Pry.start(__FILE__)
126
+ #Pry.start(__FILE__)
@@ -1,5 +1,6 @@
1
1
  module Arcade
2
2
  module Api
3
+ extend Primitives
3
4
  =begin
4
5
  This is a simple admin interface
5
6
 
@@ -22,44 +23,53 @@ module Arcade
22
23
 
23
24
  =end
24
25
 
26
+ # ------------------------------ Service methods ------------------------------------------------- #
27
+ # ------------------------------ ------------------------------------------------- #
28
+ # ------------------------------ databases ------------------------------------------------- #
29
+ # returns an array of databases present on the database-server #
25
30
 
26
31
  def self.databases
27
32
  get_data 'databases'
28
33
  end
29
34
 
35
+ # ------------------------------ create database ------------------------------------------------- #
36
+ # creates a database if not present #
30
37
  def self.create_database name
31
- unless databases.include?( name.to_s )
32
- payload = { "command" => "create database #{name}" }.to_json
33
- post_data "server", { body: payload }.merge( auth ).merge( json )
34
- end
35
- rescue QueryError => e
38
+ return if databases.include?( name.to_s )
39
+ payload = { "command" => "create database #{name}" }
40
+ post_data "server", payload
41
+ rescue HTTPX::HTTPError => e
36
42
  logger.fatal "Create database #{name} through \"POST create/#{name}\" failed"
37
43
  logger.fatal e
38
44
  raise
39
45
  end
40
46
 
47
+ # ------------------------------ drop database ------------------------------------------------- #
48
+ # deletes the given database #
41
49
  def self.drop_database name
42
- if databases.include?( name.to_s )
43
- payload = { "command" => "drop database #{name}" }.to_json
44
- post_data "server", { body: payload }.merge( auth ).merge( json )
45
- end
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
46
56
  end
47
57
  # ------------------------------ create document ------------------------------------------------- #
48
- # adds a document to the database
58
+ # adds a document to the specified database table
49
59
  #
50
60
  # specify database-fields as hash-type parameters
51
61
  #
52
62
  # i.e Arcade::Api.create_document 'devel', 'documents', name: 'herta meyer', age: 56, sex: 'f'
53
63
  #
54
64
  # returns the rid of the inserted dataset
55
- #
65
+ #
56
66
  def self.create_document database, type, **attributes
57
- payload = { "@type" => type }.merge( attributes ).to_json
67
+ payload = { "@type" => type }.merge( attributes )
58
68
  logger.debug "C: #{payload}"
59
69
  options = if session.nil?
60
- { body: payload }.merge( auth ).merge( json )
70
+ payload
61
71
  else
62
- { body: payload }.merge( auth ).merge( json ).merge( headers: { "arcadedb-session-id" => session })
72
+ payload.merge headers: { "arcadedb-session-id" => session }
63
73
  end
64
74
  post_data "document/#{database}", options
65
75
  end
@@ -71,32 +81,22 @@ module Arcade
71
81
  #
72
82
  # returns an Array of results (if propriate)
73
83
  # i.e
74
- # Arcade::Api.execcute( "devel" ) { 'select from test ' }
84
+ # Arcade::Api.execute( "devel" ) { 'select from test ' }
75
85
  # =y [{"@rid"=>"#57:0", "@type"=>"test", "name"=>"Hugo"}, {"@rid"=>"#60:0", "@type"=>"test", "name"=>"Hubert"}]
76
86
  #
77
- def self.execute database, query=nil
87
+ def self.execute database, query=nil, session_id= nil
78
88
  pl = query.nil? ? provide_payload(yield) : provide_payload(query)
79
- options = { body: pl }.merge( auth ).merge( json )
80
- unless session.nil?
81
- options = options.merge( headers: { "arcadedb-session-id" => session })
89
+ if session_id.nil? && session.nil?
90
+ post_data "command/#{database}" , pl
91
+ else
92
+ post_transaction "command/#{database}" , pl, session_id || session
82
93
  end
83
- post_data "command/#{database}" , options
84
- rescue Arcade::QueryError => e
85
- # puts e.methods
86
- #puts e.exception
87
- # puts e.full_message
88
- if e.message =~ /retry/
89
- retry
90
- else
91
- raise e.message
92
- end
93
94
  end
94
95
 
95
96
  # ------------------------------ query ------------------------------------------------- #
96
97
  # same for idempotent queries
97
98
  def self.query database, query
98
- options = { body: provide_payload(query) }.merge( auth ).merge( json )
99
- post_data "query/#{database}" , options
99
+ post_data "query/#{database}" , provide_payload(query)
100
100
  end
101
101
 
102
102
  # ------------------------------ get_record ------------------------------------------------- #
@@ -114,7 +114,7 @@ module Arcade
114
114
  if rid.rid?
115
115
  get_data "document/#{database}/#{rid}"
116
116
  else
117
- raise Arcade::Error "Get requires a rid input"
117
+ raise Error "Get requires a rid input"
118
118
  end
119
119
  end
120
120
 
@@ -136,10 +136,11 @@ module Arcade
136
136
  begin_transaction database
137
137
  success = args.map do | name, format |
138
138
  r= execute(database) {" create property #{type.to_s}.#{name.to_s} #{format.to_s} " } &.first
139
+ puts "R: #{r.inspect}"
139
140
  if r.nil?
140
141
  false
141
142
  else
142
- r.keys == [ :propertyName, :typeName, :operation ] && r[:operation] == 'create property'
143
+ r[:operation] == 'create property'
143
144
  end
144
145
  end.uniq
145
146
  if success == [true]
@@ -155,45 +156,20 @@ module Arcade
155
156
  # ------------------------------ index ------------------------------------------------- #
156
157
  def self.index database, type, name , *properties
157
158
  properties = properties.map( &:to_s )
158
- unique_requested = "unique" if properties.delete("unique")
159
+ unique_requested = "unique" if properties.delete("unique")
159
160
  unique_requested = "notunique" if properties.delete("notunique" )
160
161
  automatic = true if
161
162
  properties << name if properties.empty?
162
- # puts " create index #{type.to_s}[#{name.to_s}] on #{type} ( #{properties.join(',')} ) #{unique_requested}"
163
+ # puts " create index #{type.to_s}[#{name.to_s}] on #{type} ( #{properties.join(',')} ) #{unique_requested}"
163
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> ... ";" ... "," ... )) )
164
165
  # named indices droped for now
165
- success = execute(database) {" create index on #{type} ( #{properties.join(',')} ) #{unique_requested}" } &.first
166
+ success = execute(database) {" create index IF NOT EXISTS on #{type} (#{properties.join(', ')}) #{unique_requested}" } &.first
166
167
  # puts "success: #{success}"
167
- success && success.keys == [ :totalIndexed, :name, :operation ] && success[:operation] == 'create index'
168
-
169
- end
170
-
171
-
172
- # ------------------------------ transaction ------------------------------------------------- #
173
- #
174
- def self.begin_transaction database
175
- result = Typhoeus.post Arcade::Config.base_uri + "begin/#{database}", auth
176
- @session_id = result.headers["arcadedb-session-id"]
168
+ success[:operation] == 'create index'
177
169
 
178
- # returns the session-id
179
170
  end
180
171
 
181
172
 
182
- # ------------------------------ commit ------------------------------------------------- #
183
- def self.commit database
184
- options = auth.merge( headers: { "arcadedb-session-id" => session })
185
- post_data "commit/#{database}", options
186
- @session_id = nil
187
- end
188
-
189
- # ------------------------------ rollback ------------------------------------------------- #
190
- def self.rollback database, publish_error=true
191
- options = auth.merge( headers: { "arcadedb-session-id" => session })
192
- post_data "rollback/#{database}", options
193
- @session_id = nil
194
- raise Arcade::RollbackError "A Transaction has been rolled back" if publish_error
195
- end
196
-
197
173
  private
198
174
 
199
175
  def self.logger
@@ -235,37 +211,15 @@ module Arcade
235
211
  [ :language, value.to_sym ]
236
212
  end
237
213
  end # case
238
- end .to_h ).to_json # map
239
- end
240
-
241
- def self.get_data command, options = auth
242
- result = Typhoeus.get Arcade::Config.base_uri + command, options
243
- analyse_result(result, command)
214
+ end .to_h ) # map
244
215
  end
245
216
 
246
217
 
247
- def self.post_data command, options = auth
248
- # puts "Post DATA #{command} #{options}" # debug
249
- i = 0; a=""
250
- loop do
251
- result = Typhoeus.post Arcade::Config.base_uri + command, options
252
- # Code: 503 – Service Unavailable
253
- if result.response_code.to_i == 503 # retry two times
254
- i += 1
255
- raise Arcade::QueryError, JSON.parse( result.response_body, symbolize_names: true )[:result] if i > 3
256
- sleep 0.1
257
- else
258
- a= analyse_result(result, command )
259
- break
260
- end
261
- end
262
- a
263
- end
264
218
 
265
- # returns the json-response
219
+ # returns the json-response ## retiered
266
220
  def self.analyse_result r, command
267
221
  if r.success?
268
- return nil if r.response_code == 204 # no content
222
+ return nil if r.status == 204 # no content
269
223
  result = JSON.parse( r.response_body, symbolize_names: true )[:result]
270
224
  if result == [{}]
271
225
  []
@@ -273,14 +227,14 @@ module Arcade
273
227
  result
274
228
  end
275
229
  elsif r.timed_out?
276
- raise Arcade::Error "Timeout Error", caller
230
+ raise Error "Timeout Error", caller
277
231
  []
278
232
  elsif r.response_code > 0
279
233
  logger.error "Execution Failure – Code: #{ r.response_code } – #{r.status_message} "
280
234
  error_message = JSON.parse( r.response_body, symbolize_names: true )
281
235
  logger.error "ErrorMessage: #{ error_message[:detail]} "
282
236
  if error_message[:detail] =~ /Duplicated key/
283
- raise Arcade::IndexError, error_message[:detail]
237
+ raise IndexError, error_message[:detail]
284
238
  else
285
239
  # available fields: :detail, :exception, error
286
240
  puts error_message[:detail]
@@ -290,16 +244,13 @@ module Arcade
290
244
  end
291
245
  def self.auth
292
246
  @a ||= { httpauth: :basic,
293
- username: Arcade::Config.admin[:user],
294
- password: Arcade::Config.admin[:pass] }
247
+ username: Config.admin[:user],
248
+ password: Config.admin[:pass] }
295
249
  end
296
250
 
297
- def self.json
298
- { headers: { "Content-Type" => "application/json"} }
299
- end
300
251
  # not tested
301
252
  def self.delete_data command
302
- result = Typhoeus.delete Arcade::Config.base_uri + command, auth
253
+ result = HTTPX.delete Config.base_uri + command, auth
303
254
  analyse_result(result, command)
304
255
  end
305
256
  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
+
data/lib/arcade/base.rb CHANGED
@@ -5,7 +5,7 @@ module Arcade
5
5
  # schema schema.strict # -- throws an error if specified keys are missing
6
6
  transform_keys{ |x| x[0] == '@' ? x[1..-1].to_sym : x.to_sym }
7
7
  # Types::Rid --> only accept #000:000, raises an Error, if rid is not present
8
- attribute :rid, Types::Rid
8
+ attribute :rid?, Types::Rid
9
9
  # maybe there are edges ## removed in favour of instance methods
10
10
  # attribute :in?, Types::Nominal::Any
11
11
  # attribute :out?, Types::Nominal::Any
@@ -41,12 +41,7 @@ module Arcade
41
41
  if the_class.respond_to?(:demodulize)
42
42
  if [ 'Document','Vertex', 'Edge'].include?(the_class.demodulize)
43
43
  if the_class == superclass # no inheritance
44
- ## we have to use demodulize as the_class actually is Arcade::Vertex, ...
45
- unless parent_present[ to_s.snake_case ]
46
44
  db.create_type the_class.demodulize, to_s.snake_case
47
- else
48
- db.logger.warn "Type #{ to_s.snake_case } is present, process skipped"
49
- end
50
45
  else
51
46
  if superclass.is_a? Class # maybe its a module.
52
47
  extended = superclass.to_s.snake_case
@@ -75,7 +70,7 @@ module Arcade
75
70
  db.execute { the_command }
76
71
  end unless custom_setup.nil?
77
72
 
78
- rescue Arcade::RollbackError => e
73
+ rescue RollbackError => e
79
74
  db.logger.warn e
80
75
  rescue RuntimeError => e
81
76
  db.logger.warn e
@@ -134,10 +129,10 @@ module Arcade
134
129
  # ( depreciated )
135
130
 
136
131
  def create **attributes
137
- Api.begin_transaction db.database
132
+ s = Api.begin_transaction db.database
138
133
  attributes.merge!( created: DateTime.now ) if timestamps
139
134
  record = insert **attributes
140
- Api.commit db.database
135
+ Api.commit db.database, s
141
136
  record
142
137
  rescue QueryError => e
143
138
  db.logger.error "Dataset NOT created"
@@ -222,8 +217,7 @@ module Arcade
222
217
  # Finds the first matching record providing the parameters of a `where` query
223
218
  # Strategie.find symbol: 'Still'
224
219
  # is equivalent to
225
- # Strategie.all.find{|y| y.symbol == 'Still'
226
- # }
220
+ # Strategie.all.find{|y| y.symbol == 'Still' }
227
221
  def find **args
228
222
  f= where(**args).first
229
223
  f= where( "#{ args.keys.first } like #{ args.values.first.to_or }" ).first if f.nil? || f.empty?
@@ -278,14 +272,14 @@ module Arcade
278
272
  end
279
273
  result= query( **( { kind: :upsert }.merge statement ) ).execute do | answer|
280
274
  z= answer[:"$current"] &.allocate_model(false) # do not autoload modelfiles
281
- raise Arcade::LoadError "Upsert failed" unless z.is_a? Arcade::Base
275
+ raise LoadError "Upsert failed" unless z.is_a? Base
282
276
  z # return record
283
277
  end
284
278
  end
285
279
 
286
280
 
287
281
  def query **args
288
- Arcade::Query.new( **{ from: self }.merge(args) )
282
+ Query.new( **{ from: self }.merge(args) )
289
283
  end
290
284
 
291
285
  # immutable support
@@ -332,7 +326,7 @@ module Arcade
332
326
  end
333
327
 
334
328
  def query **args
335
- Arcade::Query.new( **{ from: rid }.merge(args) )
329
+ Query.new( **{ from: rid }.merge(args) )
336
330
  end
337
331
 
338
332
  # to JSON controlls the serialisation of Arcade::Base Objects for the HTTP-JSON API
@@ -364,7 +358,7 @@ module Arcade
364
358
 
365
359
  "<#{ self.class.to_s.snake_case }" + rid? ? "[#{ rid }]: " : " " + invariant_attributes.map do |attr, value|
366
360
  v= case value
367
- when Arcade::Base
361
+ when Base
368
362
  "< #{ self.class.to_s.snake_case }: #{ value.rid } >"
369
363
  when Array
370
364
  value.map{|x| x.to_s}
@@ -375,7 +369,12 @@ module Arcade
375
369
  end.compact.sort.join(', ') + ">".gsub('"' , ' ')
376
370
  end
377
371
 
378
- alias to_s to_human
372
+
373
+ # configure irb-output to to_human for all Arcade::Base-Objects
374
+ #
375
+ def inspect
376
+ to_human
377
+ end
379
378
 
380
379
  def to_html # iruby
381
380
  _modul, _class = self.class.to_s.split "::"
@@ -383,7 +382,7 @@ module Arcade
383
382
  IRuby.display IRuby.html "<b style=\"color: #50953DFF\"><#{ the_class}</b>"
384
383
  + rid? ? "[#{ rid }]: " : " " + invariant_attributes.map do |attr, value|
385
384
  v= case value
386
- when Arcade::Base
385
+ when Base
387
386
  "< #{ self.class.to_s.snake_case }: #{ value.rid } >"
388
387
  when Array
389
388
  value.map{|x| x.to_s}
@@ -395,13 +394,13 @@ module Arcade
395
394
  end
396
395
 
397
396
  def update **args
398
- Arcade::Query.new( from: rid , kind: :update, set: args).execute
397
+ Query.new( from: rid , kind: :update, set: args).execute
399
398
  refresh
400
399
  end
401
400
 
402
401
  # inserts or updates a embedded document
403
402
  def insert_document name, obj
404
- value = if obj.is_a? Arcade::Document
403
+ value = if obj.is_a? Document
405
404
  obj.to_json
406
405
  else
407
406
  obj.to_or
@@ -417,7 +416,7 @@ module Arcade
417
416
  end
418
417
 
419
418
  def update_list list, value
420
- value = if value.is_a? Arcade::Document
419
+ value = if value.is_a? Document
421
420
  value.to_json
422
421
  else
423
422
  value.to_or
@@ -112,8 +112,13 @@ module Arcade
112
112
  types( true ) # update cached schema
113
113
  db
114
114
 
115
- rescue Arcade::QueryError
116
- Arcade::Database.logger.warn "Database type #{type} already present"
115
+ rescue HTTPX::HTTPError => e
116
+ # puts "ERROR: #{e.message.to_s}"
117
+ if e.status == 500 && e.message.to_s =~ /already exists/
118
+ Arcade::Database.logger.warn "Database type #{type} already present"
119
+ else
120
+ raise
121
+ end
117
122
  end
118
123
 
119
124
  alias create_class create_type
@@ -233,8 +238,18 @@ module Arcade
233
238
  # If an Error occurs, its rolled back
234
239
  #
235
240
  def execute &block
236
- Api.begin_transaction database
237
- response = Api.execute database, &block
241
+ s = Api.begin_transaction database
242
+ # begin
243
+ response = Api.execute database, nil, s, &block
244
+ # rescue HTTPX::HTTPError => e
245
+ # raise e.message
246
+ # puts e.methods
247
+ # puts e.status
248
+ # puts e.response
249
+ # puts e.message
250
+ # puts e.exception
251
+ # puts e.cause
252
+ # end
238
253
  # puts response.inspect # debugging
239
254
  r= if response.is_a? Hash
240
255
  _allocate_model res
@@ -251,11 +266,15 @@ module Arcade
251
266
  else
252
267
  response
253
268
  end
254
- Api.commit database
255
- r # return associated array of Arcade::Base-objects
256
- rescue Dry::Struct::Error, Arcade::QueryError => e
257
- Api.rollback database
258
- logger.error "Execution FAILED --> #{e.exception}"
269
+ if Api.commit( database, s) == 204
270
+ r # return associated array of Arcade::Base-objects
271
+ else
272
+ []
273
+ end
274
+ rescue Dry::Struct::Error, HTTPX::HTTPError, Arcade::QueryError => e
275
+ Api.rollback database, s
276
+ logger.error "Execution FAILED --> Status #{e.status}"
277
+ # logger.error "Execution FAILED --> #{e.exception.message}"
259
278
  [] # return empty result
260
279
  end
261
280
 
@@ -272,7 +291,17 @@ module Arcade
272
291
 
273
292
  content = attributes.empty? ? "" : "CONTENT #{attributes.to_json}"
274
293
  cr = ->( f, t ) do
275
- edges = Api.execute( database, "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}").allocate_model(false)
294
+ begin
295
+ edges = Api.execute( database, "create edge #{edge_class} from #{f.rid} to #{t.rid} #{content}").allocate_model(false)
296
+ rescue HTTPX::HTTPError => e
297
+ # if e.status == 503
298
+ # puts e.status
299
+ # puts e.message
300
+ # puts e.message.class
301
+ # end
302
+ raise unless e.message =~ /Found duplicate key/
303
+ puts "#"+e.message.split("#").last[0..-3]
304
+ end
276
305
  #else
277
306
  # logger.error "Could not create Edge #{edge_class} from #{f} to #{t}"
278
307
  ## logger.error edges.to_s
@@ -1,3 +1,3 @@
1
1
  module Arcade
2
- VERSION = "0.3.3"
2
+ VERSION = "0.4"
3
3
  end
data/lib/arcade.rb CHANGED
@@ -2,7 +2,7 @@ module Arcade
2
2
 
3
3
  end
4
4
 
5
- require "arcade/api/version"
5
+ require "arcade/version"
6
6
  require "dry/configurable"
7
7
  require "dry/struct"
8
8
  require "dry/core/class_builder"
@@ -12,14 +12,10 @@ require 'json'
12
12
  module Types
13
13
  include Dry.Types()
14
14
  end
15
- #require 'pg' # ruby postgres driver
16
- #require 'mini_sql'
17
- #require 'sequel'
18
- #require 'httparty'
19
15
  require 'yaml'
20
16
  require 'securerandom'
21
- require 'typhoeus' # curl library
22
- require_relative '../lib/arcade/errors'
17
+ require 'httpx'
18
+ require 'arcade/errors'
23
19
  require_relative '../lib/support/object'
24
20
  require_relative '../lib/support/string'
25
21
  require_relative '../lib/support/class'
@@ -28,6 +24,7 @@ require_relative '../lib/support/model'
28
24
  require_relative '../lib/arcade/logging'
29
25
  require_relative '../lib/config'
30
26
  require_relative '../lib/support/conversions'
27
+ require_relative '../lib/arcade/api/primitives'
31
28
  require_relative '../lib/arcade/api/operations'
32
29
  require_relative '../lib/arcade/base'
33
30
  require_relative '../lib/arcade/database'
data/lib/config.rb CHANGED
@@ -48,17 +48,19 @@ module Arcade
48
48
  setting :namespace, default: :namespace, reader: true , constructor: ->(v) { yml(v) }
49
49
  setting :secret, reader: true, default: 12, constructor: ->(v) { seed(v) }
50
50
  private
51
- # if a config dir exists, use it
51
+ # if a config dir exists, use it.
52
+ # Standard: ProjectRoot/config.yml
52
53
  def self.config_file
53
- if @cd.nil?
54
- ( cd = ProjectRoot + 'arcade.yml' ).exist? ||
55
- ( cd = ProjectRoot + 'config' + 'arcade.yml' ).exist? ||
56
- ( cd = ProjectRoot + "config.yml" )
57
- @cd = cd
58
- else
59
- @cd
54
+
55
+ configdir = -> do
56
+ pr = ProjectRoot.is_a?(Pathname)? ProjectRoot : Pathname.new( ProjectRoot )
57
+ ( cd = pr + 'arcade.yml' ).exist? || ( cd = pr + 'config' + 'arcade.yml' ).exist? || ( cd = pr + 'config.yml' )
58
+ cd
60
59
  end
60
+
61
+ @cd ||= configdir[]
61
62
  end
63
+
62
64
  def self.yml key=nil
63
65
  y= YAML::load_file( config_file )
64
66
  key.nil? ? y : y[key]
data/lib/model/vertex.rb CHANGED
@@ -59,14 +59,14 @@ module Arcade
59
59
 
60
60
  s = Query.new from: self
61
61
  s.nodes in_or_out, via: via, **args
62
- s.query.select_result
62
+ s.query &.select_result
63
63
  end
64
64
 
65
65
 
66
66
  # #
67
67
  ## --------------------------------- Instance Methods --------------------------------- ##
68
68
  #
69
- # We need expand as fallback if a vertex, which is stored as link is automatically loaded
69
+ # We need expand as fallback if a vertex, which is stored as link, is automatically loaded
70
70
  #
71
71
  def expand
72
72
  self
@@ -77,7 +77,7 @@ module Arcade
77
77
  s = Query.new from: rid
78
78
  s.nodes in_or_out, via: via, **args
79
79
  if execute
80
- s.query.select_result
80
+ s.query &.select_result
81
81
  else
82
82
  s # just return the query
83
83
  end
@@ -209,7 +209,7 @@ Format: < Classname: Edges, Attributes >
209
209
 
210
210
  #Default presentation of Arcade::Base::Model-Objects
211
211
 
212
- "<#{self.class.to_s.snake_case}[#{rid}]: " +
212
+ "<#{self.class.to_s.snake_case}[#{rid}]:" +
213
213
  in_and_out[] +
214
214
  invariant_attributes.map do |attr, value|
215
215
  v= case value
data/lib/query.rb CHANGED
@@ -104,7 +104,7 @@ module Arcade
104
104
  elsif @q[:database].present?
105
105
  the_argument = @q[:database]
106
106
  case @q[:database]
107
- when Arcade::Base # a single record
107
+ when Base # a single record
108
108
  the_argument.rid
109
109
  when self.class # result of a query
110
110
  ' ( '+ the_argument.compose + ' ) '
@@ -370,7 +370,7 @@ end # class << self
370
370
  end
371
371
  :protected
372
372
  def resolve_target
373
- if @q[:database].is_a? Arcade::Query
373
+ if @q[:database].is_a? Query
374
374
  @q[:database].resolve_target
375
375
  else
376
376
  @q[:database]
@@ -195,7 +195,7 @@ module Arcade
195
195
  when Symbol, String
196
196
  k.to_s
197
197
  else
198
- raise "not supported key: #[k} -- must a sting, symbol or number"
198
+ raise "not supported key: #{k} -- must a sting, symbol or number"
199
199
  end
200
200
  [orient_k, v.to_db]
201
201
  end.to_h
data/lib/support/model.rb CHANGED
@@ -19,14 +19,17 @@ module Arcade
19
19
  # used by array#allocate_model
20
20
  def _allocate_model response=nil, auto = Config.autoload
21
21
 
22
+
22
23
  if response.is_a? Hash
23
24
  # save rid to a safe place
24
25
  temp_rid = response.delete :"@rid"
25
-
26
- return response if temp_rid.rid?.nil?
27
- # extract type infos and convert to database-name
28
26
  type = response.delete :"@type"
29
27
  cat = response.delete :"@cat"
28
+
29
+ return response if type.nil?
30
+ temp_rid = "#0:0" if temp_rid.nil?
31
+ type = "d" if type.nil?
32
+ # extract type infos and convert to database-name
30
33
  n, type_name = type.camelcase_and_namespace
31
34
  n = self.namespace if n.nil?
32
35
  # autoconvert rid's in attributes to model-records (exclude edges!)
@@ -38,7 +41,7 @@ module Arcade
38
41
  when Array
39
42
  x.map do| y |
40
43
  if y.is_a?(Hash) && y.include?(:@type) # if embedded documents are present, load them
41
- y.merge( rid: '#0:0' ).allocate_model(false)
44
+ y.allocate_model(false)
42
45
  elsif y.rid? # if links are present, load the object
43
46
  y.load_rid(false) # do not autoload further records, prevents from recursive locking
44
47
  else
@@ -47,7 +50,7 @@ module Arcade
47
50
  end
48
51
  when Hash
49
52
  if x.include?(:@type)
50
- x.merge( rid: '#0:0' ).allocate_model(false)
53
+ x.allocate_model(false)
51
54
  else
52
55
  x.transform_values!{|z| z.rid? ? z.load_rid(false) : z }
53
56
  end
@@ -61,7 +64,7 @@ module Arcade
61
64
  #
62
65
  begin
63
66
  # create a new object of that class with the appropriate attributes
64
- new = klass.new **response.merge( rid: temp_rid || "#0:0" ) # #0:0 --> embedded model records
67
+ new = klass.new **response.merge( rid: temp_rid )
65
68
  rescue ::ArgumentError => e
66
69
  raise "Allocation of class #{klass.to_s} failed"
67
70
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arcadedb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hartmut Bischoff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-23 00:00:00.000000000 Z
11
+ date: 2023-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: typhoeus
56
+ name: httpx
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: dry-configurable
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  description: Provides access to ArcadeDB from ruby
112
126
  email: topofocus@gmail.com
113
127
  executables: []
@@ -132,7 +146,7 @@ files:
132
146
  - examples/relation_n_n.rb
133
147
  - lib/arcade.rb
134
148
  - lib/arcade/api/operations.rb
135
- - lib/arcade/api/version.rb
149
+ - lib/arcade/api/primitives.rb
136
150
  - lib/arcade/base.rb
137
151
  - lib/arcade/database.rb
138
152
  - lib/arcade/errors.rb
@@ -1,5 +0,0 @@
1
- module Arcade
2
- module Api
3
- VERSION = 0.1
4
- end
5
- end