rightscale-nanite 0.4.1.4 → 0.4.1.10

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.
data/lib/nanite/reaper.rb CHANGED
@@ -1,23 +1,29 @@
1
1
  module Nanite
2
2
  class Reaper
3
-
3
+ attr_reader :timeouts
4
4
  def initialize(frequency=2)
5
5
  @timeouts = {}
6
6
  EM.add_periodic_timer(frequency) { EM.next_tick { reap } }
7
7
  end
8
8
 
9
- def timeout(token, seconds, &blk)
9
+ # Add the specified token to the internal timeout hash.
10
+ # The reaper will then check this instance on every reap.
11
+ def register(token, seconds, &blk)
10
12
  @timeouts[token] = {:timestamp => Time.now + seconds, :seconds => seconds, :callback => blk}
11
13
  end
14
+
15
+ def unregister(token)
16
+ @timeouts.delete(token)
17
+ end
12
18
 
13
- def reset_with_autoregister_hack(token,seconds,&blk)
19
+ # Updates the timeout timestamp for the given token. If the token is
20
+ # unknown to this reaper instance it will be auto-registered, usually
21
+ # happening when you have several mappers and not all of them know
22
+ # this agent yet, but received a ping from it.
23
+ def update(token, seconds, &blk)
14
24
  unless @timeouts[token]
15
- timeout(token, seconds, &blk)
25
+ register(token, seconds, &blk)
16
26
  end
17
- reset(token)
18
- end
19
-
20
- def reset(token)
21
27
  @timeouts[token][:timestamp] = Time.now + @timeouts[token][:seconds]
22
28
  end
23
29
 
@@ -26,12 +32,7 @@ module Nanite
26
32
  def reap
27
33
  time = Time.now
28
34
  @timeouts.reject! do |token, data|
29
- if time > data[:timestamp]
30
- data[:callback].call
31
- true
32
- else
33
- false
34
- end
35
+ time > data[:timestamp] and data[:callback].call
35
36
  end
36
37
  end
37
38
  end
@@ -0,0 +1,141 @@
1
+ require 'redis'
2
+
3
+ module Nanite
4
+
5
+ # Implementation of a tag store on top of Redis
6
+ # For a nanite with the identity 'nanite-foobar', we store the following:
7
+ #
8
+ # s-nanite-foobar: { /foo/bar, /foo/nik } # a SET of the provided services
9
+ # tg-nanite-foobar: { foo-42, customer-12 } # a SET of the tags for this agent
10
+ #
11
+ # Also we do an inverted index for quick lookup of agents providing a certain
12
+ # service, so for each service the agent provides, we add the nanite to a SET
13
+ # of all the nanites that provide said service:
14
+ #
15
+ # foo/bar: { nanite-foobar, nanite-nickelbag, nanite-another } # redis SET
16
+ #
17
+ # We do that same thing for tags:
18
+ #
19
+ # some-tag: { nanite-foobar, nanite-nickelbag, nanite-another } # redis SET
20
+ #
21
+ # This way we can do a lookup of what nanites provide a set of services and tags based
22
+ # on redis SET intersection:
23
+ #
24
+ # nanites_for('/gems/list', 'some-tag')
25
+ # => returns an array of nanites that provide the intersection of these two service tags
26
+
27
+ class RedisTagStore
28
+
29
+ # Initialize tag store with given redis handle
30
+ def initialize(redis)
31
+ @redis = redis
32
+ end
33
+
34
+ # Store services and tags for given agent
35
+ def store(nanite, services, tags)
36
+ services = nil if services.compact.empty?
37
+ tags = nil if tags.compact.empty?
38
+ log_redis_error do
39
+ if services
40
+ obsolete_services = @redis.set_members("s-#{nanite}") - services
41
+ update_elems(nanite, services, obsolete_services, "s-#{nanite}", 'naniteservices')
42
+ end
43
+ if tags
44
+ obsolete_tags = @redis.set_members("tg-#{nanite}") - tags
45
+ update_elems(nanite, tags, obsolete_tags, "tg-#{nanite}", 'nanitestags')
46
+ end
47
+ end
48
+ end
49
+
50
+ # Update tags for given agent
51
+ def update(nanite, new_tags, obsolete_tags)
52
+ update_elems(nanite, new_tags, obsolete_tags, "tg-#{nanite}", 'nanitestags')
53
+ end
54
+
55
+ # Delete services and tags for given agent
56
+ def delete(nanite)
57
+ delete_elems(nanite, "s-#{nanite}", 'naniteservices')
58
+ delete_elems(nanite, "tg-#{nanite}", 'nanitestags')
59
+ end
60
+
61
+ # Services implemented by given agent
62
+ def services(nanite)
63
+ @redis.set_members("s-#{nanite}")
64
+ end
65
+
66
+ # Tags exposed by given agent
67
+ def tags(nanite)
68
+ @redis.set_members("tg-#{nanite}")
69
+ end
70
+
71
+ # Retrieve all agents services
72
+ def all_services
73
+ log_redis_error do
74
+ @redis.set_members('naniteservices')
75
+ end
76
+ end
77
+
78
+ # Retrieve all agents tags
79
+ def all_tags
80
+ log_redis_error do
81
+ @redis.set_members('nanitetags')
82
+ end
83
+ end
84
+
85
+ # Retrieve nanites implementing given service and exposing given tags
86
+ def nanites_for(from, service, tags)
87
+ keys = tags && tags.dup || []
88
+ keys << service
89
+ log_redis_error do
90
+ @redis.set_intersect(keys.compact)
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ # Update values stored for given agent
97
+ # Also store reverse lookup information using both a unique and
98
+ # a global key (so it's possible to retrieve that agent value or
99
+ # all related values)
100
+ def update_elems(nanite, new_tags, obsolete_tags, elem_key, global_key)
101
+ new_tags = nil if new_tags.compact.empty?
102
+ obsolete_tags = nil if obsolete_tags.compact.empty?
103
+ log_redis_error do
104
+ obsolete_tags.each do |val|
105
+ @redis.set_delete(val, nanite)
106
+ @redis.set_delete(elem_key, val)
107
+ @redis.set_delete(global_key, val)
108
+ end if obsolete_tags
109
+ new_tags.each do |val|
110
+ @redis.set_add(val, nanite)
111
+ @redis.set_add(elem_key, val)
112
+ @redis.set_add(global_key, val)
113
+ end if new_tags
114
+ end
115
+ end
116
+
117
+ # Delete all values for given nanite agent
118
+ # Also delete reverse lookup information
119
+ def delete_elems(nanite, elem_key, global_key)
120
+ log_redis_error do
121
+ (@redis.set_members(elem_key)||[]).each do |val|
122
+ @redis.set_delete(val, nanite)
123
+ if @redis.set_count(val) == 0
124
+ @redis.delete(val)
125
+ @redis.set_delete(global_key, val)
126
+ end
127
+ end
128
+ @redis.delete(elem_key)
129
+ end
130
+ end
131
+
132
+ # Helper method, catch and log errors
133
+ def log_redis_error(&blk)
134
+ blk.call
135
+ rescue Exception => e
136
+ Nanite::Log.warn("redis error in method: #{caller[0]}")
137
+ raise e
138
+ end
139
+
140
+ end
141
+ end
data/lib/nanite/state.rb CHANGED
@@ -1,164 +1,135 @@
1
1
  require 'redis'
2
+ require 'redis_tag_store'
2
3
 
3
4
  module Nanite
4
5
  class State
5
6
  include Enumerable
6
7
 
7
- # this class encapsulates the state of a nanite system using redis as the
8
- # data store. here is the schema, for each agent we store a number of items,
9
- # for a nanite with the identity: nanite-foobar we store the following things:
8
+ # This class encapsulates the state of a nanite system using redis as the
9
+ # data store and a provided tag store. For a nanite with the identity
10
+ # 'nanite-foobar' we store the following:
10
11
  #
11
- # nanite-foobar: 0.72 # load average or 'status'
12
- # s-nanite-foobar: { /foo/bar, /foo/nik } # a SET of the provided services
13
- # tg-nanite-foobar: { foo-42, customer-12 } # a SET of the tags for this agent
12
+ # nanite-foobar: 0.72 # load average or 'status'
14
13
  # t-nanite-foobar: 123456789 # unix timestamp of the last state update
15
14
  #
16
- # also we do an inverted index for quick lookup of agents providing a certain
17
- # service, so for each service the agent provides, we add the nanite to a SET
18
- # of all the nanites that provide said service:
15
+ # The tag store is used to store the associated services and tags.
19
16
  #
20
- # foo/bar: { nanite-foobar, nanite-nickelbag, nanite-another } # redis SET
17
+ # A tag store should provide the following methods:
18
+ # - initialize(redis): Initialize tag store, may use provided redis handle
19
+ # - services(nanite): Retrieve services implemented by given agent
20
+ # - tags(nanite): Retrieve tags implemented by given agent
21
+ # - all_services: Retrieve all services implemented by all agents
22
+ # - all_tags: Retrieve all tags exposed by all agents
23
+ # - store(nanite, services, tags): Store agent's services and tags
24
+ # - update(name, new_tags,obsolete_tags): Update agent's tags
25
+ # - delete(nanite): Delete all entries associated with given agent
26
+ # - nanites_for(service, tags): Retrieve agents implementing given service
27
+ # and exposing given tags
21
28
  #
22
- # we do that same thing for tags:
23
- # some-tag: { nanite-foobar, nanite-nickelbag, nanite-another } # redis SET
24
- #
25
- # This way we can do a lookup of what nanites provide a set of services and tags based
26
- # on redis SET intersection:
27
- #
28
- # nanites_for('/gems/list', 'some-tag')
29
- # => returns a nested array of nanites and their state that provide the intersection
30
- # of these two service tags
31
-
32
- def initialize(redis)
33
- Nanite::Log.info("[setup] initializing redis state: #{redis}")
34
- host, port = redis.split(':')
29
+ # The default implementation for the tag store reuses Redis.
30
+
31
+ def initialize(redis, tag_store=nil)
32
+ host, port, tag_store_type = redis.split(':')
35
33
  host ||= '127.0.0.1'
36
34
  port ||= '6379'
37
- @redis = Redis.new :host => host, :port => port
38
- end
39
-
40
- def log_redis_error(meth,&blk)
41
- blk.call
42
- rescue Exception => e
43
- Nanite::Log.info("redis error in method: #{meth}")
44
- raise e
35
+ tag_store||= 'Nanite::RedisTagStore'
36
+ @redis = Redis.new(:host => host, :port => port)
37
+ @tag_store = tag_store.to_const.new(@redis)
38
+ Nanite::Log.info("[setup] Initializing redis state using host '#{host}', port '#{port}' and tag store #{tag_store}")
45
39
  end
46
-
40
+
41
+ # Retrieve given agent services, tags, status and timestamp
47
42
  def [](nanite)
48
- log_redis_error("[]") do
49
- status = @redis[nanite]
43
+ log_redis_error do
44
+ status = @redis[nanite]
50
45
  timestamp = @redis["t-#{nanite}"]
51
- services = @redis.set_members("s-#{nanite}")
52
- tags = @redis.set_members("tg-#{nanite}")
46
+ services = @tag_store.services(nanite)
47
+ tags = @tag_store.tags(nanite)
53
48
  return nil unless status && timestamp && services
54
49
  {:services => services, :status => status, :timestamp => timestamp.to_i, :tags => tags}
55
50
  end
56
51
  end
57
-
58
- def []=(nanite, hsh)
59
- log_redis_error("[]=") do
60
- update_state(nanite, hsh[:status], hsh[:services], hsh[:tags])
61
- end
52
+
53
+ # Set given attributes for given agent
54
+ # Attributes may include services, tags and status
55
+ def []=(nanite, attributes)
56
+ @tag_store.store(nanite, attributes[:services], attributes[:tags])
57
+ update_status(nanite, attributes[:status])
62
58
  end
63
-
59
+
60
+ # Delete all information related to given agent
64
61
  def delete(nanite)
65
- log_redis_error("delete") do
66
- (@redis.set_members("s-#{nanite}")||[]).each do |srv|
67
- @redis.set_delete(srv, nanite)
68
- if @redis.set_count(srv) == 0
69
- @redis.delete(srv)
70
- @redis.set_delete("naniteservices", srv)
71
- end
72
- end
73
- (@redis.set_members("tg-#{nanite}")||[]).each do |tag|
74
- @redis.set_delete(tag, nanite)
75
- if @redis.set_count(tag) == 0
76
- @redis.delete(tag)
77
- @redis.set_delete("nanitetags", tag)
78
- end
79
- end
80
- @redis.delete nanite
81
- @redis.delete "s-#{nanite}"
82
- @redis.delete "t-#{nanite}"
83
- @redis.delete "tg-#{nanite}"
62
+ @tag_store.delete(nanite)
63
+ log_redis_error do
64
+ @redis.delete(nanite)
65
+ @redis.delete("t-#{nanite}")
84
66
  end
85
67
  end
86
-
68
+
69
+ # Return all services exposed by all agents
87
70
  def all_services
88
- log_redis_error("all_services") do
89
- @redis.set_members("naniteservices")
90
- end
71
+ @tag_store.all_services
91
72
  end
92
73
 
74
+ # Return all tags exposed by all agents
93
75
  def all_tags
94
- log_redis_error("all_tags") do
95
- @redis.set_members("nanitetags")
96
- end
76
+ @tag_store.all_tags
97
77
  end
98
-
99
- def update_state(name, status, services, tags)
100
- old_services = @redis.set_members("s-#{name}")
101
- if old_services
102
- (old_services - services).each do |s|
103
- @redis.set_delete(s, name)
104
- @redis.set_delete("naniteservices", s)
105
- end
106
- end
107
- old_tags = @redis.set_members("tg-#{name}")
108
- if old_tags
109
- (old_tags - tags).each do |t|
110
- @redis.set_delete(t, name)
111
- @redis.set_delete("nanitetags", t)
112
- end
113
- end
114
- @redis.delete("s-#{name}")
115
- services.each do |srv|
116
- @redis.set_add(srv, name)
117
- @redis.set_add("s-#{name}", srv)
118
- @redis.set_add("naniteservices", srv)
119
- end
120
- @redis.delete("tg-#{name}")
121
- tags.each do |tag|
122
- next if tag.nil?
123
- @redis.set_add(tag, name)
124
- @redis.set_add("tg-#{name}", tag)
125
- @redis.set_add("nanitetags", tag)
78
+
79
+ # Update status and timestamp for given agent
80
+ def update_status(name, status)
81
+ log_redis_error do
82
+ @redis[name] = status
83
+ @redis["t-#{name}"] = Time.now.utc.to_i
126
84
  end
127
- @redis[name] = status
128
- @redis["t-#{name}"] = Time.now.to_i
129
85
  end
130
-
86
+
87
+ # Update tags for given agent
88
+ def update_tags(name, new_tags, obsolete_tags)
89
+ @tag_store.update(name, new_tags, obsolete_tags)
90
+ end
91
+
92
+ # Return all registered agents
131
93
  def list_nanites
132
- log_redis_error("list_nanites") do
94
+ log_redis_error do
133
95
  @redis.keys("nanite-*")
134
96
  end
135
97
  end
136
-
98
+
99
+ # Number of registered agents
137
100
  def size
138
101
  list_nanites.size
139
102
  end
140
-
141
- def clear_state
142
- log_redis_error("clear_state") do
143
- @redis.keys("*").each {|k| @redis.delete k}
144
- end
145
- end
146
-
103
+
104
+ # Iterate through all agents, yielding services, tags
105
+ # status and timestamp keyed by agent name
147
106
  def each
148
107
  list_nanites.each do |nan|
149
108
  yield nan, self[nan]
150
109
  end
151
110
  end
152
-
153
- def nanites_for(service, *tags)
154
- keys = tags.dup << service
155
- log_redis_error("nanites_for") do
156
- res = []
157
- (@redis.set_intersect(keys)||[]).each do |nan|
158
- res << [nan, self[nan]]
111
+
112
+ # Return agents that implement given service and expose
113
+ # all given tags
114
+ def nanites_for(from, service, tags)
115
+ res = []
116
+ @tag_store.nanites_for(from, service, tags).each do |nanite_id|
117
+ if nanite = self[nanite_id]
118
+ res << [nanite_id, nanite]
159
119
  end
160
- res
161
120
  end
121
+ res
122
+ end
123
+
124
+ private
125
+
126
+ # Helper method, catch and log errors
127
+ def log_redis_error(&blk)
128
+ blk.call
129
+ rescue Exception => e
130
+ Nanite::Log.warn("redis error in method: #{caller[0]}")
131
+ raise e
162
132
  end
133
+
163
134
  end
164
135
  end
data/lib/nanite/util.rb CHANGED
@@ -27,6 +27,26 @@ class String
27
27
  def to_const_path
28
28
  snake_case.gsub(/::/, "/")
29
29
  end
30
+
31
+ # Convert constant name to constant
32
+ #
33
+ # "FooBar::Baz".to_const => FooBar::Baz
34
+ #
35
+ # @return [Constant] Constant corresponding to given name or nil if no
36
+ # constant with that name exists
37
+ #
38
+ # @api public
39
+ def to_const
40
+ names = split('::')
41
+ names.shift if names.empty? || names.first.empty?
42
+
43
+ constant = Object
44
+ names.each do |name|
45
+ # modified to return nil instead of raising an const_missing error
46
+ constant = constant && constant.const_defined?(name) ? constant.const_get(name) : nil
47
+ end
48
+ constant
49
+ end
30
50
  end
31
51
 
32
52
  class Object
@@ -55,4 +75,4 @@ class Object
55
75
  end
56
76
  end
57
77
  end
58
- end
78
+ end
data/lib/nanite.rb CHANGED
@@ -20,7 +20,7 @@ require 'nanite/mapper'
20
20
  require 'nanite/actor'
21
21
  require 'nanite/actor_registry'
22
22
  require 'nanite/streaming'
23
- require 'nanite/dispatcher'
23
+ require 'nanite/nanite_dispatcher'
24
24
  require 'nanite/agent'
25
25
  require 'nanite/cluster'
26
26
  require 'nanite/reaper'
@@ -39,7 +39,7 @@ require 'nanite/security/static_certificate_store'
39
39
  require 'nanite/serializer'
40
40
 
41
41
  module Nanite
42
- VERSION = '0.4.1.4' unless defined?(Nanite::VERSION)
42
+ VERSION = '0.4.1.10' unless defined?(Nanite::VERSION)
43
43
 
44
44
  class MapperNotRunning < StandardError; end
45
45
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rightscale-nanite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1.4
4
+ version: 0.4.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Zygmuntowicz
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-16 00:00:00 -07:00
12
+ date: 2009-11-09 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -39,74 +39,50 @@ files:
39
39
  - README.rdoc
40
40
  - Rakefile
41
41
  - TODO
42
- - lib/nanite.rb
43
42
  - lib/nanite
44
- - lib/nanite/streaming.rb
45
- - lib/nanite/serializer.rb
46
- - lib/nanite/pid_file.rb
47
- - lib/nanite/mapper.rb
43
+ - lib/nanite/actor.rb
44
+ - lib/nanite/actor_registry.rb
45
+ - lib/nanite/admin.rb
46
+ - lib/nanite/agent.rb
47
+ - lib/nanite/amqp.rb
48
+ - lib/nanite/cluster.rb
49
+ - lib/nanite/config.rb
50
+ - lib/nanite/console.rb
48
51
  - lib/nanite/daemonize.rb
52
+ - lib/nanite/identity.rb
53
+ - lib/nanite/job.rb
54
+ - lib/nanite/local_state.rb
55
+ - lib/nanite/log
56
+ - lib/nanite/log/formatter.rb
57
+ - lib/nanite/log.rb
58
+ - lib/nanite/mapper.rb
49
59
  - lib/nanite/mapper_proxy.rb
60
+ - lib/nanite/nanite_dispatcher.rb
61
+ - lib/nanite/packets.rb
62
+ - lib/nanite/pid_file.rb
63
+ - lib/nanite/reaper.rb
64
+ - lib/nanite/redis_tag_store.rb
50
65
  - lib/nanite/security
51
- - lib/nanite/security/distinguished_name.rb
52
- - lib/nanite/security/secure_serializer.rb
53
- - lib/nanite/security/certificate_cache.rb
54
- - lib/nanite/security/signature.rb
66
+ - lib/nanite/security/cached_certificate_store_proxy.rb
55
67
  - lib/nanite/security/certificate.rb
68
+ - lib/nanite/security/certificate_cache.rb
69
+ - lib/nanite/security/distinguished_name.rb
56
70
  - lib/nanite/security/encrypted_document.rb
57
71
  - lib/nanite/security/rsa_key_pair.rb
72
+ - lib/nanite/security/secure_serializer.rb
73
+ - lib/nanite/security/signature.rb
58
74
  - lib/nanite/security/static_certificate_store.rb
59
- - lib/nanite/security/cached_certificate_store_proxy.rb
60
- - lib/nanite/config.rb
61
- - lib/nanite/util.rb
62
- - lib/nanite/log
63
- - lib/nanite/log/formatter.rb
64
- - lib/nanite/state.rb
65
- - lib/nanite/cluster.rb
66
- - lib/nanite/dispatcher.rb
67
75
  - lib/nanite/security_provider.rb
68
- - lib/nanite/packets.rb
69
- - lib/nanite/actor.rb
70
- - lib/nanite/console.rb
71
- - lib/nanite/admin.rb
72
- - lib/nanite/amqp.rb
73
- - lib/nanite/agent.rb
74
- - lib/nanite/local_state.rb
75
- - lib/nanite/identity.rb
76
- - lib/nanite/actor_registry.rb
77
- - lib/nanite/log.rb
78
- - lib/nanite/reaper.rb
79
- - lib/nanite/job.rb
80
- - bin/nanite-agent
76
+ - lib/nanite/serializer.rb
77
+ - lib/nanite/state.rb
78
+ - lib/nanite/streaming.rb
79
+ - lib/nanite/util.rb
80
+ - lib/nanite.rb
81
81
  - bin/nanite-admin
82
+ - bin/nanite-agent
82
83
  - bin/nanite-mapper
83
- - spec/util_spec.rb
84
- - spec/encrypted_document_spec.rb
85
- - spec/agent_spec.rb
86
- - spec/certificate_cache_spec.rb
87
- - spec/cached_certificate_store_proxy_spec.rb
88
- - spec/dispatcher_spec.rb
89
- - spec/log_spec.rb
90
- - spec/rsa_key_pair_spec.rb
91
- - spec/cluster_spec.rb
92
- - spec/spec_helper.rb
93
- - spec/mapper_spec.rb
94
- - spec/actor_registry_spec.rb
95
- - spec/actor_spec.rb
96
- - spec/packet_spec.rb
97
- - spec/local_state_spec.rb
98
- - spec/static_certificate_store_spec.rb
99
- - spec/job_spec.rb
100
- - spec/signature_spec.rb
101
- - spec/mapper_proxy_spec.rb
102
- - spec/secure_serializer_spec.rb
103
- - spec/serializer_spec.rb
104
- - spec/certificate_spec.rb
105
- - spec/nanite_spec.rb
106
- - spec/distinguished_name_spec.rb
107
84
  has_rdoc: true
108
85
  homepage: http://github.com/ezmobius/nanite
109
- licenses:
110
86
  post_install_message:
111
87
  rdoc_options: []
112
88
 
@@ -127,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
103
  requirements: []
128
104
 
129
105
  rubyforge_project:
130
- rubygems_version: 1.3.5
106
+ rubygems_version: 1.3.1
131
107
  signing_key:
132
108
  specification_version: 2
133
109
  summary: self assembling fabric of ruby daemons
@@ -1,60 +0,0 @@
1
- require File.join(File.dirname(__FILE__), 'spec_helper')
2
-
3
- describe Nanite::ActorRegistry do
4
-
5
- class ::WebDocumentImporter
6
- include Nanite::Actor
7
- expose :import, :cancel
8
-
9
- def import
10
- 1
11
- end
12
- def cancel
13
- 0
14
- end
15
- end
16
-
17
- module ::Actors
18
- class ComedyActor
19
- include Nanite::Actor
20
- expose :fun_tricks
21
- def fun_tricks
22
- :rabbit_in_the_hat
23
- end
24
- end
25
- end
26
-
27
- before(:each) do
28
- Nanite::Log.stub!(:info)
29
- @registry = Nanite::ActorRegistry.new
30
- end
31
-
32
- it "should know about all services" do
33
- @registry.register(WebDocumentImporter.new, nil)
34
- @registry.register(Actors::ComedyActor.new, nil)
35
- @registry.services.sort.should == ["/actors/comedy_actor/fun_tricks", "/web_document_importer/cancel", "/web_document_importer/import"]
36
- end
37
-
38
- it "should not register anything except Nanite::Actor" do
39
- lambda { @registry.register(String.new, nil) }.should raise_error(ArgumentError)
40
- end
41
-
42
- it "should register an actor" do
43
- importer = WebDocumentImporter.new
44
- @registry.register(importer, nil)
45
- @registry.actors['web_document_importer'].should == importer
46
- end
47
-
48
- it "should log info message that actor was registered" do
49
- importer = WebDocumentImporter.new
50
- Nanite::Log.should_receive(:info).with("[actor] #{importer.class.to_s}")
51
- @registry.register(importer, nil)
52
- end
53
-
54
- it "should handle actors registered with a custom prefix" do
55
- importer = WebDocumentImporter.new
56
- @registry.register(importer, 'monkey')
57
- @registry.actor_for('monkey').should == importer
58
- end
59
-
60
- end # Nanite::ActorRegistry