alki 0.10.0 → 0.11.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/Gemfile +2 -0
- data/alki.gemspec +3 -2
- data/config/assembly.rb +21 -0
- data/lib/alki/assembly/executor.rb +46 -67
- data/lib/alki/assembly/instance.rb +31 -20
- data/lib/alki/assembly/meta/overlay.rb +40 -0
- data/lib/alki/assembly/meta/tags.rb +18 -0
- data/lib/alki/assembly/types/factory.rb +1 -1
- data/lib/alki/assembly/types/func.rb +1 -1
- data/lib/alki/assembly/types/group.rb +8 -0
- data/lib/alki/assembly/types/proc_value.rb +1 -1
- data/lib/alki/assembly/types/service.rb +5 -4
- data/lib/alki/assembly.rb +8 -8
- data/lib/alki/dsls/assembly.rb +3 -2
- data/lib/alki/dsls/assembly_group.rb +28 -5
- data/lib/alki/execution/cache_entry.rb +7 -8
- data/lib/alki/execution/context_class_builder.rb +1 -1
- data/lib/alki/execution/value_helpers.rb +0 -4
- data/lib/alki/invalid_path_error.rb +3 -0
- data/lib/alki/overlay_info.rb +1 -1
- data/lib/alki/version.rb +1 -1
- data/lib/alki.rb +9 -12
- data/test/feature/auto_group_test.rb +21 -0
- data/test/feature/multithreading_test.rb +60 -0
- data/test/feature/reload_test.rb +32 -0
- data/test/feature_test_helper.rb +3 -1
- data/test/fixtures/auto_group/lib/alki_loader.rb +2 -0
- data/test/fixtures/auto_group/lib/auto_group_dsl.rb +9 -0
- data/test/fixtures/auto_group/lib/auto_group_test/a/two.rb +3 -0
- data/test/fixtures/auto_group/lib/auto_group_test/one.rb +3 -0
- data/test/fixtures/example/config/assembly.rb +3 -1
- metadata +45 -15
- data/lib/alki/feature_test.rb +0 -7
- data/lib/alki/test.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3555b8b45ee20ff856590c5bd5b38cd91042d93a
|
4
|
+
data.tar.gz: d97785bfd1cc1cb00da4166f08af02dc959149ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47710dd291c0d8d8c4bdcff0d01bf9d4c4c370697183aba0a846ddfbef1ffe1022eab6848227af07eccdf2c48773fce4856bf1c5f56c0ba78a44440e04bce1b3
|
7
|
+
data.tar.gz: 844374a0d77f694b1b7075326b5fbe5528dea1835a93bfe619a8289703edb2988c1d9ba385acaf32d2eeba93efda4a23e44d54755d21fa475d3cd73cd6820aae
|
data/Gemfile
CHANGED
data/alki.gemspec
CHANGED
@@ -20,7 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.6"
|
22
22
|
spec.add_development_dependency "rake", '~> 10.0'
|
23
|
-
spec.add_dependency "
|
24
|
-
spec.add_dependency "alki-dsl", "~> 0.4"
|
23
|
+
spec.add_dependency "alki-dsl", "~> 0.4", ">= 0.4.2"
|
25
24
|
spec.add_dependency "alki-support", "~> 0.7"
|
25
|
+
spec.add_dependency "concurrent-ruby", "~> 1.0"
|
26
|
+
spec.add_dependency "ice_nine", "~> 0.11"
|
26
27
|
end
|
data/config/assembly.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Alki do
|
2
|
+
factory :delegate_overlay do
|
3
|
+
require 'alki/overlay_delegator'
|
4
|
+
-> obj, overlay, **args {
|
5
|
+
Alki::OverlayDelegator.new obj, overlay, args
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
factory :build_service do
|
10
|
+
-> (klass, grp=nil) {
|
11
|
+
klass = Alki.load klass
|
12
|
+
grp ||= parent
|
13
|
+
args = if klass.respond_to? :uses
|
14
|
+
klass.uses.map {|path| grp.lookup path }
|
15
|
+
else
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
klass.new *args
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
@@ -1,24 +1,22 @@
|
|
1
1
|
require 'alki/execution/context_class_builder'
|
2
2
|
require 'alki/execution/cache_entry'
|
3
|
-
require '
|
3
|
+
require 'concurrent'
|
4
|
+
require 'alki/invalid_path_error'
|
4
5
|
|
5
6
|
module Alki
|
6
|
-
InvalidPathError = Class.new(StandardError)
|
7
7
|
module Assembly
|
8
8
|
class Executor
|
9
9
|
def initialize(assembly,meta)
|
10
10
|
@assembly = assembly
|
11
11
|
@meta = meta
|
12
|
-
@
|
13
|
-
@semaphore = Monitor.new
|
12
|
+
@semaphore = Concurrent::ReentrantReadWriteLock.new
|
14
13
|
@lookup_cache = {}
|
15
14
|
@call_cache = {}
|
16
15
|
@context_cache = {}
|
17
|
-
@processed_meta = false
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
@semaphore.
|
18
|
+
def lock
|
19
|
+
@semaphore.with_write_lock do
|
22
20
|
yield
|
23
21
|
end
|
24
22
|
end
|
@@ -27,32 +25,19 @@ module Alki
|
|
27
25
|
execute({},path,args,blk)
|
28
26
|
end
|
29
27
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
else
|
40
|
-
synchronize do
|
41
|
-
cache_entry = @call_cache[path]
|
42
|
-
unless cache_entry
|
43
|
-
cache_entry = @call_cache[path] = Alki::Execution::CacheEntry.new
|
44
|
-
action = lookup(path)
|
45
|
-
if action[:build]
|
46
|
-
build_meta = meta.merge(building: path.join('.'))
|
47
|
-
build_meta.merge!(action[:meta]) if action[:meta]
|
48
|
-
build_action = action[:build].merge(scope: action[:scope],modules: action[:modules])
|
49
|
-
call_value(*process_action(build_action),build_meta,[action])
|
28
|
+
def lookup(path)
|
29
|
+
@semaphore.with_read_lock do
|
30
|
+
unless @lookup_cache[path]
|
31
|
+
@semaphore.with_write_lock do
|
32
|
+
@lookup_cache[path] = lookup_elem(path).tap do |elem|
|
33
|
+
unless elem
|
34
|
+
raise InvalidPathError.new("Invalid path #{path.inspect}")
|
35
|
+
end
|
50
36
|
end
|
51
|
-
cache_entry.finish *process_action(action)
|
52
37
|
end
|
53
38
|
end
|
39
|
+
@lookup_cache[path]
|
54
40
|
end
|
55
|
-
call_value(cache_entry.type,cache_entry.value,meta,args,blk)
|
56
41
|
end
|
57
42
|
|
58
43
|
def canonical_path(from,path)
|
@@ -64,58 +49,52 @@ module Alki
|
|
64
49
|
end
|
65
50
|
end
|
66
51
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
52
|
+
def execute(meta,path,args,blk)
|
53
|
+
type,value = nil,nil
|
54
|
+
@semaphore.with_read_lock do
|
55
|
+
cache_entry = @call_cache[path]
|
56
|
+
if cache_entry
|
57
|
+
if cache_entry == :building
|
58
|
+
raise "Circular element reference found: #{path.join(".")}"
|
59
|
+
end
|
60
|
+
type,value = cache_entry.type,cache_entry.value
|
61
|
+
else
|
62
|
+
@semaphore.with_write_lock do
|
63
|
+
@call_cache[path] = :building
|
64
|
+
type, value = build(path)
|
65
|
+
@call_cache[path] = Alki::Execution::CacheEntry.finished type, value
|
78
66
|
end
|
79
67
|
end
|
80
68
|
end
|
69
|
+
call_value(type, value, meta, args, blk)
|
81
70
|
end
|
82
71
|
|
83
|
-
|
84
|
-
tags.each do |tag|
|
85
|
-
(@data[:tags][tag]||=[]) << from
|
86
|
-
end
|
87
|
-
end
|
72
|
+
private
|
88
73
|
|
89
|
-
def
|
90
|
-
|
91
|
-
if
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
74
|
+
def build(path)
|
75
|
+
action = lookup(path)
|
76
|
+
if action[:build]
|
77
|
+
build_meta = {building: path.join('.')}
|
78
|
+
build_meta.merge!(action[:meta]) if action[:meta]
|
79
|
+
build_action = action[:build].merge(scope: action[:scope], modules: action[:modules])
|
80
|
+
call_value(*process_action(build_action), build_meta, [action])
|
96
81
|
end
|
97
|
-
|
98
|
-
raise InvalidPathError.new("Invalid overlay target #{info.target.join('.')}")
|
99
|
-
target = target.dup.push tag if tag
|
100
|
-
overlay = info.overlay
|
101
|
-
if overlay.is_a?(Array)
|
102
|
-
overlay = canonical_path(from,info.overlay) or
|
103
|
-
raise InvalidPathError.new("Invalid overlay path #{info.overlay.join('.')}")
|
104
|
-
end
|
105
|
-
(@data[:overlays][target]||=[]) << [info.type, overlay, info.args]
|
82
|
+
process_action action
|
106
83
|
end
|
107
84
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
85
|
+
def data_copy
|
86
|
+
unless @data
|
87
|
+
@data = {}
|
88
|
+
@meta.each do |(from,meta)|
|
89
|
+
meta.process self, from, @data
|
113
90
|
end
|
91
|
+
IceNine.deep_freeze @data
|
114
92
|
end
|
93
|
+
@data.dup
|
115
94
|
end
|
116
95
|
|
117
96
|
def lookup_elem(path)
|
118
|
-
data =
|
97
|
+
data = data_copy
|
119
98
|
elem = @assembly
|
120
99
|
path.each do |key|
|
121
100
|
elem = elem.index data, key
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'delegate'
|
2
|
+
require 'concurrent'
|
2
3
|
require 'alki/support'
|
4
|
+
require 'concurrent'
|
3
5
|
|
4
6
|
module Alki
|
5
7
|
module Assembly
|
@@ -8,37 +10,46 @@ module Alki
|
|
8
10
|
@assembly_module = assembly_module
|
9
11
|
@args = args
|
10
12
|
@version = 0
|
13
|
+
@needs_load = true
|
14
|
+
@lock = Concurrent::ReentrantReadWriteLock.new
|
11
15
|
end
|
12
16
|
|
13
17
|
def __reload__
|
14
|
-
|
15
|
-
|
18
|
+
@lock.with_read_lock do
|
19
|
+
if @obj
|
20
|
+
@lock.with_write_lock do
|
21
|
+
@needs_load = true
|
22
|
+
@version+=1
|
23
|
+
end
|
24
|
+
end
|
16
25
|
end
|
17
|
-
if did_something != false && @obj
|
18
|
-
__setobj__ nil
|
19
|
-
did_something = true
|
20
|
-
end
|
21
|
-
if did_something
|
22
|
-
GC.start
|
23
|
-
end
|
24
|
-
!!did_something
|
25
|
-
end
|
26
|
-
|
27
|
-
def __setobj__(obj)
|
28
|
-
@version += 1
|
29
|
-
@obj = obj
|
30
26
|
end
|
31
27
|
|
32
28
|
def __version__
|
33
|
-
@
|
29
|
+
@lock.with_read_lock do
|
30
|
+
@version
|
31
|
+
end
|
34
32
|
end
|
35
33
|
|
36
34
|
def __getobj__
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
@lock.with_read_lock do
|
36
|
+
__load__ if @needs_load
|
37
|
+
@obj
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def __load__
|
44
|
+
# Calls __setobj__
|
45
|
+
@lock.with_write_lock do
|
46
|
+
@needs_load = false
|
47
|
+
@obj.__unload__ if @obj.respond_to?(:__unload__)
|
48
|
+
Alki.load(@assembly_module).raw_instance *@args do |obj|
|
49
|
+
@obj = obj
|
50
|
+
self
|
51
|
+
end
|
40
52
|
end
|
41
|
-
@obj
|
42
53
|
end
|
43
54
|
end
|
44
55
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'alki/invalid_path_error'
|
2
|
+
require 'alki/overlay_info'
|
3
|
+
|
4
|
+
module Alki
|
5
|
+
module Assembly
|
6
|
+
module Meta
|
7
|
+
class Overlay
|
8
|
+
def initialize(type,target,overlay,args)
|
9
|
+
@type = type
|
10
|
+
@target = target
|
11
|
+
@overlay = overlay
|
12
|
+
@args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(executor,from,data)
|
16
|
+
data[:total_overlays] ||= 0
|
17
|
+
data[:overlays]||={}
|
18
|
+
target_path = @target.dup
|
19
|
+
if target_path.last.to_s.start_with?('%')
|
20
|
+
tag = target_path.pop
|
21
|
+
end
|
22
|
+
if target_path == []
|
23
|
+
target_path = [:root]
|
24
|
+
end
|
25
|
+
target = executor.canonical_path(from,target_path) or
|
26
|
+
raise InvalidPathError.new("Invalid overlay target #{@target.join('.')}")
|
27
|
+
target = target.dup.push tag if tag
|
28
|
+
overlay = @overlay
|
29
|
+
if overlay.is_a?(Array)
|
30
|
+
overlay = executor.canonical_path(from,@overlay) or
|
31
|
+
raise InvalidPathError.new("Invalid overlay path #{@overlay.join('.')}")
|
32
|
+
end
|
33
|
+
order = data[:total_overlays]
|
34
|
+
(data[:overlays][target]||=[]) << OverlayInfo.new(order,@type, overlay, @args)
|
35
|
+
data[:total_overlays] += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alki
|
2
|
+
module Assembly
|
3
|
+
module Meta
|
4
|
+
class Tags
|
5
|
+
def initialize(tags)
|
6
|
+
@tags = tags
|
7
|
+
end
|
8
|
+
|
9
|
+
def process(_executor,from,data)
|
10
|
+
data[:tags]||={}
|
11
|
+
@tags.each do |tag|
|
12
|
+
(data[:tags][tag.to_sym]||=[]) << from
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -6,6 +6,7 @@ Alki do
|
|
6
6
|
index do
|
7
7
|
update_scope children, data[:prefix], data[:scope]
|
8
8
|
|
9
|
+
data[:tags] ||= {}
|
9
10
|
data[:tags] = data[:tags].inject({}) do |tags,(tag,tagged)|
|
10
11
|
tagged.each do |path|
|
11
12
|
if path.empty? || path[0] == key.to_sym
|
@@ -15,6 +16,7 @@ Alki do
|
|
15
16
|
tags
|
16
17
|
end
|
17
18
|
|
19
|
+
data[:overlays] ||= {}
|
18
20
|
data[:overlays] = data[:overlays].inject({}) do |no,(target,overlays)|
|
19
21
|
target = target.dup
|
20
22
|
if target.size == 1 && target[0].to_s.start_with?('%')
|
@@ -36,10 +38,16 @@ Alki do
|
|
36
38
|
end
|
37
39
|
|
38
40
|
output do
|
41
|
+
children_names = children.keys.map(&:to_sym)
|
39
42
|
{
|
40
43
|
full_scope: update_scope(children, data[:prefix], data[:scope]),
|
41
44
|
scope: update_scope(children,data[:prefix]),
|
42
45
|
modules: [Alki::Execution::Helpers],
|
46
|
+
methods: {
|
47
|
+
children: -> {
|
48
|
+
children_names
|
49
|
+
}
|
50
|
+
},
|
43
51
|
proc: ->{self}
|
44
52
|
}
|
45
53
|
end
|
@@ -4,18 +4,19 @@ Alki do
|
|
4
4
|
attr :block
|
5
5
|
|
6
6
|
output do
|
7
|
-
overlays = (data[:overlays][[]]||[]).group_by(&:
|
7
|
+
overlays = (data[:overlays][[]]||[]).sort_by(&:order).group_by(&:type)
|
8
8
|
value_overlays = overlays[:value]||[]
|
9
9
|
reference_overlays = overlays[:reference]||[]
|
10
10
|
methods = {
|
11
11
|
__build__: block,
|
12
12
|
__apply_overlays__: -> obj, overlays {
|
13
|
-
overlays.inject(obj) do |val,
|
13
|
+
overlays.inject(obj) do |val,info|
|
14
|
+
overlay = info.overlay
|
14
15
|
overlay = __raw_root__.lookup(overlay) if overlay.is_a?(Array)
|
15
16
|
if !overlay.respond_to?(:call) && overlay.respond_to?(:new)
|
16
17
|
overlay = overlay.method(:new)
|
17
18
|
end
|
18
|
-
overlay.call val, *args
|
19
|
+
overlay.call val, *info.args
|
19
20
|
end
|
20
21
|
}
|
21
22
|
}
|
@@ -31,7 +32,7 @@ Alki do
|
|
31
32
|
elem[:value] = __apply_overlays__ __build__, value_overlays
|
32
33
|
},
|
33
34
|
},
|
34
|
-
modules: [Alki::Execution::
|
35
|
+
modules: [Alki::Execution::Helpers],
|
35
36
|
scope: data[:scope],
|
36
37
|
}
|
37
38
|
end
|
data/lib/alki/assembly.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'alki/override_builder'
|
2
|
-
require 'alki/assembly/types/assembly'
|
3
|
-
require 'alki/assembly/types/group'
|
4
2
|
require 'alki/assembly/instance'
|
5
3
|
require 'alki/assembly/executor'
|
4
|
+
require 'alki/assembly/meta/overlay'
|
6
5
|
require 'alki/overlay_info'
|
6
|
+
require 'ice_nine'
|
7
7
|
|
8
8
|
module Alki
|
9
9
|
module Assembly
|
@@ -11,24 +11,24 @@ module Alki
|
|
11
11
|
Instance.new load_class, [overrides, blk]
|
12
12
|
end
|
13
13
|
|
14
|
-
def raw_instance(
|
14
|
+
def raw_instance(overrides,blk,&wrapper)
|
15
15
|
overrides_info = OverrideBuilder.build(overrides,&blk)
|
16
16
|
override_root = overrides_info[:root] || build(:group)
|
17
17
|
|
18
18
|
assembly = build :assembly, root, override_root
|
19
|
-
update_instance_overlay = [[]
|
19
|
+
update_instance_overlay = [[],Meta::Overlay.new(
|
20
20
|
:value,
|
21
21
|
[:assembly_instance],
|
22
|
-
->obj{
|
22
|
+
->obj{wrapper.call obj},
|
23
23
|
[]
|
24
24
|
)]
|
25
25
|
all_meta = meta+overrides_info[:meta]+[update_instance_overlay]
|
26
|
+
IceNine.deep_freeze all_meta
|
26
27
|
executor = Executor.new(assembly, all_meta)
|
27
28
|
|
28
|
-
override_root.children[:assembly_instance] = build(:service,->{
|
29
|
-
root
|
30
|
-
})
|
29
|
+
override_root.children[:assembly_instance] = build(:service,->{ root })
|
31
30
|
override_root.children[:assembly_executor] = build(:value,executor)
|
31
|
+
|
32
32
|
executor.call [:assembly_instance]
|
33
33
|
end
|
34
34
|
|
data/lib/alki/dsls/assembly.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
Alki do
|
2
|
+
require 'ice_nine'
|
2
3
|
require_dsl 'alki/dsls/class'
|
3
4
|
require_dsl 'alki/dsls/assembly_group'
|
4
5
|
|
@@ -6,8 +7,8 @@ Alki do
|
|
6
7
|
add :config_dir, build(:value, ctx[:config_dir])
|
7
8
|
add :assembly_name, build(:value, ctx[:assembly_name])
|
8
9
|
|
9
|
-
root = ctx[:root]
|
10
|
-
meta = ctx[:meta]
|
10
|
+
root = IceNine.deep_freeze ctx[:root]
|
11
|
+
meta = IceNine.deep_freeze ctx[:meta]
|
11
12
|
add_class_method :root do
|
12
13
|
root
|
13
14
|
end
|
@@ -10,7 +10,7 @@ Alki do
|
|
10
10
|
|
11
11
|
helper :add do |name,elem|
|
12
12
|
if @tags
|
13
|
-
ctx[:meta] << [[name.to_sym]
|
13
|
+
ctx[:meta] << [[name.to_sym],build_meta(:tags,@tags)]
|
14
14
|
@tags = nil
|
15
15
|
end
|
16
16
|
ctx[:root].children[name.to_sym] = elem
|
@@ -21,12 +21,16 @@ Alki do
|
|
21
21
|
Alki.load("alki/assembly/types/#{type}").new *args
|
22
22
|
end
|
23
23
|
|
24
|
+
helper :build_meta do |type,*args|
|
25
|
+
Alki.load("alki/assembly/meta/#{type}").new *args
|
26
|
+
end
|
27
|
+
|
24
28
|
dsl_method :add_overlay do |type,target,overlay,args|
|
25
29
|
(ctx[:meta]||=[]) << [
|
26
|
-
[],
|
27
|
-
|
28
|
-
|
29
|
-
target.to_s.split('.').map(&:to_sym),
|
30
|
+
[],
|
31
|
+
build_meta(
|
32
|
+
:overlay,
|
33
|
+
type, target.to_s.split('.').map(&:to_sym),
|
30
34
|
overlay.to_s.split('.').map(&:to_sym),
|
31
35
|
args
|
32
36
|
)
|
@@ -81,6 +85,25 @@ Alki do
|
|
81
85
|
update_meta name, grp[:meta]
|
82
86
|
end
|
83
87
|
|
88
|
+
dsl_method :auto_group do |name,dir,callable,*args|
|
89
|
+
grp = build(:group)
|
90
|
+
dir = File.join(File.expand_path(dir,ctx[:config_dir]),"")
|
91
|
+
Dir.glob(File.join(dir,'**','*.rb')).each do |path|
|
92
|
+
require_path = Alki::Loader.lookup_name path
|
93
|
+
if require_path
|
94
|
+
elems = path[dir.size..-1].chomp('.rb').split('/')
|
95
|
+
*parents,basename = elems
|
96
|
+
parent_group = parents.inject(grp) do |grp,parent|
|
97
|
+
grp.children[parent] ||= build(:group)
|
98
|
+
end
|
99
|
+
parent_group.children[basename] = build :service,-> {
|
100
|
+
lookup(callable).call require_path, *args
|
101
|
+
}
|
102
|
+
end
|
103
|
+
end
|
104
|
+
add name, grp
|
105
|
+
end
|
106
|
+
|
84
107
|
dsl_method :load do |group_name,name=group_name.to_s|
|
85
108
|
unless ctx[:prefix]
|
86
109
|
raise "Load command is not available without a config directory"
|
@@ -1,15 +1,14 @@
|
|
1
|
+
require 'concurrent/immutable_struct'
|
2
|
+
|
1
3
|
module Alki
|
2
4
|
module Execution
|
3
|
-
class CacheEntry
|
4
|
-
|
5
|
-
|
6
|
-
@status = :building
|
5
|
+
class CacheEntry < Concurrent::ImmutableStruct.new(:type,:value,:status)
|
6
|
+
def self.building
|
7
|
+
new nil, nil, :building
|
7
8
|
end
|
8
9
|
|
9
|
-
def
|
10
|
-
|
11
|
-
@type = type
|
12
|
-
@value = value
|
10
|
+
def self.finished(type,value)
|
11
|
+
new type, value, :done
|
13
12
|
end
|
14
13
|
end
|
15
14
|
end
|
data/lib/alki/overlay_info.rb
CHANGED
data/lib/alki/version.rb
CHANGED
data/lib/alki.rb
CHANGED
@@ -1,18 +1,15 @@
|
|
1
1
|
require 'alki/dsl'
|
2
2
|
require 'alki/assembly/builder'
|
3
3
|
|
4
|
-
|
5
|
-
class << self
|
6
|
-
def project_assembly!(opts={},&blk)
|
7
|
-
opts[:project_assembly] ||= caller_locations(1,1)[0].absolute_path
|
8
|
-
opts[:load_mode] = :require
|
9
|
-
Assembly::Builder.build(opts,&blk)
|
10
|
-
end
|
4
|
+
Alki::Assembly::Builder.build project_assembly: __FILE__, load_mode: :require
|
11
5
|
|
12
|
-
|
6
|
+
def Alki.project_assembly!(opts={},&blk)
|
7
|
+
opts[:project_assembly] ||= caller_locations(1,1)[0].absolute_path
|
8
|
+
opts[:load_mode] = :require
|
9
|
+
Alki::Assembly::Builder.build(opts,&blk)
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
12
|
+
def Alki.create_assembly(opts={},&blk)
|
13
|
+
Alki::Assembly::Builder.build(opts,&blk)
|
18
14
|
end
|
15
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'alki/feature_test'
|
2
|
+
|
3
|
+
describe 'Auto Group' do
|
4
|
+
before do
|
5
|
+
@assembly = Alki.create_assembly do
|
6
|
+
auto_group :grp, fixture_path('auto_group','lib','auto_group_test'), :construct
|
7
|
+
|
8
|
+
factory :construct do
|
9
|
+
-> name { Alki.load(name).new }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
@obj = @assembly.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should create a group containing all items' do
|
16
|
+
@obj.grp.children.must_equal [:a,:one]
|
17
|
+
@obj.grp.one.value.must_equal 1
|
18
|
+
@obj.grp.a.children.must_equal [:two]
|
19
|
+
@obj.grp.a.two.value.must_equal 2
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'alki/feature_test'
|
2
|
+
require 'concurrent'
|
3
|
+
|
4
|
+
describe 'Multithreading' do
|
5
|
+
it 'should cause access to block while assembly is building elements' do
|
6
|
+
cb = Concurrent::CyclicBarrier.new 2
|
7
|
+
e = Concurrent::Event.new
|
8
|
+
|
9
|
+
assembly = Alki.create_assembly do
|
10
|
+
service :svc do
|
11
|
+
cb.wait
|
12
|
+
e.wait
|
13
|
+
end
|
14
|
+
|
15
|
+
service :svc2 do
|
16
|
+
:val
|
17
|
+
end
|
18
|
+
end
|
19
|
+
obj = assembly.new
|
20
|
+
thread = Thread.new { obj.svc }
|
21
|
+
cb.wait
|
22
|
+
thread2 = Thread.new { obj.svc2 }
|
23
|
+
sleep 0.1
|
24
|
+
thread2.alive?.must_equal true
|
25
|
+
e.set
|
26
|
+
sleep 0.1
|
27
|
+
thread2.alive?.must_equal false
|
28
|
+
|
29
|
+
thread.join
|
30
|
+
thread2.join
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should allow concurrent access when not building elements' do
|
34
|
+
cb = Concurrent::CyclicBarrier.new 3
|
35
|
+
assembly = Alki.create_assembly do
|
36
|
+
func :f do
|
37
|
+
cb.wait
|
38
|
+
cb.wait
|
39
|
+
end
|
40
|
+
|
41
|
+
func :f2 do
|
42
|
+
cb.wait
|
43
|
+
end
|
44
|
+
end
|
45
|
+
obj = assembly.new
|
46
|
+
thread = Thread.new { obj.f }
|
47
|
+
thread2 = Thread.new { cb.wait; obj.f2 }
|
48
|
+
cb.wait
|
49
|
+
sleep 0.1
|
50
|
+
thread.alive?.must_equal true
|
51
|
+
thread2.alive?.must_equal true
|
52
|
+
cb.wait
|
53
|
+
sleep 0.1
|
54
|
+
thread.alive?.must_equal false
|
55
|
+
thread2.alive?.must_equal false
|
56
|
+
|
57
|
+
thread.join
|
58
|
+
thread2.join
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'alki/feature_test'
|
2
|
+
|
3
|
+
describe 'Reload' do
|
4
|
+
before do
|
5
|
+
counter = 0
|
6
|
+
@assembly = Alki.create_assembly do
|
7
|
+
service :svc do
|
8
|
+
counter += 1
|
9
|
+
end
|
10
|
+
end
|
11
|
+
@obj = @assembly.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should cause services to be rebuilt' do
|
15
|
+
@obj.svc.must_equal 1
|
16
|
+
@obj.__reload__
|
17
|
+
@obj.svc.must_equal 2
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should increment version number of assembly' do
|
21
|
+
@obj.__version__.must_equal 0
|
22
|
+
@obj.svc
|
23
|
+
@obj.__reload__
|
24
|
+
@obj.__version__.must_equal 1
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should not reload if the assembly hasn\'t been used' do
|
28
|
+
@obj.__version__.must_equal 0
|
29
|
+
@obj.__reload__
|
30
|
+
@obj.__version__.must_equal 0
|
31
|
+
end
|
32
|
+
end
|
data/test/feature_test_helper.rb
CHANGED
@@ -5,7 +5,8 @@ class Minitest::Spec
|
|
5
5
|
before do
|
6
6
|
@test_projects = [
|
7
7
|
Alki::Test.fixture_path('example'),
|
8
|
-
Alki::Test.fixture_path('tlogger')
|
8
|
+
Alki::Test.fixture_path('tlogger'),
|
9
|
+
Alki::Test.fixture_path('auto_group')
|
9
10
|
]
|
10
11
|
@test_projects.each do |proj|
|
11
12
|
$LOAD_PATH.unshift File.join(proj,'lib')
|
@@ -25,6 +26,7 @@ class Minitest::Spec
|
|
25
26
|
end
|
26
27
|
undefine :Example, false
|
27
28
|
undefine :Tlogger, false
|
29
|
+
undefine :AutoGroupTest, false
|
28
30
|
end
|
29
31
|
|
30
32
|
def undefine(sym,force=true)
|
@@ -1,11 +1,13 @@
|
|
1
1
|
Alki do
|
2
|
+
mount :alki
|
3
|
+
|
2
4
|
load :settings
|
3
5
|
load :handlers
|
4
6
|
|
5
7
|
factory :log_overlay do
|
6
8
|
require 'log_overlay'
|
7
9
|
-> (obj) {
|
8
|
-
delegate_overlay obj, LogOverlay.new(log), name: meta[:building]
|
10
|
+
alki.delegate_overlay obj, LogOverlay.new(log), name: meta[:building]
|
9
11
|
}
|
10
12
|
end
|
11
13
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Edlefsen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,53 +39,67 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: alki-dsl
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0.4'
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version:
|
50
|
+
version: 0.4.2
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
54
54
|
requirements:
|
55
55
|
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: '
|
57
|
+
version: '0.4'
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
60
|
+
version: 0.4.2
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name: alki-
|
62
|
+
name: alki-support
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '0.
|
67
|
+
version: '0.7'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '0.
|
74
|
+
version: '0.7'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
76
|
+
name: concurrent-ruby
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '0
|
81
|
+
version: '1.0'
|
82
82
|
type: :runtime
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '0
|
88
|
+
version: '1.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: ice_nine
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.11'
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.11'
|
89
103
|
description: Base library for building applications. Provides tools for organizing
|
90
104
|
and connecting application units.
|
91
105
|
email:
|
@@ -102,6 +116,7 @@ files:
|
|
102
116
|
- Rakefile
|
103
117
|
- alki.gemspec
|
104
118
|
- bin/alki
|
119
|
+
- config/assembly.rb
|
105
120
|
- doc/assemblies.adoc
|
106
121
|
- doc/assembly_dsl.adoc
|
107
122
|
- doc/index.adoc
|
@@ -113,6 +128,8 @@ files:
|
|
113
128
|
- lib/alki/assembly/executor.rb
|
114
129
|
- lib/alki/assembly/handler.rb
|
115
130
|
- lib/alki/assembly/instance.rb
|
131
|
+
- lib/alki/assembly/meta/overlay.rb
|
132
|
+
- lib/alki/assembly/meta/tags.rb
|
116
133
|
- lib/alki/assembly/type.rb
|
117
134
|
- lib/alki/assembly/types/assembly.rb
|
118
135
|
- lib/alki/assembly/types/factory.rb
|
@@ -133,24 +150,30 @@ files:
|
|
133
150
|
- lib/alki/execution/helpers.rb
|
134
151
|
- lib/alki/execution/reference.rb
|
135
152
|
- lib/alki/execution/value_helpers.rb
|
136
|
-
- lib/alki/feature_test.rb
|
137
153
|
- lib/alki/generator.rb
|
154
|
+
- lib/alki/invalid_path_error.rb
|
138
155
|
- lib/alki/overlay_delegator.rb
|
139
156
|
- lib/alki/overlay_info.rb
|
140
157
|
- lib/alki/override_builder.rb
|
141
158
|
- lib/alki/service_delegator.rb
|
142
|
-
- lib/alki/test.rb
|
143
159
|
- lib/alki/version.rb
|
144
160
|
- lib/alki_loader.rb
|
145
161
|
- test/feature/alki_test.rb
|
162
|
+
- test/feature/auto_group_test.rb
|
146
163
|
- test/feature/example_test.rb
|
147
164
|
- test/feature/factories_test.rb
|
165
|
+
- test/feature/multithreading_test.rb
|
148
166
|
- test/feature/overlays_test.rb
|
149
167
|
- test/feature/overrides_test.rb
|
150
168
|
- test/feature/pseudo_elements_test.rb
|
151
169
|
- test/feature/reference_overlays_test.rb
|
170
|
+
- test/feature/reload_test.rb
|
152
171
|
- test/feature/tags_test.rb
|
153
172
|
- test/feature_test_helper.rb
|
173
|
+
- test/fixtures/auto_group/lib/alki_loader.rb
|
174
|
+
- test/fixtures/auto_group/lib/auto_group_dsl.rb
|
175
|
+
- test/fixtures/auto_group/lib/auto_group_test/a/two.rb
|
176
|
+
- test/fixtures/auto_group/lib/auto_group_test/one.rb
|
154
177
|
- test/fixtures/example/config/assembly.rb
|
155
178
|
- test/fixtures/example/config/handlers.rb
|
156
179
|
- test/fixtures/example/config/settings.rb
|
@@ -192,14 +215,21 @@ specification_version: 4
|
|
192
215
|
summary: Base library for building applications.
|
193
216
|
test_files:
|
194
217
|
- test/feature/alki_test.rb
|
218
|
+
- test/feature/auto_group_test.rb
|
195
219
|
- test/feature/example_test.rb
|
196
220
|
- test/feature/factories_test.rb
|
221
|
+
- test/feature/multithreading_test.rb
|
197
222
|
- test/feature/overlays_test.rb
|
198
223
|
- test/feature/overrides_test.rb
|
199
224
|
- test/feature/pseudo_elements_test.rb
|
200
225
|
- test/feature/reference_overlays_test.rb
|
226
|
+
- test/feature/reload_test.rb
|
201
227
|
- test/feature/tags_test.rb
|
202
228
|
- test/feature_test_helper.rb
|
229
|
+
- test/fixtures/auto_group/lib/alki_loader.rb
|
230
|
+
- test/fixtures/auto_group/lib/auto_group_dsl.rb
|
231
|
+
- test/fixtures/auto_group/lib/auto_group_test/a/two.rb
|
232
|
+
- test/fixtures/auto_group/lib/auto_group_test/one.rb
|
203
233
|
- test/fixtures/example/config/assembly.rb
|
204
234
|
- test/fixtures/example/config/handlers.rb
|
205
235
|
- test/fixtures/example/config/settings.rb
|
data/lib/alki/feature_test.rb
DELETED
data/lib/alki/test.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
Bundler.require(:test)
|
2
|
-
require 'minitest/autorun'
|
3
|
-
require 'alki/dsl'
|
4
|
-
|
5
|
-
module Alki
|
6
|
-
module Test
|
7
|
-
def app_root
|
8
|
-
Bundler.root
|
9
|
-
end
|
10
|
-
|
11
|
-
def lib_dir
|
12
|
-
File.join app_root, 'lib'
|
13
|
-
end
|
14
|
-
|
15
|
-
def tests_root
|
16
|
-
File.join app_root, 'test'
|
17
|
-
end
|
18
|
-
|
19
|
-
def fixtures_path
|
20
|
-
File.join tests_root, 'fixtures'
|
21
|
-
end
|
22
|
-
|
23
|
-
def fixture_path(*fixture)
|
24
|
-
File.join fixtures_path, *fixture
|
25
|
-
end
|
26
|
-
|
27
|
-
def load_fixture(*fixture)
|
28
|
-
require fixture_path(*fixture)
|
29
|
-
end
|
30
|
-
|
31
|
-
extend self
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
class Minitest::Spec
|
36
|
-
include Alki::Test
|
37
|
-
end
|
38
|
-
|
39
|
-
unless $LOAD_PATH.include? Alki::Test.lib_dir
|
40
|
-
$LOAD_PATH.unshift Alki::Test.lib_dir
|
41
|
-
end
|
42
|
-
|
43
|
-
test_helper = File.join(Alki::Test.tests_root,'test_helper.rb')
|
44
|
-
|
45
|
-
if File.exists? test_helper
|
46
|
-
require test_helper
|
47
|
-
end
|