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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc042cd47800b613d12e02456c24d25afc170f7b
4
- data.tar.gz: 1ab703cbc5c5458d181f3b8d2a4c357d4d9c4056
3
+ metadata.gz: 3555b8b45ee20ff856590c5bd5b38cd91042d93a
4
+ data.tar.gz: d97785bfd1cc1cb00da4166f08af02dc959149ee
5
5
  SHA512:
6
- metadata.gz: b85b7153906906aaabb7d3dfc18e6060765f68bcf3a2885972acbbbd1c3d6a01a15b5c112205dc8fa0f64cf8403f056dd9091fadc2849e3051806cb4fe3fb183
7
- data.tar.gz: b4dabbf9b1b3514ae65e189334848768670839d4e086bb6160158154ece8b7041def60184036e819c15df41de971ebb126849c1db62cb52917014615995f0abd
6
+ metadata.gz: 47710dd291c0d8d8c4bdcff0d01bf9d4c4c370697183aba0a846ddfbef1ffe1022eab6848227af07eccdf2c48773fce4856bf1c5f56c0ba78a44440e04bce1b3
7
+ data.tar.gz: 844374a0d77f694b1b7075326b5fbe5528dea1835a93bfe619a8289703edb2988c1d9ba385acaf32d2eeba93efda4a23e44d54755d21fa475d3cd73cd6820aae
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'alki-testing', path: '/home/matt/Projects/personal/alki/alki-testing'
4
+
3
5
  gemspec
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 "minitest", "~> 5.9", '>= 5.9.1'
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
@@ -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 'thread'
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
- @data = {}
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 synchronize
21
- @semaphore.synchronize do
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 execute(meta,path,args,blk)
31
- cache_entry = nil
32
- synchronize do
33
- cache_entry = @call_cache[path]
34
- end
35
- if cache_entry
36
- if cache_entry.status == :building
37
- raise "Circular element reference found: #{path.join(".")}"
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
- private
68
-
69
- def process_meta
70
- unless @processed_meta
71
- @processed_meta = true
72
- @data[:overlays] = {}
73
- @data[:tags] = {}
74
- @meta.each do |(from,type,info)|
75
- case type
76
- when :overlay then process_overlay from, info
77
- when :tags then process_tags from, info
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
- def process_tags(from,tags)
84
- tags.each do |tag|
85
- (@data[:tags][tag]||=[]) << from
86
- end
87
- end
72
+ private
88
73
 
89
- def process_overlay(from,info)
90
- target_path = info.target.dup
91
- if target_path.last.to_s.start_with?('%')
92
- tag = target_path.pop
93
- end
94
- if target_path == []
95
- target_path = [:root]
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
- target = canonical_path(from,target_path) or
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 lookup(path)
109
- process_meta
110
- @lookup_cache[path] ||= lookup_elem(path).tap do |elem|
111
- unless elem
112
- raise InvalidPathError.new("Invalid path #{path.inspect}")
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 = @data.dup
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
- if @obj.respond_to? :__reload__
15
- did_something = @obj.__reload__
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
- @version
29
+ @lock.with_read_lock do
30
+ @version
31
+ end
34
32
  end
35
33
 
36
34
  def __getobj__
37
- unless @obj
38
- # Will call __setobj__
39
- Alki.load(@assembly_module).raw_instance self, *@args
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
@@ -5,7 +5,7 @@ Alki do
5
5
 
6
6
  output do
7
7
  {
8
- modules: [Alki::Execution::ValueHelpers],
8
+ modules: [Alki::Execution::Helpers],
9
9
  scope: data[:scope],
10
10
  build: {
11
11
  methods: {
@@ -4,7 +4,7 @@ Alki do
4
4
  attr :block
5
5
  output do
6
6
  {
7
- modules: [Alki::Execution::ValueHelpers],
7
+ modules: [Alki::Execution::Helpers],
8
8
  scope: data[:scope],
9
9
  proc: block
10
10
  }
@@ -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
@@ -11,7 +11,7 @@ Alki do
11
11
  },
12
12
  proc: ->(desc) {desc[:value] = __build__}
13
13
  },
14
- modules: [Alki::Execution::ValueHelpers],
14
+ modules: [Alki::Execution::Helpers],
15
15
  scope: data[:scope]
16
16
  }
17
17
  end
@@ -4,18 +4,19 @@ Alki do
4
4
  attr :block
5
5
 
6
6
  output do
7
- overlays = (data[:overlays][[]]||[]).group_by(&:first)
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,(_,overlay,args)|
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::ValueHelpers],
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(instance,overrides,blk)
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 = [[],:overlay, OverlayInfo.new(
19
+ update_instance_overlay = [[],Meta::Overlay.new(
20
20
  :value,
21
21
  [:assembly_instance],
22
- ->obj{instance.__setobj__ obj; instance},
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
 
@@ -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],:tags,@tags]
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
- [], :overlay,
27
- Alki::OverlayInfo.new(
28
- type,
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
- attr_accessor :type,:value,:status
5
- def initialize
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 finish(type,value)
10
- @status = :done
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
@@ -36,7 +36,7 @@ module Alki
36
36
  (config[:methods]||{}).each do |name,body|
37
37
  methods[name] = {
38
38
  body: body,
39
- private: true,
39
+ private: name.to_s.start_with?('__'),
40
40
  }
41
41
  end
42
42
  ClassBuilder.build(
@@ -5,10 +5,6 @@ module Alki
5
5
  module Execution
6
6
  module ValueHelpers
7
7
  include Helpers
8
-
9
- def delegate_overlay(obj,overlay,**args)
10
- Alki::OverlayDelegator.new(obj,overlay,args)
11
- end
12
8
  end
13
9
  end
14
10
  end
@@ -0,0 +1,3 @@
1
+ module Alki
2
+ InvalidPathError = Class.new(StandardError)
3
+ end
@@ -1,3 +1,3 @@
1
1
  module Alki
2
- OverlayInfo = Struct.new(:type,:target,:overlay,:args)
2
+ OverlayInfo = Struct.new(:order,:type,:overlay,:args)
3
3
  end
data/lib/alki/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Alki
2
- VERSION = "0.10.0"
2
+ VERSION = "0.11.0"
3
3
  end
data/lib/alki.rb CHANGED
@@ -1,18 +1,15 @@
1
1
  require 'alki/dsl'
2
2
  require 'alki/assembly/builder'
3
3
 
4
- module Alki
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
- alias_method :create_assembly!, :project_assembly!
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
- def create_assembly(opts={},&blk)
15
- Assembly::Builder.build(opts,&blk)
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
@@ -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)
@@ -0,0 +1,2 @@
1
+ Alki::Loader.register 'auto_group_dsl.rb', builder: 'alki/dsls/dsl'
2
+ Alki::Loader.register 'auto_group_test', builder: 'auto_group_dsl'
@@ -0,0 +1,9 @@
1
+ Alki do
2
+ require_dsl 'alki/dsls/class'
3
+
4
+ dsl_method :value do |val|
5
+ add_method :value do
6
+ val
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ Alki do
2
+ value 2
3
+ end
@@ -0,0 +1,3 @@
1
+ Alki do
2
+ value 1
3
+ end
@@ -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.10.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: 2016-12-29 00:00:00.000000000 Z
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: minitest
42
+ name: alki-dsl
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '5.9'
47
+ version: '0.4'
48
48
  - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 5.9.1
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: '5.9'
57
+ version: '0.4'
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 5.9.1
60
+ version: 0.4.2
61
61
  - !ruby/object:Gem::Dependency
62
- name: alki-dsl
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.4'
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.4'
74
+ version: '0.7'
75
75
  - !ruby/object:Gem::Dependency
76
- name: alki-support
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.7'
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.7'
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
@@ -1,7 +0,0 @@
1
- require 'alki/test'
2
-
3
- feature_test_helper = File.join(Alki::Test.tests_root,'feature_test_helper.rb')
4
-
5
- if File.exists? feature_test_helper
6
- require feature_test_helper
7
- end
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