Skip to content

Commit 24405f8

Browse files
authored
Merge pull request #695 from Cygnetise/memory_optimisations
Reduce the retained memory when defining the relation readers
2 parents 4676769 + a39ac5c commit 24405f8

File tree

3 files changed

+50
-24
lines changed

3 files changed

+50
-24
lines changed

core/lib/rom/plugins/relation/registry_reader.rb

+2-15
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ class RegistryReader < ::Module
1414
EMPTY_REGISTRY = RelationRegistry.build(EMPTY_HASH).freeze
1515

1616
# @api private
17-
attr_reader :relations
18-
19-
# @api private
20-
def initialize(relations:)
21-
@relations = relations
22-
define_readers!
17+
def initialize(klass:, relation_readers_module:)
18+
klass.include relation_readers_module
2319
end
2420

2521
# @api private
@@ -29,15 +25,6 @@ def included(klass)
2925

3026
klass.option :__registry__, default: -> { EMPTY_REGISTRY }
3127
end
32-
33-
private
34-
35-
# @api private
36-
def define_readers!
37-
relations.each do |name|
38-
define_method(name) { __registry__[name] }
39-
end
40-
end
4128
end
4229
end
4330
end

core/lib/rom/setup/finalize/finalize_relations.rb

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ class Finalize
99
class FinalizeRelations
1010
attr_reader :notifications
1111

12+
module BuildRelationReaders
13+
def self.build(relations)
14+
Module.new do
15+
relations.each do |name|
16+
define_method(name) do
17+
__registry__[name]
18+
end
19+
end
20+
end
21+
end
22+
end
23+
1224
# Build relation registry of specified descendant classes
1325
#
1426
# This is used by the setup
@@ -30,6 +42,7 @@ def initialize(gateways, relation_classes, notifications:, mappers: nil, plugins
3042
# @api private
3143
def run!
3244
relation_registry = RelationRegistry.new do |registry, relations|
45+
relation_readers_module = BuildRelationReaders.build(relation_names)
3346
@relation_classes.each do |klass|
3447
unless klass.adapter
3548
raise MissingAdapterIdentifierError,
@@ -43,7 +56,7 @@ def run!
4356
"Relation with name #{key.inspect} registered more than once"
4457
end
4558

46-
klass.use(:registry_reader, relations: relation_names)
59+
klass.use(:registry_reader, klass: klass, relation_readers_module: relation_readers_module)
4760

4861
notifications.trigger('configuration.relations.class.ready', relation: klass, adapter: klass.adapter)
4962

repository/lib/rom/repository/relation_reader.rb

+34-8
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,50 @@ module ROM
44
class Repository
55
# @api private
66
class RelationReader < Module
7+
extend Dry::Core::ClassAttributes
8+
79
# @api private
810
attr_reader :klass
911

1012
# @api private
1113
attr_reader :relations
1214

15+
defines :relation_readers
16+
17+
defines :mutex
18+
mutex(Mutex.new)
19+
20+
defines :relation_cache
21+
relation_cache(Concurrent::Hash.new)
22+
1323
module InstanceMethods
1424
# @api private
1525
def set_relation(name)
1626
container
1727
.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)
2034
end
2135
end
2236

37+
# @api private
38+
def mutex
39+
ROM::Repository::RelationReader.mutex
40+
end
41+
2342
# @api private
2443
def initialize(klass, relations)
25-
@klass = klass
2644
@relations = relations
27-
define_readers!
45+
mutex.synchronize do
46+
unless self.class.relation_readers
47+
self.class.relation_readers(build_relation_readers(relations, self.class.relation_cache))
48+
end
49+
end
50+
klass.include self.class.relation_readers
2851
end
2952

3053
# @api private
@@ -33,13 +56,16 @@ def included(klass)
3356
klass.include(InstanceMethods)
3457
end
3558

59+
3660
private
3761

3862
# @api private
39-
def define_readers!
40-
relations.each do |name|
41-
define_method(name) do
42-
@relations[name] ||= set_relation(name)
63+
def build_relation_readers(relations, relation_cache)
64+
Module.new do
65+
relations.each do |name|
66+
define_method(name) do
67+
relation_reader(name, relation_cache)
68+
end
4369
end
4470
end
4571
end

0 commit comments

Comments
 (0)