diametric 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +3 -3
  3. data/Jarfile +13 -6
  4. data/LICENSE.txt +2 -2
  5. data/README.md +57 -26
  6. data/Rakefile +1 -0
  7. data/bin/datomic-rest +1 -1
  8. data/bin/download-datomic +1 -1
  9. data/datomic_version.yml +2 -2
  10. data/diametric.gemspec +8 -7
  11. data/ext/diametric/DiametricCollection.java +45 -38
  12. data/ext/diametric/DiametricConnection.java +16 -15
  13. data/ext/diametric/DiametricDatabase.java +9 -8
  14. data/ext/diametric/DiametricEntity.java +104 -21
  15. data/ext/diametric/DiametricObject.java +12 -1
  16. data/ext/diametric/DiametricPeer.java +52 -31
  17. data/ext/diametric/DiametricService.java +2 -0
  18. data/ext/diametric/DiametricSet.java +11 -4
  19. data/ext/diametric/DiametricUUID.java +8 -1
  20. data/ext/diametric/DiametricUtils.java +90 -62
  21. data/lib/diametric.rb +1 -0
  22. data/lib/diametric/associations/collection.rb +103 -0
  23. data/lib/diametric/entity.rb +166 -103
  24. data/lib/diametric/persistence/common.rb +0 -44
  25. data/lib/diametric/persistence/peer.rb +53 -2
  26. data/lib/diametric/persistence/rest.rb +27 -1
  27. data/lib/diametric/query.rb +49 -31
  28. data/lib/diametric/rest_service.rb +8 -9
  29. data/lib/diametric/service_base.rb +7 -7
  30. data/lib/diametric/transactor.rb +6 -5
  31. data/lib/diametric/version.rb +1 -1
  32. data/lib/diametric_service.jar +0 -0
  33. data/spec/config/free-transactor-template.properties +6 -6
  34. data/spec/developer_query_spec.rb +17 -6
  35. data/spec/diametric/entity_spec.rb +62 -139
  36. data/spec/diametric/peer_api_spec.rb +23 -23
  37. data/spec/diametric/persistence/peer_spec.rb +73 -11
  38. data/spec/diametric/persistence/rest_spec.rb +108 -16
  39. data/spec/diametric/query_spec.rb +3 -3
  40. data/spec/diametric/rest_service_spec.rb +4 -4
  41. data/spec/diametric/schema_spec.rb +526 -0
  42. data/spec/diametric/transactor_spec.rb +5 -6
  43. data/spec/integration_spec.rb +7 -7
  44. data/spec/peer_integration_spec.rb +25 -1
  45. data/spec/peer_seattle_spec.rb +1 -2
  46. data/spec/spec_helper.rb +31 -4
  47. data/spec/support/cardinarity_many_example.rb +37 -0
  48. data/spec/support/entities.rb +127 -0
  49. data/spec/support/has_a_example.rb +31 -0
  50. data/spec/support/has_many_example.rb +79 -0
  51. data/spec/support/persistence_examples.rb +13 -5
  52. data/spec/support/various_types_examples.rb +163 -0
  53. data/spec/test_version_file.yml +2 -2
  54. metadata +66 -15
@@ -2,7 +2,6 @@ module Diametric
2
2
  module Persistence
3
3
  module Common
4
4
  def self.included(base)
5
- base.send(:extend, ClassMethods)
6
5
  base.send(:include, InstanceMethods)
7
6
  end
8
7
 
@@ -34,49 +33,6 @@ module Diametric
34
33
  return true
35
34
  end
36
35
  end
37
-
38
- module ClassMethods
39
- def create_schema(connection=nil)
40
- if self.instance_variable_get("@peer")
41
- connection ||= Diametric::Persistence::Peer.connect
42
- connection.transact(schema)
43
- else
44
- transact(schema)
45
- end
46
- end
47
-
48
- def all(connection=nil, resolve=true)
49
- if self.instance_variable_get("@peer")
50
- connection ||= Diametric::Persistence::Peer.connect
51
- end
52
- Diametric::Query.new(self, connection, resolve).all
53
- end
54
-
55
- def first(conditions = {}, connection=nil, resolve=true)
56
- if self.instance_variable_get("@peer")
57
- connection ||= Diametric::Persistence::Peer.connect
58
- end
59
- where(conditions, connection, resolve).first
60
- end
61
-
62
- def where(conditions = {}, connection=nil, resolve=true)
63
- if self.instance_variable_get("@peer")
64
- connection ||= Diametric::Persistence::Peer.connect
65
- end
66
- query = Diametric::Query.new(self, connection, resolve)
67
- query.where(conditions)
68
- end
69
-
70
- def filter(*filter)
71
- if self.instance_variable_get("@peer")
72
- connection = Diametric::Persistence::Peer.connect
73
- else
74
- connection = nil
75
- end
76
- query = Diametric::Query.new(self, connection, true)
77
- query.filter(*filter)
78
- end
79
- end
80
36
  end
81
37
  end
82
38
  end
@@ -3,7 +3,6 @@ require 'diametric/persistence/common'
3
3
  module Diametric
4
4
  module Persistence
5
5
  module Peer
6
-
7
6
  def save(connection=nil)
8
7
  return false unless valid?
9
8
  return true unless changed?
@@ -12,8 +11,16 @@ module Diametric
12
11
  parsed_data = []
13
12
  parse_tx_data(tx_data, parsed_data)
14
13
 
14
+ # TODO: exception handling. error message should be found by errors.messages
15
15
  map = connection.transact(parsed_data).get
16
16
 
17
+ =begin
18
+ resolve_fn = Java::ClojureLang::RT.var("datomic.api", "resolve-tempid")
19
+ tempids_key = Java::ClojureLang::Keyword.intern("tempids")
20
+ ids = map.to_java.get(tempids_key)
21
+ db = connection.db.to_java
22
+ resolve_fn.invoke(db, ids, self.dbid.to_java)
23
+ =end
17
24
  resolve_changes([self], map)
18
25
 
19
26
  map
@@ -122,6 +129,50 @@ module Diametric
122
129
  end
123
130
 
124
131
  module ClassMethods
132
+
133
+ # Create a temporary id placeholder.
134
+ #
135
+ # @param e [*#to_edn] Elements to put in the placeholder. Should
136
+ # be either partition or partition and a negative number to be
137
+ # used as a reference.
138
+ #
139
+ # @return [Diametric::Persistence::Object] Temporary id placeholder.
140
+ def tempid(*e)
141
+ if e.size == 1
142
+ return Diametric::Persistence::Peer.tempid(e[0])
143
+ elsif e.size == 2
144
+ return Diametric::Persistence::Peer.tempid(e[0], e[1])
145
+ end
146
+ nil
147
+ end
148
+
149
+ def create_schema(connection=nil)
150
+ connection ||= Diametric::Persistence::Peer.connect
151
+ connection.transact(schema)
152
+ end
153
+
154
+ def all(connection=nil, resolve=true)
155
+ connection ||= Diametric::Persistence::Peer.connect
156
+ Diametric::Query.new(self, connection, resolve).all
157
+ end
158
+
159
+ def first(conditions = {}, connection=nil, resolve=true)
160
+ connection ||= Diametric::Persistence::Peer.connect
161
+ where(conditions, connection, resolve).first
162
+ end
163
+
164
+ def where(conditions = {}, connection=nil, resolve=true)
165
+ connection ||= Diametric::Persistence::Peer.connect
166
+ query = Diametric::Query.new(self, connection, resolve)
167
+ query.where(conditions)
168
+ end
169
+
170
+ def filter(connection, *filter)
171
+ connection ||= Diametric::Persistence::Peer.connect
172
+ query = Diametric::Query.new(self, connection, true)
173
+ query.filter(*filter)
174
+ end
175
+
125
176
  def get(dbid, connection=nil, resolve=false)
126
177
  entity = self.new
127
178
  dbid = dbid.to_i if dbid.is_a?(String)
@@ -137,7 +188,7 @@ module Diametric
137
188
  else
138
189
  db = conn_or_db
139
190
  end
140
- Diametric::Persistence::Peer.q(query, db, args)
191
+ Diametric::Persistence::Peer.q(query, db, args.flatten(1))
141
192
  end
142
193
  end
143
194
  end
@@ -43,10 +43,36 @@ module Diametric
43
43
  @database || Diametric::Persistence::REST.database
44
44
  end
45
45
 
46
+ def tempid(*e)
47
+ EDN.tagged_element('db/id', e)
48
+ end
49
+
46
50
  def transact(data)
47
51
  connection.transact(database, data)
48
52
  end
49
53
 
54
+ def create_schema
55
+ transact(schema)
56
+ end
57
+
58
+ def all
59
+ Diametric::Query.new(self, nil, true).all
60
+ end
61
+
62
+ def first(conditions = {})
63
+ where(conditions).first
64
+ end
65
+
66
+ def where(conditions = {})
67
+ query = Diametric::Query.new(self, nil, true)
68
+ query.where(conditions)
69
+ end
70
+
71
+ def filter(*filter)
72
+ query = Diametric::Query.new(self, nil, true)
73
+ query.filter(*filter)
74
+ end
75
+
50
76
  def get(dbid, conn=nil, resolve=false)
51
77
  conn ||= connection
52
78
  res = conn.entity(database, dbid.to_i)
@@ -84,7 +110,7 @@ module Diametric
84
110
  self.dbid = self.dbid.to_i if self.dbid.class == String
85
111
 
86
112
  res = self.class.transact(tx_data)
87
- if dbid.nil?
113
+ if dbid.nil? || dbid.is_a?(EDN::Type::Unknown)
88
114
  self.dbid = res.data[:tempids].values.first
89
115
  end
90
116
 
@@ -1,4 +1,5 @@
1
1
  require 'diametric'
2
+ require 'edn'
2
3
 
3
4
  module Diametric
4
5
  # +Query+ objects are used to generate Datomic queries, whether to
@@ -15,7 +16,7 @@ module Diametric
15
16
  class Query
16
17
  include Enumerable
17
18
 
18
- attr_reader :conditions, :filters, :filter_attrs, :model, :connection, :resolve
19
+ attr_reader :conditions, :filters, :filter_attrs, :filter_values, :model, :connection, :resolve
19
20
 
20
21
  # Create a new Datomic query.
21
22
  #
@@ -26,6 +27,7 @@ module Diametric
26
27
  @conditions = {}
27
28
  @filters = []
28
29
  @filter_attrs = []
30
+ @filter_values = []
29
31
  @conn_or_db = connection_or_database
30
32
  @resolve = resolve
31
33
  end
@@ -72,7 +74,7 @@ module Diametric
72
74
  # that will be converted into a Datalog query.
73
75
  # @return [Query]
74
76
  def filter(*filter)
75
- return peer_filter(filter) if self.model.instance_variable_get("@peer")
77
+ return peer_filter(*filter) if self.model.instance_variable_get("@peer")
76
78
  query = self.dup
77
79
 
78
80
  if filter.first.is_a?(EDN::Type::List)
@@ -87,16 +89,19 @@ module Diametric
87
89
 
88
90
  def peer_filter(*filter)
89
91
  query = self.dup
90
- if filter.first.is_a?(Array)
91
- filter = filter.first
92
+ query.filter_attrs += (self.model.attribute_names & filter)
93
+ filter = filter.map do |e|
94
+ if e.is_a? Symbol
95
+ convert_filter_element(e)
96
+ elsif e.is_a? String
97
+ e
98
+ else
99
+ query.filter_values << e
100
+ ~"?#{query.filter_attrs.last.to_s}value"
101
+ end
92
102
  end
93
- filter_attrs << filter[1].to_s
94
- query_filter = []
95
- query_filter << filter[0].to_s
96
- query_filter << "?#{filter[1].to_s}"
97
- query_filter << filter[2..-1]
98
- query_filter = query_filter.flatten
99
- query.filters += [query_filter]
103
+ filter = EDN::Type::List.new(*filter)
104
+ query.filters << [Diametric::Persistence::Utils.read_string(filter.to_edn)]
100
105
  query
101
106
  end
102
107
 
@@ -111,7 +116,7 @@ module Diametric
111
116
  # an appropriate error if not.
112
117
  res = model.q(*data, @conn_or_db)
113
118
  collapse_results(res).each do |entity|
114
- if self.model.instance_variable_get("@peer") && @resolve
119
+ if @resolve
115
120
  yield model.reify(entity.first, @conn_or_db, @resolve)
116
121
  elsif self.model.instance_variable_get("@peer")
117
122
  yield entity
@@ -177,31 +182,36 @@ module Diametric
177
182
  [(= ?ns ?include-ns)]]
178
183
  EOQ
179
184
  else
180
- unless conditions.empty?
181
- clauses = conditions.keys.inject("") do |memo, attribute|
182
- memo + "[?e " + model.namespace(model.prefix, attribute) + " ?#{attribute} ] "
185
+ from = conditions.map do |k, v|
186
+ if v.kind_of? Array
187
+ [~"?#{k}",
188
+ Diametric::Persistence::Utils.read_string("...")]
189
+ else
190
+ ~"?#{k}"
183
191
  end
184
- from = conditions.inject("") {|memo, kv| memo + "?#{kv.shift} "}
185
- args = conditions.map { |_, v| v }
186
192
  end
187
193
 
194
+ keys = conditions.keys
188
195
  unless filter_attrs.empty?
189
- clauses ||= ""
190
- clauses = filter_attrs.inject(clauses) do |memo, attribute|
191
- memo + "[?e " + model.namespace(model.prefix, attribute) + " ?#{attribute} ] "
192
- end
193
- from ||= ""
194
- from = filter_attrs.inject(from) {|from, attr| from + "?#{attr}_value "}
195
- filter_query =
196
- "[" +
197
- filters.inject("") {|memo, filter| memo + "(#{filter[0]} #{filter[1]} #{filter[1]}_value) "} +
198
- "]"
199
- args ||= []
200
- args = filters.inject(args) {|args, filter| args + filter[2..-1]}
196
+ from += filter_attrs.inject([]) { |memo, key| memo << ~"?#{key}value"; memo }
197
+ keys += filter_attrs
201
198
  end
202
- query = "[:find ?e :in $ [#{from}] :where #{clauses} #{filter_query}]"
203
- end
199
+ keys.uniq!
200
+
201
+ clauses = keys.map { |attribute|
202
+ [~"?e", model.namespace(model.prefix, attribute), ~"?#{attribute}"]
203
+ }
204
+ clauses += filters
204
205
 
206
+ args = conditions.map { |_, v| v }
207
+ args += filter_values
208
+
209
+ query = [
210
+ :find, ~"?e",
211
+ :in, ~"\$", from.flatten(1),
212
+ :where, *clauses
213
+ ]
214
+ end
205
215
  [query, args]
206
216
  end
207
217
 
@@ -215,6 +225,14 @@ EOQ
215
225
  @filters = filters
216
226
  end
217
227
 
228
+ def filter_attrs=(filter_attrs)
229
+ @filter_attrs = filter_attrs
230
+ end
231
+
232
+ def filter_values=(filter_values)
233
+ @filter_values = filter_values
234
+ end
235
+
218
236
  def convert_filter_element(element)
219
237
  if element.is_a?(Symbol)
220
238
  if model.attribute_names.include?(element) || @conditions.keys.include?(element)
@@ -6,7 +6,7 @@ module Diametric
6
6
  class << self
7
7
  def datomic_command(datomic_home)
8
8
  classpath = datomic_classpath(datomic_home)
9
- command = ["java -server -Xmx1g", "-cp", classpath, "clojure.main", "-i", "#{datomic_home}/bin/bridge.clj", "--main datomic.rest"].flatten.join(" ")
9
+ ["java -server -Xmx1g", "-cp", classpath, "clojure.main", "-i", "#{datomic_home}/bin/bridge.clj", "--main datomic.rest"].flatten.join(" ")
10
10
  end
11
11
  end
12
12
 
@@ -14,12 +14,11 @@ module Diametric
14
14
  attr_accessor :host, :port, :db_alias, :uri
15
15
 
16
16
  def initialize(conf="datomic_version.yml", dest="vendor/datomic")
17
- @conf = conf
18
- @dest = dest
19
- @datomic_version = RestService.datomic_version(conf)
20
- @datomic_home = File.join(File.dirname(__FILE__), "../..", dest, @datomic_version)
21
- @datomic_version_no = RestService.datomic_version_no(@datomic_version)
22
- @pid = nil
17
+ @conf = conf
18
+ @dest = dest
19
+ datomic_type, datomic_version = RestService.datomic_version(conf)
20
+ @datomic_home = File.join(File.dirname(__FILE__), "../..", dest, "datomic-#{datomic_type}-#{datomic_version}")
21
+ @pid = nil
23
22
  end
24
23
 
25
24
  def start(opts={})
@@ -51,7 +50,7 @@ module Diametric
51
50
  end
52
51
 
53
52
  def port_available?(uri)
54
- response = Net::HTTP.get_response(uri)
53
+ Net::HTTP.get_response(uri)
55
54
  false
56
55
  rescue Errno::ECONNREFUSED
57
56
  true
@@ -60,7 +59,7 @@ module Diametric
60
59
  def ready?(uri)
61
60
  while true
62
61
  begin
63
- response = Net::HTTP.get_response(uri)
62
+ Net::HTTP.get_response(uri)
64
63
  return true
65
64
  rescue
66
65
  sleep 1
@@ -21,12 +21,12 @@ module Diametric
21
21
  datomic_names = File.read(File.join(File.dirname(__FILE__), "../..", conf))
22
22
  datomic_versions = YAML.load(datomic_names)
23
23
  if ENV['DIAMETRIC_ENV'] && (ENV['DIAMETRIC_ENV'] == "pro")
24
- datomic_versions["pro"]
24
+ return "pro", datomic_versions["pro"]
25
25
  else
26
- datomic_versions["free"]
26
+ return "free", datomic_versions["free"]
27
27
  end
28
28
  else
29
- conf
29
+ return "free", conf
30
30
  end
31
31
  end
32
32
 
@@ -35,17 +35,17 @@ module Diametric
35
35
  end
36
36
 
37
37
  def downloaded?(conf="datomic_version.yml", dest="vendor/datomic")
38
- datomic_home = datomic_version(conf)
38
+ datomic_type, datomic_version = datomic_version(conf)
39
39
  if Pathname.new(dest).relative?
40
40
  dest = File.join(File.dirname(__FILE__), "..", "..", dest)
41
41
  end
42
- File.exists?(File.join(dest, datomic_home))
42
+ File.exists?(File.join(dest, "datomic-#{datomic_type}-#{datomic_version}"))
43
43
  end
44
44
 
45
45
  def download(conf="datomic_version.yml", dest="vendor/datomic")
46
46
  return true if downloaded?(conf, dest)
47
- version = datomic_version(conf)
48
- url = "http://downloads.datomic.com/#{datomic_version_no(version)}/#{version}.zip"
47
+ type, version = datomic_version(conf)
48
+ url = "https://my.datomic.com/downloads/#{type}/#{version}"
49
49
  if Pathname.new(dest).relative?
50
50
  dest = File.join(File.dirname(__FILE__), "../..", dest)
51
51
  end
@@ -8,7 +8,7 @@ module Diametric
8
8
  class << self
9
9
  def datomic_command(datomic_home)
10
10
  classpath = datomic_classpath(datomic_home)
11
- java_opts = "-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly"
11
+ java_opts='-XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSScavengeBeforeRemark'
12
12
  command = ["java -server -Xmx1g -Xms1g", java_opts, "-cp", classpath, "clojure.main", "--main datomic.launcher"].flatten.join(" ")
13
13
  end
14
14
  end
@@ -19,13 +19,14 @@ module Diametric
19
19
  def initialize(conf="datomic_version.yml", dest="vendor/datomic")
20
20
  @conf = conf
21
21
  @dest = dest
22
- @datomic_version = Transactor.datomic_version(conf)
22
+ datomic_type, datomic_version = Transactor.datomic_version(conf)
23
+ datomic_path = "datomic-#{datomic_type}-#{datomic_version}"
23
24
  if Pathname.new(dest).relative?
24
- @datomic_home = File.join(File.dirname(__FILE__), "../..", dest, @datomic_version)
25
+ @datomic_home = File.join(File.dirname(__FILE__), "../..", dest, datomic_path)
25
26
  else
26
- @datomic_home = File.join(dest, @datomic_version)
27
+ @datomic_home = File.join(dest, datomic_path)
27
28
  end
28
- @datomic_version_no = Transactor.datomic_version_no(@datomic_version)
29
+ #@datomic_version_no = Transactor.datomic_version_no(@datomic_version)
29
30
  @hostname = nil
30
31
  @port = nil
31
32
  @pid = nil
@@ -1,3 +1,3 @@
1
1
  module Diametric
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
Binary file
@@ -23,9 +23,9 @@ port=39082
23
23
 
24
24
 
25
25
  # Recommended settings for -Xmx4g, ongoing usage.
26
- memory-index-threshold=32m
27
- memory-index-max=128m
28
- object-cache-max=1g
26
+ # memory-index-threshold=32m
27
+ # memory-index-max=128m
28
+ # object-cache-max=1g
29
29
 
30
30
  # Recommended settings for -Xmx4g import jobs.
31
31
  # memory-index-threshold=512m
@@ -33,9 +33,9 @@ object-cache-max=1g
33
33
  # object-cache-max=1g
34
34
 
35
35
  # Recommended settings for -Xmx1g usage, e.g. dev laptops.
36
- # memory-index-threshold=32m
37
- # memory-index-max=128m
38
- # object-cache-max=128m
36
+ memory-index-threshold=32m
37
+ memory-index-max=128m
38
+ object-cache-max=128m
39
39
 
40
40
 
41
41