smart_core 0.6.0 → 0.7.0
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 +4 -4
- data/.rspec +1 -1
- data/.rubocop.yml +1 -1
- data/.travis.yml +5 -8
- data/CHANGELOG.md +5 -0
- data/README.md +14 -4
- data/lib/smart_core.rb +2 -2
- data/lib/smart_core/container.rb +49 -56
- data/lib/smart_core/container/arbitary_lock.rb +22 -0
- data/lib/smart_core/container/definition_dsl.rb +105 -55
- data/lib/smart_core/container/{command_set.rb → definition_dsl/command_set.rb} +20 -26
- data/lib/smart_core/container/definition_dsl/commands.rb +12 -0
- data/lib/smart_core/container/{commands → definition_dsl/commands}/base.rb +3 -3
- data/lib/smart_core/container/definition_dsl/commands/definition/compose.rb +46 -0
- data/lib/smart_core/container/definition_dsl/commands/definition/namespace.rb +51 -0
- data/lib/smart_core/container/{commands → definition_dsl/commands/definition}/register.rb +13 -25
- data/lib/smart_core/container/definition_dsl/commands/instantiation/compose.rb +50 -0
- data/lib/smart_core/container/definition_dsl/commands/instantiation/freeze_state.rb +24 -0
- data/lib/smart_core/container/dependency_compatability.rb +3 -3
- data/lib/smart_core/container/dependency_compatability/definition.rb +42 -0
- data/lib/smart_core/container/dependency_compatability/general.rb +61 -0
- data/lib/smart_core/container/dependency_compatability/registry.rb +28 -29
- data/lib/smart_core/container/dependency_resolver.rb +9 -4
- data/lib/smart_core/container/entities.rb +11 -0
- data/lib/smart_core/container/{entity.rb → entities/base.rb} +7 -7
- data/lib/smart_core/container/entities/dependency.rb +38 -0
- data/lib/smart_core/container/entities/dependency_builder.rb +50 -0
- data/lib/smart_core/container/entities/namespace.rb +73 -0
- data/lib/smart_core/container/entities/namespace_builder.rb +41 -0
- data/lib/smart_core/container/errors.rb +43 -0
- data/lib/smart_core/container/key_guard.rb +5 -5
- data/lib/smart_core/container/mixin.rb +20 -16
- data/lib/smart_core/container/registry.rb +224 -201
- data/lib/smart_core/container/registry_builder.rb +38 -5
- data/lib/smart_core/{exceptions.rb → errors.rb} +0 -0
- data/lib/smart_core/operation.rb +3 -1
- data/lib/smart_core/operation/{custom.rb → callback.rb} +7 -7
- data/lib/smart_core/operation/result.rb +1 -1
- data/lib/smart_core/operation/result_interface.rb +3 -3
- data/lib/smart_core/version.rb +1 -1
- data/smart_core.gemspec +6 -5
- metadata +28 -38
- data/lib/smart_core/container/command_definer.rb +0 -117
- data/lib/smart_core/container/commands.rb +0 -9
- data/lib/smart_core/container/commands/namespace.rb +0 -53
- data/lib/smart_core/container/dependency.rb +0 -44
- data/lib/smart_core/container/dependency_builder.rb +0 -48
- data/lib/smart_core/container/dependency_compatability/abstract.rb +0 -59
- data/lib/smart_core/container/dependency_compatability/command_set.rb +0 -35
- data/lib/smart_core/container/exceptions.rb +0 -31
- data/lib/smart_core/container/memoized_dependency.rb +0 -28
- data/lib/smart_core/container/namespace.rb +0 -51
@@ -1,227 +1,250 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
@access_lock = Mutex.new
|
16
|
-
@registry = {}
|
17
|
-
end
|
3
|
+
# @api private
|
4
|
+
# @since 0.7.0
|
5
|
+
# rubocop:disable Metrics/ClassLength
|
6
|
+
class SmartCore::Container::Registry
|
7
|
+
# @since 0.7.0
|
8
|
+
include Enumerable
|
9
|
+
|
10
|
+
# @return [Hash<Symbol,SmartCore::Container::Entity>]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
# @since 0.7.0
|
14
|
+
attr_reader :registry
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
# @return [void]
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.7.0
|
20
|
+
def initialize
|
21
|
+
@registry = {}
|
22
|
+
@access_lock = SmartCore::Container::ArbitaryLock.new
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
# @param entity_path [String, Symbol]
|
26
|
+
# @return [SmartCore::Container::Entity]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
# @since 0.7.0
|
30
|
+
def resolve(entity_path)
|
31
|
+
thread_safe { fetch_entity(entity_path) }
|
32
|
+
end
|
34
33
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
34
|
+
# @param name [String, Symbol]
|
35
|
+
# @param dependency_definition [Block]
|
36
|
+
# @return [void]
|
37
|
+
#
|
38
|
+
# @api private
|
39
|
+
# @since 0.7.0
|
40
|
+
def register_dependency(name, &dependency_definition)
|
41
|
+
thread_safe { add_dependency(name, dependency_definition) }
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def register(name, **options, &dependency_definition)
|
54
|
-
thread_safe do
|
55
|
-
raise(
|
56
|
-
SmartCore::Container::FrozenRegistryError,
|
57
|
-
'Can not modify frozen registry'
|
58
|
-
) if state_frozen?
|
59
|
-
|
60
|
-
append_dependency(name, dependency_definition, **options)
|
61
|
-
end
|
62
|
-
end
|
44
|
+
# @param name [String, Symbol]
|
45
|
+
# @param dependencies_definition [Block]
|
46
|
+
# @return [void]
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.7.0
|
50
|
+
def register_namespace(name, &dependencies_definition)
|
51
|
+
thread_safe { add_namespace(name, dependencies_definition) }
|
52
|
+
end
|
63
53
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
thread_safe do
|
72
|
-
raise(
|
73
|
-
SmartCore::Container::FrozenRegistryError,
|
74
|
-
'Can not modify frozen registry'
|
75
|
-
) if state_frozen?
|
76
|
-
|
77
|
-
append_namespace(name, dependency_definitions)
|
78
|
-
end
|
79
|
-
end
|
54
|
+
# @return [void]
|
55
|
+
#
|
56
|
+
# @api private
|
57
|
+
# @since 0.7.0
|
58
|
+
def freeze!
|
59
|
+
thread_safe { freeze_state }
|
60
|
+
end
|
80
61
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
end
|
62
|
+
# @return [Boolean]
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
# @since 0.7.0
|
66
|
+
def frozen?
|
67
|
+
thread_safe { state_frozen? }
|
68
|
+
end
|
89
69
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
70
|
+
# @param block [Block]
|
71
|
+
# @return [Enumerable]
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
# @since 0.7.0
|
75
|
+
def each(&block)
|
76
|
+
thread_safe { enumerate(&block) }
|
77
|
+
end
|
97
78
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#
|
108
|
-
# @api private
|
109
|
-
# @since 0.5.0
|
110
|
-
attr_reader :registry
|
111
|
-
|
112
|
-
# @return [Boolean]
|
113
|
-
#
|
114
|
-
# @api private
|
115
|
-
# @since 0.5.0
|
116
|
-
def state_frozen?
|
117
|
-
registry.frozen?
|
118
|
-
end
|
79
|
+
# @return [Hash<String|Symbol,SmartCore::Container::Entities::Base|Any>]
|
80
|
+
#
|
81
|
+
# @api private
|
82
|
+
# @since 0.7.0
|
83
|
+
def hash_tree(resolve_dependencies: false)
|
84
|
+
thread_safe { build_hash_tree(resolve_dependencies: resolve_dependencies) }
|
85
|
+
end
|
86
|
+
alias_method :to_h, :hash_tree
|
87
|
+
alias_method :to_hash, :hash_tree
|
119
88
|
|
120
|
-
|
121
|
-
#
|
122
|
-
# @api private
|
123
|
-
# @since 0.5.0
|
124
|
-
def freeze_state
|
125
|
-
registry.freeze
|
126
|
-
end
|
89
|
+
private
|
127
90
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
def fetch_dependency(dependency_path)
|
134
|
-
# TODO: rabbit style dependnecy path
|
135
|
-
name = indifferently_accessable_name(dependency_path)
|
136
|
-
registry.fetch(name)
|
137
|
-
rescue KeyError
|
138
|
-
raise(
|
139
|
-
SmartCore::Container::UnexistentDependencyError,
|
140
|
-
"Dependencny with '#{name}' name does not exist!"
|
141
|
-
)
|
142
|
-
end
|
91
|
+
# @return [Mutex]
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
# @since 0.7.0
|
95
|
+
attr_reader :lock
|
143
96
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
#
|
152
|
-
# @api private
|
153
|
-
# @since 0.5.0
|
154
|
-
def append_dependency(dependency_name, dependency_definition, **options)
|
155
|
-
dependency_name = indifferently_accessable_name(dependency_name)
|
156
|
-
prevent_namespace_overlap!(dependency_name)
|
157
|
-
dependency = DependencyBuilder.build(dependency_name, dependency_definition, **options)
|
158
|
-
|
159
|
-
registry[dependency_name] = dependency
|
160
|
-
end
|
97
|
+
# @return [Boolean]
|
98
|
+
#
|
99
|
+
# @api private
|
100
|
+
# @since 0.7.0
|
101
|
+
def state_frozen?
|
102
|
+
registry.frozen?
|
103
|
+
end
|
161
104
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
namespace = begin
|
176
|
-
registry.fetch(namespace_name)
|
177
|
-
rescue KeyError
|
178
|
-
registry[namespace_name] = SmartCore::Container::Namespace.new(namespace_name)
|
105
|
+
# @return [Hash<String|Symbol,SmartCore::Container::Entities::Base|Any>]
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
# @since 0.7.0
|
109
|
+
def build_hash_tree(resolve_dependencies: false)
|
110
|
+
{}.tap do |tree|
|
111
|
+
enumerate do |(entity_name, entity)|
|
112
|
+
case entity
|
113
|
+
when SmartCore::Container::Entities::Namespace
|
114
|
+
tree[entity_name] = entity.resolve.hash_tree(resolve_dependencies: resolve_dependencies)
|
115
|
+
when SmartCore::Container::Entities::Dependency
|
116
|
+
tree[entity_name] = resolve_dependencies ? entity.resolve : entity
|
117
|
+
end
|
179
118
|
end
|
180
|
-
# rubocop:enable Layout/RescueEnsureAlignment
|
181
|
-
|
182
|
-
namespace.append_definitions(dependency_definitions)
|
183
119
|
end
|
120
|
+
end
|
184
121
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
122
|
+
# @return [void]
|
123
|
+
#
|
124
|
+
# @api private
|
125
|
+
# @since 0.7.0
|
126
|
+
def freeze_state
|
127
|
+
registry.freeze.tap do
|
128
|
+
enumerate do |(entity_name, entity)|
|
129
|
+
entity.freeze! if entity.is_a?(SmartCore::Container::Entities::Namespace)
|
130
|
+
end
|
194
131
|
end
|
132
|
+
end
|
195
133
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
134
|
+
# @param block
|
135
|
+
# @return [Enumerable]
|
136
|
+
#
|
137
|
+
# @api private
|
138
|
+
# @since 0.7.0
|
139
|
+
def enumerate(&block)
|
140
|
+
block_given? ? registry.each(&block) : registry.each
|
141
|
+
end
|
142
|
+
|
143
|
+
# @paramm entity_path [String, Symbol]
|
144
|
+
# @return [SmartCore::Container::Entity]
|
145
|
+
#
|
146
|
+
# @api private
|
147
|
+
# @since 0.7.0
|
148
|
+
def fetch_entity(entity_path)
|
149
|
+
dependency_name = indifferently_accessable_name(entity_path)
|
150
|
+
registry.fetch(dependency_name)
|
151
|
+
rescue KeyError
|
152
|
+
raise(
|
153
|
+
SmartCore::Container::NonexistentEntityError,
|
154
|
+
"Entity with '#{dependency_name}' name does not exist!"
|
155
|
+
)
|
156
|
+
end
|
157
|
+
|
158
|
+
# @param dependency_name [String, Symbol]
|
159
|
+
# @param dependency_definition [Proc]
|
160
|
+
# @return [SmartCore::Container::Entities::Dependency]
|
161
|
+
#
|
162
|
+
# @raise [SmartCore::Container::DependencyOverNamespaceOverlapError]
|
163
|
+
#
|
164
|
+
# @api private
|
165
|
+
# @since 0.7.0
|
166
|
+
def add_dependency(dependency_name, dependency_definition)
|
167
|
+
if state_frozen?
|
168
|
+
raise(SmartCore::Container::FrozenRegistryError, 'Can not modify frozen registry!')
|
205
169
|
end
|
170
|
+
dependency_name = indifferently_accessable_name(dependency_name)
|
171
|
+
prevent_namespace_overlap!(dependency_name)
|
172
|
+
|
173
|
+
dependency_entity = SmartCore::Container::Entities::DependencyBuilder.build(
|
174
|
+
dependency_name, dependency_definition
|
175
|
+
)
|
206
176
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
177
|
+
dependency_entity.tap { registry[dependency_name] = dependency_entity }
|
178
|
+
end
|
179
|
+
|
180
|
+
# @param namespace_name [String, Symbol]
|
181
|
+
# @param dependencies_definition [Proc]
|
182
|
+
# @return [SmartCore::Container::Entities::Namespace]
|
183
|
+
#
|
184
|
+
# @raise [SmartCore::Container::NamespaceOverDependencyOverlapError]
|
185
|
+
#
|
186
|
+
# @api private
|
187
|
+
# @since 0.7.0
|
188
|
+
def add_namespace(namespace_name, dependencies_definition)
|
189
|
+
if state_frozen?
|
190
|
+
raise(SmartCore::Container::FrozenRegistryError, 'Can not modify frozen registry!')
|
191
|
+
end
|
192
|
+
namespace_name = indifferently_accessable_name(namespace_name)
|
193
|
+
prevent_dependency_overlap!(namespace_name)
|
194
|
+
|
195
|
+
# rubocop:disable Layout/RescueEnsureAlignment
|
196
|
+
namespace_entity = begin
|
197
|
+
fetch_entity(namespace_name)
|
198
|
+
rescue SmartCore::Container::NonexistentEntityError
|
199
|
+
registry[namespace_name] = SmartCore::Container::Entities::NamespaceBuilder.build(
|
200
|
+
namespace_name
|
215
201
|
)
|
216
202
|
end
|
203
|
+
# rubocop:enable Layout/RescueEnsureAlignment
|
217
204
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
205
|
+
namespace_entity.tap { namespace_entity.append_definitions(dependencies_definition) }
|
206
|
+
end
|
207
|
+
|
208
|
+
# @param name [String, Symbol]
|
209
|
+
# @return [void]
|
210
|
+
#
|
211
|
+
# @see [SmartCore::Container::KeyGuard]
|
212
|
+
#
|
213
|
+
# @api private
|
214
|
+
# @since 0.7.0
|
215
|
+
def indifferently_accessable_name(name)
|
216
|
+
SmartCore::Container::KeyGuard.indifferently_accessable_key(name)
|
217
|
+
end
|
218
|
+
|
219
|
+
# @param dependency_name [String]
|
220
|
+
# @return [void]
|
221
|
+
#
|
222
|
+
# @api private
|
223
|
+
# @since 0.7.0
|
224
|
+
def prevent_namespace_overlap!(dependency_name)
|
225
|
+
SmartCore::Container::DependencyCompatability::Registry.prevent_namespace_overlap!(
|
226
|
+
self, dependency_name
|
227
|
+
)
|
228
|
+
end
|
229
|
+
|
230
|
+
# @param namespace_name [String]
|
231
|
+
# @return [void]
|
232
|
+
#
|
233
|
+
# @api private
|
234
|
+
# @since 0.7.0
|
235
|
+
def prevent_dependency_overlap!(namespace_name)
|
236
|
+
SmartCore::Container::DependencyCompatability::Registry.prevent_dependency_overlap!(
|
237
|
+
self, namespace_name
|
238
|
+
)
|
239
|
+
end
|
240
|
+
|
241
|
+
# @param block [Proc]
|
242
|
+
# @return [Any]
|
243
|
+
#
|
244
|
+
# @api private
|
245
|
+
# @since 0.7.0
|
246
|
+
def thread_safe(&block)
|
247
|
+
@access_lock.thread_safe(&block)
|
226
248
|
end
|
227
249
|
end
|
250
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -1,18 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# @api private
|
4
|
-
# @since 0.
|
4
|
+
# @since 0.7.0
|
5
5
|
module SmartCore::Container::RegistryBuilder
|
6
|
+
# rubocop:disable Metrics/LineLength
|
6
7
|
class << self
|
7
|
-
# @
|
8
|
+
# @parma container [SmartCore::Container]
|
9
|
+
# @option ignored_definition_commands [Array<Class::SmartCore::Container::DefinitionDSL::Commands::Base>>]
|
10
|
+
# @option ignored_instantiation_commands [Array<Class::SmartCore::Container::DefinitionDSL::Commands::Base>>]
|
8
11
|
# @return [SmartCore::Container::Registry]
|
9
12
|
#
|
10
13
|
# @api private
|
11
|
-
# @since 0.
|
12
|
-
def build(
|
14
|
+
# @since 0.7.0
|
15
|
+
def build(container, ignored_definition_commands: [], ignored_instantiation_commands: [])
|
13
16
|
SmartCore::Container::Registry.new.tap do |registry|
|
14
|
-
|
17
|
+
build_definitions(container.class, registry, ignored_commands: ignored_definition_commands)
|
18
|
+
build_state(container.class, registry, ignored_commands: ignored_instantiation_commands)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param container_klass [Class<SmartCore::Container>]
|
23
|
+
# @param registry [SmartCore::Container::Registry]
|
24
|
+
# @option ignored_commands [Array<Class<SmartCore::Container::DefinitionDSL::Commands::Base>>]
|
25
|
+
# @return [void]
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
# @since 0.7.0
|
29
|
+
def build_definitions(container_klass, registry, ignored_commands: [])
|
30
|
+
container_klass.__container_definition_commands__.each do |command|
|
31
|
+
next if ignored_commands.include?(command.class)
|
32
|
+
command.call(registry)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @param container_klass [Class<SmartCore::Container>]
|
37
|
+
# @param registry [SmartCore::Container::Registry]
|
38
|
+
# @option ignored_commands [Array<Class<SmartCore::Container::DefinitionDSL::Commands::Base>>]
|
39
|
+
# @return [void]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.7.0
|
43
|
+
def build_state(container_klass, registry, ignored_commands: [])
|
44
|
+
container_klass.__container_instantiation_commands__.each do |command|
|
45
|
+
next if ignored_commands.include?(command.class)
|
46
|
+
command.call(registry)
|
15
47
|
end
|
16
48
|
end
|
17
49
|
end
|
50
|
+
# rubocop:enable Metrics/LineLength
|
18
51
|
end
|