alki 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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