rightscale-nanite 0.4.1.4 → 0.4.1.10

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