smart_container 0.4.0 → 0.8.1
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/.rubocop.yml +2 -2
- data/.travis.yml +6 -5
- data/CHANGELOG.md +32 -0
- data/Gemfile.lock +46 -31
- data/README.md +248 -4
- data/Rakefile +2 -1
- data/lib/smart_core/container.rb +132 -7
- data/lib/smart_core/container/{arbitary_lock.rb → arbitrary_lock.rb} +1 -1
- data/lib/smart_core/container/definition_dsl.rb +2 -2
- data/lib/smart_core/container/definition_dsl/command_set.rb +1 -1
- data/lib/smart_core/container/definition_dsl/commands/definition/register.rb +1 -1
- data/lib/smart_core/container/dependency_resolver.rb +80 -6
- data/lib/smart_core/container/dependency_watcher.rb +151 -0
- data/lib/smart_core/container/dependency_watcher/observer.rb +46 -0
- data/lib/smart_core/container/entities/dependency.rb +3 -1
- data/lib/smart_core/container/entities/dependency_builder.rb +27 -59
- data/lib/smart_core/container/entities/memoized_dependency.rb +4 -2
- data/lib/smart_core/container/entities/namespace.rb +23 -6
- data/lib/smart_core/container/entities/namespace_builder.rb +14 -34
- data/lib/smart_core/container/host.rb +77 -0
- data/lib/smart_core/container/mixin.rb +2 -2
- data/lib/smart_core/container/registry.rb +15 -6
- data/lib/smart_core/container/version.rb +2 -2
- data/smart_container.gemspec +5 -5
- metadata +15 -12
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.8.0
|
5
|
+
class SmartCore::Container::DependencyWatcher::Observer
|
6
|
+
# @param container [SmartCore::Container]
|
7
|
+
# @param dependency_path [String]
|
8
|
+
# @param callback [Proc]
|
9
|
+
# @return [void]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.8.0
|
13
|
+
def initialize(container, dependency_path, callback)
|
14
|
+
@container = container
|
15
|
+
@dependency_path = dependency_path
|
16
|
+
@callback = callback
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [void]
|
20
|
+
#
|
21
|
+
# @api private
|
22
|
+
# @since 0.8.0
|
23
|
+
def notify!
|
24
|
+
callback.call(dependency_path, container)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @return [SmartCore::Container]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.8.0
|
33
|
+
attr_reader :container
|
34
|
+
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
# @since 0.8.0
|
39
|
+
attr_reader :dependency_path
|
40
|
+
|
41
|
+
# @return [Proc]
|
42
|
+
#
|
43
|
+
# @api private
|
44
|
+
# @since 0.8.0
|
45
|
+
attr_reader :callback
|
46
|
+
end
|
@@ -20,11 +20,13 @@ class SmartCore::Container::Entities::Dependency < SmartCore::Container::Entitie
|
|
20
20
|
@dependency_definition = dependency_definition
|
21
21
|
end
|
22
22
|
|
23
|
+
# @param host_container [SmartCore::Container, NilClass]
|
23
24
|
# @return [Any]
|
24
25
|
#
|
25
26
|
# @api private
|
26
27
|
# @since 0.1.0
|
27
|
-
|
28
|
+
# @version 0.8.1
|
29
|
+
def reveal(host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
28
30
|
dependency_definition.call
|
29
31
|
end
|
30
32
|
|
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
-
|
5
|
+
# @version 0.8.1
|
6
|
+
module SmartCore::Container::Entities::DependencyBuilder
|
6
7
|
class << self
|
7
8
|
# @param dependency_name [String]
|
8
9
|
# @param dependency_definition [Proc]
|
@@ -11,68 +12,35 @@ class SmartCore::Container::Entities::DependencyBuilder
|
|
11
12
|
#
|
12
13
|
# @api private
|
13
14
|
# @since 0.1.0
|
14
|
-
# @version 0.
|
15
|
+
# @version 0.8.1
|
15
16
|
def build(dependency_name, dependency_definition, memoize)
|
16
|
-
|
17
|
+
if memoize
|
18
|
+
build_memoized_dependency(dependency_name, dependency_definition)
|
19
|
+
else
|
20
|
+
build_original_dependency(dependency_name, dependency_definition)
|
21
|
+
end
|
17
22
|
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# @param dependency_name [String]
|
21
|
-
# @param dependency_definition [Proc]
|
22
|
-
# @param memoize [Boolean]
|
23
|
-
# @return [void]
|
24
|
-
#
|
25
|
-
# @api private
|
26
|
-
# @since 0.1.0
|
27
|
-
# @version 0.2.0
|
28
|
-
def initialize(dependency_name, dependency_definition, memoize)
|
29
|
-
@dependency_name = dependency_name
|
30
|
-
@dependency_definition = dependency_definition
|
31
|
-
@memoize = memoize
|
32
|
-
end
|
33
|
-
|
34
|
-
# @return [SmartCore::Container::Entities::Dependency]
|
35
|
-
#
|
36
|
-
# @api private
|
37
|
-
# @since 0.1.0
|
38
|
-
# @version 0.2.0
|
39
|
-
def build
|
40
|
-
memoize ? build_memoized_dependency : build_original_dependency
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
23
|
|
45
|
-
|
46
|
-
#
|
47
|
-
# @api private
|
48
|
-
# @since 0.1.0
|
49
|
-
attr_reader :dependency_name
|
24
|
+
private
|
50
25
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# @since 0.2.0
|
61
|
-
attr_reader :memoize
|
62
|
-
|
63
|
-
# @return [SmartCore::Container::Entities::Dependency]
|
64
|
-
#
|
65
|
-
# @api private
|
66
|
-
# @since 0.2.0
|
67
|
-
def build_memoized_dependency
|
68
|
-
SmartCore::Container::Entities::MemoizedDependency.new(dependency_name, dependency_definition)
|
69
|
-
end
|
26
|
+
# @param dependency_name [String]
|
27
|
+
# @param dependency_definition [Proc]
|
28
|
+
# @return [SmartCore::Container::Entities::Dependency]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
# @since 0.8.1
|
32
|
+
def build_memoized_dependency(dependency_name, dependency_definition)
|
33
|
+
SmartCore::Container::Entities::MemoizedDependency.new(dependency_name, dependency_definition)
|
34
|
+
end
|
70
35
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
36
|
+
# @param dependency_name [String]
|
37
|
+
# @param dependency_definition [Proc]
|
38
|
+
# @return [SmartCore::Container::Entities::Dependency]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
# @since 0.8.1
|
42
|
+
def build_original_dependency(dependency_name, dependency_definition)
|
43
|
+
SmartCore::Container::Entities::Dependency.new(dependency_name, dependency_definition)
|
44
|
+
end
|
77
45
|
end
|
78
46
|
end
|
@@ -12,14 +12,16 @@ module SmartCore::Container::Entities
|
|
12
12
|
# @since 0.2.0
|
13
13
|
def initialize(dependency_name, dependency_definition)
|
14
14
|
super(dependency_name, dependency_definition)
|
15
|
-
@lock = SmartCore::Container::
|
15
|
+
@lock = SmartCore::Container::ArbitraryLock.new
|
16
16
|
end
|
17
17
|
|
18
|
+
# @param host_container [SmartCore::Container, NilClass]
|
18
19
|
# @return [Any]
|
19
20
|
#
|
20
21
|
# @api private
|
21
22
|
# @since 0.2.0
|
22
|
-
|
23
|
+
# @version 0.8.1
|
24
|
+
def reveal(host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
23
25
|
@lock.thread_safe do
|
24
26
|
unless instance_variable_defined?(:@revealed_dependency)
|
25
27
|
@revealed_dependency = dependency_definition.call
|
@@ -9,24 +9,35 @@ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities
|
|
9
9
|
# @since 0.1.0
|
10
10
|
alias_method :namespace_name, :external_name
|
11
11
|
|
12
|
+
# @return [NilClass, SmartCore::Container]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
# @since 0.8.01
|
16
|
+
attr_reader :host_container
|
17
|
+
|
12
18
|
# @param namespace_name [String]
|
19
|
+
# @param host_container [NilClass, SmartCore::Container]
|
13
20
|
# @return [void]
|
14
21
|
#
|
15
22
|
# @api private
|
16
23
|
# @since 0.1.0
|
17
|
-
|
24
|
+
# @version 0.8.1
|
25
|
+
def initialize(namespace_name, host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
18
26
|
super(namespace_name)
|
19
27
|
@container_klass = Class.new(SmartCore::Container)
|
20
28
|
@container_instance = nil
|
21
|
-
@
|
29
|
+
@host_container = host_container
|
30
|
+
@lock = SmartCore::Container::ArbitraryLock.new
|
22
31
|
end
|
23
32
|
|
33
|
+
# @param runtime_host_container [SmartCore::Container, NilClass]
|
24
34
|
# @return [SmartCore::Container]
|
25
35
|
#
|
26
36
|
# @api private
|
27
37
|
# @since 0.1.0
|
28
|
-
|
29
|
-
|
38
|
+
# @version 0.8.1
|
39
|
+
def reveal(runtime_host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
40
|
+
thread_safe { container_instance(runtime_host_container) }
|
30
41
|
end
|
31
42
|
|
32
43
|
# @param dependencies_definition [Proc]
|
@@ -54,12 +65,18 @@ class SmartCore::Container::Entities::Namespace < SmartCore::Container::Entities
|
|
54
65
|
# @since 0.1.0
|
55
66
|
attr_reader :container_klass
|
56
67
|
|
68
|
+
# @param runtime_host_container [SmartCore::Container, NilClass]
|
57
69
|
# @return [SmartCore::Container]
|
58
70
|
#
|
59
71
|
# @api private
|
60
72
|
# @since 0.1.0
|
61
|
-
|
62
|
-
|
73
|
+
# @version 0.8.1
|
74
|
+
def container_instance(runtime_host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
75
|
+
@host_container ||= runtime_host_container
|
76
|
+
@container_instance ||= container_klass.new(
|
77
|
+
host_container: @host_container,
|
78
|
+
host_path: @host_container && namespace_name
|
79
|
+
)
|
63
80
|
end
|
64
81
|
|
65
82
|
# @param block [Block]
|
@@ -2,40 +2,20 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
# @version 0.8.1
|
6
|
+
module SmartCore::Container::Entities
|
7
|
+
module NamespaceBuilder
|
8
|
+
class << self
|
9
|
+
# @param namespace_name [String]
|
10
|
+
# @param host_container [SmartContainer, NilClass]
|
11
|
+
# @return [SmartCore::Container::Entities::Namespace]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
# @since 0.1.0
|
15
|
+
# @version 0.8.1
|
16
|
+
def build(namespace_name, host_container = SmartCore::Container::NO_HOST_CONTAINER)
|
17
|
+
SmartCore::Container::Entities::Namespace.new(namespace_name, host_container)
|
18
|
+
end
|
14
19
|
end
|
15
20
|
end
|
16
|
-
|
17
|
-
# @param namespace_name [String]
|
18
|
-
# @return [void]
|
19
|
-
#
|
20
|
-
# @api private
|
21
|
-
# @since 0.1.0
|
22
|
-
def initialize(namespace_name)
|
23
|
-
@namespace_name = namespace_name
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [SmartCore::Container::Entities::Namespace]
|
27
|
-
#
|
28
|
-
# @api private
|
29
|
-
# @since 0.1.0
|
30
|
-
def build
|
31
|
-
SmartCore::Container::Entities::Namespace.new(namespace_name)
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
# @return [String]
|
37
|
-
#
|
38
|
-
# @api private
|
39
|
-
# @since 0.1.0
|
40
|
-
attr_reader :namespace_name
|
41
21
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.8.1
|
5
|
+
class SmartCore::Container::Host
|
6
|
+
class << self
|
7
|
+
# @param container [SmartCore::Container]
|
8
|
+
# @param path [String]
|
9
|
+
# @return [SmartCore::Container::Host]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.8.1
|
13
|
+
def build(container, path) # rubocop:disable Metrics/AbcSize
|
14
|
+
if (container.nil? && !path.nil?) || (!container.nil? && path.nil?)
|
15
|
+
raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
|
16
|
+
Host container requires both host container instance and host container path
|
17
|
+
(container: #{container.inspect} / path: #{path.inspect})
|
18
|
+
ERROR_MESSAGE
|
19
|
+
end
|
20
|
+
|
21
|
+
if (!container.nil? && !path.nil?) &&
|
22
|
+
(!container.is_a?(SmartCore::Container) || !path.is_a?(String))
|
23
|
+
raise(SmartCore::Container::ArgumentError, <<~ERROR_MESSAGE)
|
24
|
+
Host container should be a type of SmartCore::Container
|
25
|
+
and host path should be a type of String.
|
26
|
+
ERROR_MESSAGE
|
27
|
+
end
|
28
|
+
|
29
|
+
new(container, path)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [SmartCore::Container]
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
# @since 0.8.1
|
37
|
+
attr_reader :container
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
#
|
41
|
+
# @api private
|
42
|
+
# @since 0.8.1
|
43
|
+
attr_reader :path
|
44
|
+
|
45
|
+
# @return [Boolean]
|
46
|
+
#
|
47
|
+
# @api private
|
48
|
+
# @since 0.8.1
|
49
|
+
attr_reader :exists
|
50
|
+
alias_method :exists?, :exists
|
51
|
+
alias_method :present?, :exists
|
52
|
+
|
53
|
+
# @param container [SmartCore::Container]
|
54
|
+
# @param path [String]
|
55
|
+
# @return [void]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.8.1
|
59
|
+
def initialize(container, path)
|
60
|
+
@container = container
|
61
|
+
@path = path
|
62
|
+
@exists = !!container
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param nested_entity_path [String]
|
66
|
+
# @return [void]
|
67
|
+
#
|
68
|
+
# @api private
|
69
|
+
# @since 0.8.1
|
70
|
+
def notify_about_nested_changement(nested_entity_path)
|
71
|
+
return unless exists?
|
72
|
+
host_path = "#{path}" \
|
73
|
+
"#{SmartCore::Container::DependencyResolver::PATH_PART_SEPARATOR}" \
|
74
|
+
"#{nested_entity_path}"
|
75
|
+
container.watcher.notify(host_path)
|
76
|
+
end
|
77
|
+
end
|
@@ -11,7 +11,7 @@ module SmartCore::Container::Mixin
|
|
11
11
|
# @since 0.1.0
|
12
12
|
def included(base_klass)
|
13
13
|
# rubocop:disable Layout/LineLength
|
14
|
-
base_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::
|
14
|
+
base_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitraryLock.new)
|
15
15
|
base_klass.instance_variable_set(:@__smart_core_container_klass__, Class.new(SmartCore::Container))
|
16
16
|
base_klass.instance_variable_set(:@__smart_core_container__, nil)
|
17
17
|
# rubocop:enable Layout/LineLength
|
@@ -34,7 +34,7 @@ module SmartCore::Container::Mixin
|
|
34
34
|
inherited_container_klass = Class.new(@__smart_core_container_klass__)
|
35
35
|
|
36
36
|
# rubocop:disable Layout/LineLength
|
37
|
-
child_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::
|
37
|
+
child_klass.instance_variable_set(:@__smart_core_container_access_lock__, SmartCore::Container::ArbitraryLock.new)
|
38
38
|
child_klass.instance_variable_set(:@__smart_core_container_klass__, inherited_container_klass)
|
39
39
|
child_klass.instance_variable_set(:@__smart_core_container__, nil)
|
40
40
|
# rubocop:enable Layout/LineLength
|
@@ -37,7 +37,7 @@ class SmartCore::Container::Registry
|
|
37
37
|
# @since 0.1.0
|
38
38
|
def initialize
|
39
39
|
@registry = {}
|
40
|
-
@access_lock = SmartCore::Container::
|
40
|
+
@access_lock = SmartCore::Container::ArbitraryLock.new
|
41
41
|
end
|
42
42
|
|
43
43
|
# @param entity_path [String, Symbol]
|
@@ -57,18 +57,24 @@ class SmartCore::Container::Registry
|
|
57
57
|
# @api private
|
58
58
|
# @since 0.1.0
|
59
59
|
# @version 0.3.0
|
60
|
-
def register_dependency(name, memoize
|
60
|
+
def register_dependency(name, memoize: DEFAULT_MEMOIZATION_BEHAVIOR, &dependency_definition)
|
61
61
|
thread_safe { add_dependency(name, dependency_definition, memoize) }
|
62
62
|
end
|
63
63
|
|
64
64
|
# @param name [String, Symbol]
|
65
|
+
# @param host_container [NilClasss, SmartCore::Container]
|
65
66
|
# @param dependencies_definition [Block]
|
66
67
|
# @return [void]
|
67
68
|
#
|
68
69
|
# @api private
|
69
70
|
# @since 0.1.0
|
70
|
-
|
71
|
-
|
71
|
+
# @version 0.8.1
|
72
|
+
def register_namespace(
|
73
|
+
name,
|
74
|
+
host_container = SmartCore::Container::NO_HOST_CONTAINER,
|
75
|
+
&dependencies_definition
|
76
|
+
)
|
77
|
+
thread_safe { add_namespace(name, host_container, dependencies_definition) }
|
72
78
|
end
|
73
79
|
|
74
80
|
# @return [void]
|
@@ -223,6 +229,7 @@ class SmartCore::Container::Registry
|
|
223
229
|
end
|
224
230
|
|
225
231
|
# @param namespace_name [String, Symbol]
|
232
|
+
# @param host_container [NilClass, SmartCore::Container]
|
226
233
|
# @param dependencies_definition [Proc]
|
227
234
|
# @return [SmartCore::Container::Entities::Namespace]
|
228
235
|
#
|
@@ -230,11 +237,13 @@ class SmartCore::Container::Registry
|
|
230
237
|
#
|
231
238
|
# @api private
|
232
239
|
# @since 0.1.0
|
233
|
-
|
240
|
+
# @version 0.8.1
|
241
|
+
def add_namespace(namespace_name, host_container, dependencies_definition)
|
234
242
|
if state_frozen?
|
235
243
|
raise(SmartCore::Container::FrozenRegistryError, 'Can not modify frozen registry!')
|
236
244
|
end
|
237
245
|
namespace_name = indifferently_accessable_name(namespace_name)
|
246
|
+
dependencies_definition ||= proc {}
|
238
247
|
prevent_dependency_overlap!(namespace_name)
|
239
248
|
|
240
249
|
# rubocop:disable Layout/RescueEnsureAlignment
|
@@ -242,7 +251,7 @@ class SmartCore::Container::Registry
|
|
242
251
|
fetch_entity(namespace_name)
|
243
252
|
rescue SmartCore::Container::FetchError
|
244
253
|
registry[namespace_name] = SmartCore::Container::Entities::NamespaceBuilder.build(
|
245
|
-
namespace_name
|
254
|
+
namespace_name, host_container
|
246
255
|
)
|
247
256
|
end
|
248
257
|
# rubocop:enable Layout/RescueEnsureAlignment
|