@@ -4,28 +4,53 @@ module ROM
4
4
class Repository
5
5
# @api private
6
6
class RelationReader < ::Module
7
+ extend ::Dry ::Core ::ClassAttributes
8
+
7
9
# @api private
8
10
attr_reader :klass
9
11
10
12
# @api private
11
13
attr_reader :relations
12
14
15
+ defines :relation_readers
16
+
17
+ defines :mutex
18
+ mutex ( Mutex . new )
19
+
20
+ defines :relation_cache
21
+ relation_cache ( Concurrent ::Hash . new )
22
+
13
23
module InstanceMethods
14
24
# @api private
15
25
def set_relation ( name ) # rubocop:disable Naming/AccessorMethodName
16
26
container
17
27
. relations [ name ]
18
- . with ( auto_struct : auto_struct )
19
- . struct_namespace ( struct_namespace )
28
+ . with ( auto_struct : auto_struct , struct_namespace : struct_namespace )
29
+ end
30
+
31
+ def relation_reader ( name , relation_cache )
32
+ key = [ name , auto_struct , struct_namespace ]
33
+ relation_cache [ key ] ||= set_relation ( name )
20
34
end
21
35
end
22
36
37
+ # @api private
38
+ def mutex
39
+ ROM ::Repository ::RelationReader . mutex
40
+ end
41
+
23
42
# @api private
24
43
def initialize ( klass , relations )
25
44
super ( )
26
- @klass = klass
27
45
@relations = relations
28
- define_readers!
46
+ mutex . synchronize do
47
+ unless self . class . relation_readers
48
+ self . class . relation_readers (
49
+ build_relation_readers ( relations , self . class . relation_cache )
50
+ )
51
+ end
52
+ end
53
+ klass . include self . class . relation_readers
29
54
end
30
55
31
56
# @api private
@@ -37,10 +62,12 @@ def included(klass)
37
62
private
38
63
39
64
# @api private
40
- def define_readers!
41
- relations . each do |name |
42
- define_method ( name ) do
43
- @relations [ name ] ||= set_relation ( name )
65
+ def build_relation_readers ( relations , relation_cache )
66
+ Module . new do
67
+ relations . each do |name |
68
+ define_method ( name ) do
69
+ relation_reader ( name , relation_cache )
70
+ end
44
71
end
45
72
end
46
73
end
0 commit comments