ree_lib 1.0.49 → 1.0.50

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -3
  3. data/lib/ree_lib/Packages.schema.json +4 -0
  4. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +17 -10
  5. data/lib/ree_lib/packages/ree_dao/Package.schema.json +10 -0
  6. data/lib/ree_lib/packages/ree_dao/package/ree_dao/aggregate_dsl.rb +26 -0
  7. data/lib/ree_lib/packages/ree_dao/package/ree_dao/association.rb +311 -0
  8. data/lib/ree_lib/packages/ree_dao/package/ree_dao/associations.rb +148 -0
  9. data/lib/ree_lib/packages/ree_dao/package/ree_dao/beans/dao_cache.rb +40 -19
  10. data/lib/ree_lib/packages/ree_dao/package/ree_dao/contract/dao_dataset_contract.rb +15 -0
  11. data/lib/ree_lib/packages/ree_dao/package/ree_dao/contract/entity_contract.rb +15 -0
  12. data/lib/ree_lib/packages/ree_dao/package/ree_dao/dataset_extensions.rb +4 -0
  13. data/lib/ree_lib/packages/ree_dao/package/ree_dao/dsl.rb +1 -1
  14. data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/build_pg_connection.rb +1 -0
  15. data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/build_sqlite_connection.rb +1 -0
  16. data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/drop_cache.rb +1 -1
  17. data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/init_cache.rb +1 -1
  18. data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/load_agg.rb +63 -0
  19. data/lib/ree_lib/packages/ree_dao/package/ree_dao/thread_parents.rb +40 -0
  20. data/lib/ree_lib/packages/ree_dao/package/ree_dao.rb +9 -0
  21. data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/build_pg_connection.schema.json +1 -1
  22. data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/build_sqlite_connection.schema.json +1 -1
  23. data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/load_agg.schema.json +43 -0
  24. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_benchmark_spec.rb +414 -0
  25. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_spec.rb +605 -0
  26. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/ree_dao_load_agg_test.rb +524 -0
  27. data/lib/ree_lib/packages/ree_logger/package/ree_logger/multi_logger.rb +19 -10
  28. data/lib/ree_lib/packages/ree_logger/spec/ree_logger/multi_logger_spec.rb +10 -0
  29. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory_proxy.rb +6 -3
  30. data/lib/ree_lib/packages/ree_std/.gitignore +0 -0
  31. data/lib/ree_lib/packages/ree_std/.rspec +2 -0
  32. data/lib/ree_lib/packages/ree_std/Package.schema.json +24 -0
  33. data/lib/ree_lib/packages/ree_std/bin/console +5 -0
  34. data/lib/ree_lib/packages/ree_std/package/ree_std/functions/retry_on_fail.rb +46 -0
  35. data/lib/ree_lib/packages/ree_std/package/ree_std/retry.rb +67 -0
  36. data/lib/ree_lib/packages/ree_std/package/ree_std.rb +6 -0
  37. data/lib/ree_lib/packages/ree_std/schemas/ree_std/functions/retry_on_fail.schema.json +38 -0
  38. data/lib/ree_lib/packages/ree_std/spec/package_schema_spec.rb +14 -0
  39. data/lib/ree_lib/packages/ree_std/spec/ree_std/functions/retry_on_fail_spec.rb +97 -0
  40. data/lib/ree_lib/packages/ree_std/spec/spec_helper.rb +3 -0
  41. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_request_body_schema.rb +5 -0
  42. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_serializer_schema.rb +5 -0
  43. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_endpoint_schema_spec.rb +4 -2
  44. data/lib/ree_lib/packages/ree_swagger/spec/functions/build_request_body_spec.rb +4 -2
  45. data/lib/ree_lib/version.rb +1 -1
  46. metadata +38 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c09a8508f0d27f47f70238fbd1dad1c5627c6082f575d703c509a831c67385f
4
- data.tar.gz: 297458d5b314777ce81af4d077e97fdcddc7985bf947ff0e33d7d07635a68718
3
+ metadata.gz: 4a53010ba7fdd43f86e011e0ee3f90675bb71e1b7f0c66d127736918ec89f6f0
4
+ data.tar.gz: 739eeb996f5ebfff231c613b5a6fd13022a4e91c5fa05716902dbd37d32f4d26
5
5
  SHA512:
6
- metadata.gz: 7804922d52fc7d3d6b203d58cfbfa63b0d87df69655537edc85b70b01d1e4bba88ed73459bad71e0c1f10ebd6d5ffcbb6d5c86c231b0c817038ed5cb6eba48a3
7
- data.tar.gz: ecd43b3975300c865644f617d7235f7d7868b945c9ca5a8f61e8bd2e939faa0214283d66aa883ad85bcba9ce365cfacd723a020eda31027991c74a4919e992b5
6
+ metadata.gz: f3a66d7108179a12e92fc5b36eb1adaaff37a733760f02e8867bcd949b9507b966161c4cb245da9d308de3d6066d8e6990ebd81b7a0d76a3e52e6fca02b75fd3
7
+ data.tar.gz: 5008628b066547548f69f3690d14e3103756b01573d3be8eb001450538c76a88c4adf3ebfec0ae36b5b47c13af9f598264d11a50c3a54f8eca0f3a630039563c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.49)
4
+ ree_lib (1.0.50)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -28,6 +28,8 @@ GEM
28
28
  crass (1.0.6)
29
29
  debug_inspector (1.1.0)
30
30
  diff-lcs (1.5.0)
31
+ faker (3.2.0)
32
+ i18n (>= 1.8.11, < 2)
31
33
  hashdiff (1.0.1)
32
34
  highline (2.0.3)
33
35
  i18n (1.12.0)
@@ -36,8 +38,6 @@ GEM
36
38
  crass (~> 1.0.2)
37
39
  nokogiri (>= 1.5.9)
38
40
  msgpack (1.6.0)
39
- nokogiri (1.15.2-x86_64-darwin)
40
- racc (~> 1.4)
41
41
  nokogiri (1.15.2-x86_64-linux)
42
42
  racc (~> 1.4)
43
43
  oj (3.13.23)
@@ -87,6 +87,7 @@ PLATFORMS
87
87
 
88
88
  DEPENDENCIES
89
89
  bootsnap
90
+ faker (~> 3.2)
90
91
  pg (~> 1.4.1)
91
92
  rack-test
92
93
  rake (~> 13.0)
@@ -78,6 +78,10 @@
78
78
  "name": "ree_routes",
79
79
  "schema": "packages/ree_routes/Package.schema.json"
80
80
  },
81
+ {
82
+ "name": "ree_std",
83
+ "schema": "packages/ree_std/Package.schema.json"
84
+ },
81
85
  {
82
86
  "name": "ree_string",
83
87
  "schema": "packages/ree_string/Package.schema.json"
@@ -150,23 +150,30 @@ RSpec.describe ReeActions::DSL, type: [:autoclean] do
150
150
  user = ReeActionsTest::User.new(name: 'John', age: 30)
151
151
  users_dao.put(user)
152
152
 
153
- thr = Thread.new {
154
- user2 = ReeActionsTest::User.new(name: 'Alex', age: 33)
155
- users_dao.put(user2)
156
- }
153
+ Thread.new do
154
+ users_dao.put(ReeActionsTest::User.new(name: 'Alex', age: 33))
155
+ end.join
157
156
 
158
- thr.join
157
+ Thread.new do
158
+ users_dao.put(ReeActionsTest::User.new(name: 'David', age: 21))
159
+
160
+ Thread.new do
161
+ users_dao.put(ReeActionsTest::User.new(name: 'Sam', age: 19))
162
+ end.join
163
+ end.join
159
164
 
160
- $thread_group_cache = ReeDao::DaoCache.new.instance_variable_get(:@thread_groups)
161
- .dig(Thread.current.group.object_id, :users)
165
+ $thread_cache = ReeDao::DaoCache.new.instance_variable_get(:@threads)
166
+ .dig(Thread.current.object_id, :users)
162
167
 
163
168
  attrs[:user_id]
164
169
  end
165
170
  end
166
171
  end
167
172
 
168
- ReeActionsTest::TestAction3.new.call('user_access', {user_id: 1})
169
- expect($thread_group_cache.keys.count).to_not eq(0)
170
- expect($thread_group_cache.keys.count).to eq(2)
173
+ Thread.new do
174
+ ReeActionsTest::TestAction3.new.call('user_access', {user_id: 1})
175
+ end.join
176
+ expect($thread_cache.keys.count).to_not eq(0)
177
+ expect($thread_cache.keys.count).to eq(4)
171
178
  }
172
179
  end
@@ -16,6 +16,9 @@
16
16
  {
17
17
  "name": "ree_enum"
18
18
  },
19
+ {
20
+ "name": "ree_hash"
21
+ },
19
22
  {
20
23
  "name": "ree_mapper"
21
24
  },
@@ -93,6 +96,13 @@
93
96
  "fn"
94
97
  ]
95
98
  },
99
+ {
100
+ "name": "load_agg",
101
+ "schema": "packages/ree_dao/schemas/ree_dao/functions/load_agg.schema.json",
102
+ "tags": [
103
+ "fn"
104
+ ]
105
+ },
96
106
  {
97
107
  "name": "one_to_many",
98
108
  "schema": "packages/ree_dao/schemas/ree_dao/functions/one_to_many.schema.json",
@@ -0,0 +1,26 @@
1
+ module ReeDao
2
+ module AggregateDSL
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ def self.extended(base)
8
+ base.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def aggregate(name, &proc)
13
+ dsl = Ree::ObjectDsl.new(
14
+ Ree.container.packages_facade, name, self, :fn
15
+ )
16
+
17
+ dsl.instance_exec(&proc) if block_given?
18
+ dsl.tags(["aggregate"])
19
+ dsl.freeze(false)
20
+ dsl.object.set_as_compiled(false)
21
+
22
+ Ree.container.compile(dsl.package, name)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,311 @@
1
+ module ReeDao
2
+ class Association
3
+ include Ree::LinkDSL
4
+
5
+ link :demodulize, from: :ree_string
6
+ link :group_by, from: :ree_array
7
+ link :index_by, from: :ree_array
8
+ link :underscore, from: :ree_string
9
+
10
+ attr_reader :parent, :list, :global_opts
11
+
12
+ contract(ReeDao::Associations, Array, Ksplat[RestKeys => Any] => Any)
13
+ def initialize(parent, list, **global_opts)
14
+ @parent = parent
15
+ @list = list
16
+ @global_opts = global_opts
17
+ end
18
+
19
+ contract(
20
+ Or[:belongs_to, :has_one, :has_many, :field],
21
+ Symbol,
22
+ Ksplat[RestKeys => Any],
23
+ Optblock => Array
24
+ )
25
+ def load(assoc_type, assoc_name, **opts, &block)
26
+ load_association(assoc_type, assoc_name, **opts, &block)
27
+ end
28
+
29
+ contract(
30
+ Or[:belongs_to, :has_one, :has_many, :field],
31
+ Symbol,
32
+ Ksplat[RestKeys => Any],
33
+ Optblock => Nilor[Array]
34
+ )
35
+ def load_association(assoc_type, assoc_name, **opts, &block)
36
+ assoc_index = load_association_by_type(
37
+ assoc_type,
38
+ assoc_name,
39
+ **opts
40
+ )
41
+
42
+ process_block(assoc_index, opts[:autoload_children] ||= false, &block) if block_given?
43
+
44
+ list
45
+ end
46
+
47
+ contract(
48
+ Or[:belongs_to, :has_one, :has_many, :field],
49
+ Symbol,
50
+ Ksplat[RestKeys => Any] => Any
51
+ )
52
+ def load_association_by_type(type, assoc_name, **opts)
53
+ case type
54
+ when :belongs_to
55
+ one_to_one(
56
+ assoc_name,
57
+ list,
58
+ scope: opts[:scope],
59
+ foreign_key: opts[:foreign_key],
60
+ setter: opts[:setter],
61
+ reverse: false
62
+ )
63
+ when :has_one
64
+ one_to_one(
65
+ assoc_name,
66
+ list,
67
+ scope: opts[:scope],
68
+ foreign_key: opts[:foreign_key],
69
+ setter: opts[:setter],
70
+ reverse: true
71
+ )
72
+ when :has_many
73
+ one_to_many(
74
+ assoc_name,
75
+ list,
76
+ scope: opts[:scope],
77
+ foreign_key: opts[:foreign_key],
78
+ setter: opts[:setter]
79
+ )
80
+ else
81
+ one_to_many(
82
+ assoc_name,
83
+ list,
84
+ scope: opts[:scope],
85
+ foreign_key: opts[:foreign_key],
86
+ setter: opts[:setter],
87
+ skip_dao: true
88
+ )
89
+ end
90
+ end
91
+
92
+ contract(Hash, Bool, Block => Any)
93
+ def process_block(assoc, autoload_children, &block)
94
+ assoc_list = assoc.values.flatten
95
+
96
+ if ReeDao::Associations.sync_mode?
97
+ ReeDao::Associations.new(
98
+ parent.agg_caller,
99
+ assoc_list,
100
+ parent.local_vars,
101
+ autoload_children,
102
+ **global_opts
103
+ ).instance_exec(assoc_list, &block)
104
+ else
105
+ ReeDao::Associations.new(
106
+ parent.agg_caller,
107
+ assoc_list,
108
+ parent.local_vars,
109
+ autoload_children,
110
+ **global_opts
111
+ ).instance_exec(assoc_list, &block).map(&:join)
112
+ end
113
+ end
114
+
115
+ contract(
116
+ Symbol,
117
+ Array,
118
+ Kwargs[
119
+ foreign_key: Nilor[Symbol],
120
+ scope: Nilor[Sequel::Dataset],
121
+ setter: Nilor[Or[Symbol, Proc]],
122
+ reverse: Bool
123
+ ] => Hash
124
+ )
125
+ def one_to_one(
126
+ assoc_name,
127
+ list,
128
+ scope: nil,
129
+ foreign_key: nil,
130
+ setter: nil,
131
+ reverse: true
132
+ )
133
+ return {} if list.empty?
134
+
135
+ assoc_dao = find_dao(assoc_name, parent, scope)
136
+
137
+ if reverse
138
+ if !foreign_key
139
+ name = underscore(demodulize(list.first.class.name))
140
+ foreign_key = "#{name}_id".to_sym
141
+ end
142
+
143
+ root_ids = list.map(&:id).uniq
144
+ else
145
+ if !foreign_key
146
+ dto_class = assoc_dao
147
+ .opts[:schema_mapper]
148
+ .dto(:db_load)
149
+
150
+ name = underscore(demodulize(dto_class.name))
151
+
152
+ root_ids = list.map(&:"#{"#{name}_id".to_sym}").uniq
153
+ foreign_key = :id
154
+ else
155
+ root_ids = list.map(&:"#{foreign_key}")
156
+ foreign_key = :id
157
+ end
158
+ end
159
+
160
+ default_scope = assoc_dao&.where(foreign_key => root_ids)
161
+
162
+ items = add_scopes(default_scope, scope, global_opts[assoc_name])
163
+
164
+ assoc = index_by(items) { _1.send(foreign_key) }
165
+
166
+ populate_association(
167
+ list,
168
+ assoc,
169
+ assoc_name,
170
+ setter: setter,
171
+ reverse: reverse
172
+ )
173
+
174
+ assoc
175
+ end
176
+
177
+ contract(
178
+ Symbol,
179
+ Array,
180
+ Kwargs[
181
+ foreign_key: Nilor[Symbol],
182
+ scope: Nilor[Sequel::Dataset],
183
+ setter: Nilor[Or[Symbol, Proc]],
184
+ skip_dao: Bool
185
+ ] => Hash
186
+ )
187
+ def one_to_many(
188
+ assoc_name,
189
+ list,
190
+ foreign_key: nil,
191
+ scope: nil,
192
+ setter: nil,
193
+ skip_dao: false
194
+ )
195
+ return {} if list.empty?
196
+
197
+ assoc_dao = nil
198
+ assoc_dao = find_dao(assoc_name, parent, scope) if !skip_dao
199
+
200
+ foreign_key ||= "#{underscore(demodulize(list.first.class.name))}_id".to_sym
201
+
202
+ root_ids = list.map(&:id)
203
+
204
+ default_scope = assoc_dao&.where(foreign_key => root_ids)
205
+
206
+ items = add_scopes(default_scope, scope, global_opts[assoc_name])
207
+
208
+ assoc = group_by(items) { _1.send(foreign_key) }
209
+
210
+ populate_association(
211
+ list,
212
+ assoc,
213
+ assoc_name,
214
+ setter: setter
215
+ )
216
+
217
+ assoc
218
+ end
219
+
220
+ contract(
221
+ Array,
222
+ Hash,
223
+ Symbol,
224
+ Kwargs[
225
+ reverse: Nilor[Bool],
226
+ setter: Nilor[Or[Symbol, Proc]]
227
+ ] => Any
228
+ )
229
+ def populate_association(
230
+ list,
231
+ association_index,
232
+ assoc_name,
233
+ reverse: nil,
234
+ setter: nil
235
+ )
236
+ assoc_setter = if setter
237
+ setter
238
+ else
239
+ "set_#{assoc_name}"
240
+ end
241
+
242
+ list.each do |item|
243
+ if setter && setter.is_a?(Proc)
244
+ self.instance_exec(item, association_index, &assoc_setter)
245
+ else
246
+ key = if reverse.nil?
247
+ :id
248
+ else
249
+ reverse ? :id : "#{assoc_name}_id"
250
+ end
251
+ value = association_index[item.send(key)]
252
+ next if value.nil?
253
+
254
+ item.send(assoc_setter, value)
255
+ end
256
+ end
257
+ end
258
+
259
+ contract(Nilor[Sequel::Dataset], Nilor[Sequel::Dataset], Nilor[Proc] => Array)
260
+ def add_scopes(default_scope, scope, named_scope)
261
+ if default_scope && !scope
262
+ res = default_scope
263
+ end
264
+
265
+ if default_scope && scope
266
+ if scope == []
267
+ res = default_scope
268
+ else
269
+ res = merge_scopes(default_scope, scope)
270
+ end
271
+ end
272
+
273
+ if !default_scope && scope
274
+ return [] if scope.empty?
275
+
276
+ res = scope
277
+ end
278
+
279
+ if named_scope
280
+ res = named_scope.call(res)
281
+ end
282
+
283
+ res.all
284
+ end
285
+
286
+ def merge_scopes(s1, s2)
287
+ if s2.opts[:where]
288
+ s1 = s1.where(s2.opts[:where])
289
+ end
290
+
291
+ if s2.opts[:order]
292
+ s1 = s1.order(*s2.opts[:order])
293
+ end
294
+
295
+ s1
296
+ end
297
+
298
+ def find_dao(assoc_name, parent, scope)
299
+ dao_from_name = parent.instance_variable_get("@#{assoc_name}") || parent.instance_variable_get("@#{assoc_name}s")
300
+ return dao_from_name if dao_from_name
301
+
302
+ raise ArgumentError, "can't find DAO for :#{assoc_name}, provide correct scope or association name" if scope.nil?
303
+
304
+ table_name = scope.first_source_table
305
+ dao_from_scope = parent.instance_variable_get("@#{table_name}")
306
+ return dao_from_scope if dao_from_scope
307
+
308
+ raise ArgumentError, "can't find DAO for :#{assoc_name}, provide correct scope or association name"
309
+ end
310
+ end
311
+ end
@@ -0,0 +1,148 @@
1
+ module ReeDao
2
+ class Associations
3
+ include Ree::LinkDSL
4
+
5
+ attr_reader :agg_caller, :list, :local_vars, :only, :except, :autoload_children, :global_opts
6
+
7
+ def initialize(agg_caller, list, local_vars, autoload_children = false, **opts)
8
+ @agg_caller = agg_caller
9
+ @list = list
10
+ @local_vars = local_vars
11
+ @threads = [] if !self.class.sync_mode?
12
+ @global_opts = opts
13
+ @only = opts[:only] if opts[:only]
14
+ @except = opts[:except] if opts[:except]
15
+ @autoload_children = autoload_children
16
+
17
+ raise ArgumentError.new("you can't use both :only and :except arguments at the same time") if @only && @except
18
+
19
+ local_vars.each do |k, v|
20
+ instance_variable_set(k, v)
21
+
22
+ self.class.define_method k.to_s.gsub('@', '') do
23
+ v
24
+ end
25
+ end
26
+ end
27
+
28
+ def self.sync_mode?
29
+ ReeDao.load_sync_associations_enabled?
30
+ end
31
+
32
+ contract(
33
+ Symbol,
34
+ Ksplat[
35
+ scope?: Sequel::Dataset,
36
+ setter?: Or[Symbol, Proc],
37
+ foreign_key?: Symbol,
38
+ autoload_children?: Bool
39
+ ],
40
+ Optblock => Any
41
+ )
42
+ def belongs_to(assoc_name, **opts, &block)
43
+ association(__method__, assoc_name, **opts, &block)
44
+ end
45
+
46
+ contract(
47
+ Symbol,
48
+ Ksplat[
49
+ scope?: Sequel::Dataset,
50
+ setter?: Or[Symbol, Proc],
51
+ foreign_key?: Symbol,
52
+ autoload_children?: Bool
53
+ ],
54
+ Optblock => Any
55
+ )
56
+ def has_one(assoc_name, **opts, &block)
57
+ association(__method__, assoc_name, **opts, &block)
58
+ end
59
+
60
+ contract(
61
+ Symbol,
62
+ Ksplat[
63
+ scope?: Sequel::Dataset,
64
+ setter?: Or[Symbol, Proc],
65
+ foreign_key?: Symbol,
66
+ autoload_children?: Bool
67
+ ],
68
+ Optblock => Any
69
+ )
70
+ def has_many(assoc_name, **opts, &block)
71
+ association(__method__, assoc_name, **opts, &block)
72
+ end
73
+
74
+ contract(
75
+ Symbol,
76
+ Ksplat[
77
+ scope?: Sequel::Dataset,
78
+ setter?: Or[Symbol, Proc],
79
+ foreign_key?: Symbol,
80
+ autoload_children?: Bool
81
+ ],
82
+ Optblock => Any
83
+ )
84
+ def field(assoc_name, **opts, &block)
85
+ association(__method__, assoc_name, **opts, &block)
86
+ end
87
+
88
+ private
89
+
90
+ contract(
91
+ Or[
92
+ :belongs_to,
93
+ :has_one,
94
+ :has_many,
95
+ :field
96
+ ],
97
+ Symbol,
98
+ Ksplat[
99
+ scope?: Sequel::Dataset,
100
+ setter?: Or[Symbol, Proc],
101
+ foreign_key?: Symbol,
102
+ autoload_children?: Bool
103
+ ],
104
+ Optblock => Any
105
+ )
106
+ def association(assoc_type, assoc_name, **assoc_opts, &block)
107
+ if self.class.sync_mode?
108
+ return if association_is_not_included?(assoc_name)
109
+
110
+ association = Association.new(self, list, **global_opts)
111
+ association.load(assoc_type, assoc_name, **assoc_opts, &block)
112
+ else
113
+ return @threads if association_is_not_included?(assoc_name)
114
+
115
+ @threads << Thread.new do
116
+ association = Association.new(self, list, **global_opts)
117
+ association.load(assoc_type, assoc_name, **assoc_opts, &block)
118
+ end
119
+ end
120
+ end
121
+
122
+ contract(Symbol => Bool)
123
+ def association_is_not_included?(assoc_name)
124
+ return false if !only && !except
125
+
126
+ if only
127
+ return false if only && only.include?(assoc_name)
128
+
129
+ if only && !only.include?(assoc_name)
130
+ return false if autoload_children
131
+ return true
132
+ end
133
+ end
134
+
135
+ if except
136
+ return true if except && except.include?(assoc_name)
137
+ return false if except && !except.include?(assoc_name)
138
+ end
139
+ end
140
+
141
+ contract(Symbol, SplatOf[Any], Optblock => Any)
142
+ def method_missing(method, *args, &block)
143
+ return super if !agg_caller.private_methods(false).include?(method)
144
+
145
+ agg_caller.send(method, *args, &block)
146
+ end
147
+ end
148
+ end
@@ -9,48 +9,69 @@ class ReeDao::DaoCache
9
9
  end
10
10
 
11
11
  def setup
12
- @thread_groups = {}
12
+ @threads = {}
13
13
  end
14
14
 
15
- def add_thread_group_cache(thread_group)
16
- @thread_groups[thread_group.object_id] ||= {}
15
+ def add_thread_cache(thread)
16
+ @threads[get_thread_object_id(thread)] ||= {}
17
17
  end
18
18
 
19
- def drop_thread_group_cache(thread_group)
20
- @thread_groups.delete(thread_group.object_id)
19
+ def drop_thread_cache(thread)
20
+ @threads.delete(get_thread_object_id(thread))
21
21
  end
22
22
 
23
23
  def get(table_name, primary_key)
24
- add_thread_group_cache(current_thread_group)
24
+ add_thread_cache(current_thread)
25
25
  add_table_name(table_name)
26
26
 
27
- @thread_groups[current_thread_group.object_id][table_name][primary_key]
27
+ @threads[current_thread_object_id][table_name][primary_key]
28
28
  end
29
29
 
30
30
  def set(table_name, primary_key, data)
31
- add_thread_group_cache(current_thread_group)
31
+ add_thread_cache(current_thread)
32
32
  add_table_name(table_name)
33
33
  add_primary_key(table_name, primary_key)
34
34
 
35
- @thread_groups[current_thread_group.object_id][table_name][primary_key] = deep_dup(data)
35
+ @threads[current_thread_object_id][table_name][primary_key] = deep_dup(data)
36
36
  end
37
37
 
38
- def drop_table_cache(table_name)
39
- add_thread_group_cache(current_thread_group)
40
- @thread_groups[current_thread_group.object_id].delete(table_name)
38
+ private
39
+
40
+ def get_thread_object_id(thread)
41
+ thread.parent == Thread.main ? thread.object_id : get_parent_thread(thread)
41
42
  end
42
43
 
43
- private
44
+ def get_parent_thread(thread)
45
+ return thread.object_id if thread.parent == Thread.main || thread == Thread.main
46
+
47
+ get_parent_thread(thread.parent)
48
+ end
44
49
 
45
- def current_thread_group
46
- Thread.current.group
50
+ def current_thread
51
+ Thread.current
47
52
  end
48
53
 
49
- def add_table_name(thread_group = Thread.current.group, table_name)
50
- @thread_groups[thread_group.object_id][table_name] ||= {}
54
+ def current_thread_object_id
55
+ get_thread_object_id(current_thread)
51
56
  end
52
57
 
53
- def add_primary_key(thread_group = Thread.current.group, table_name, primary_key)
54
- @thread_groups[thread_group.object_id][table_name][primary_key] ||= {}
58
+ def add_table_name(table_name)
59
+ if !@threads[current_thread_object_id]
60
+ @threads[current_thread_object_id] ||= {}
61
+ end
62
+
63
+ @threads[current_thread_object_id][table_name] ||= {}
64
+ end
65
+
66
+ def add_primary_key(table_name, primary_key)
67
+ if !@threads[current_thread_object_id]
68
+ @threads[current_thread_object_id] ||= {}
69
+ end
70
+
71
+ if !@threads[current_thread_object_id][table_name]
72
+ @threads[current_thread_object_id][table_name] ||= {}
73
+ end
74
+
75
+ @threads[current_thread_object_id][table_name][primary_key] ||= {}
55
76
  end
56
77
  end