Module: Omega::Server::Registry

Included in:
Cosmos::Registry, Manufactured::Registry, Missions::Registry, Motel::Registry, Users::Registry
Defined in:
lib/omega/server/registry.rb

Overview

Defines a mechanism which provides protected access to entities and runs event loops

Constant Summary collapse

DEFAULT_LOOP_POLL =

Default time loop threads sleep between event cycles

1
DEFAULT_EVENT_POLL =

Default time event loop thread sleeps between event cycles

0.5
DEFAULT_COMMAND_POLL =

Default time command loop thread sleeps between command cycles

0.5

Config options collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.loop_pollObject

Default loop poll


31
32
33
# File 'lib/omega/server/registry.rb', line 31

def loop_poll
  @loop_poll
end

Instance Attribute Details

#backup_excludesObject

Returns the value of attribute backup_excludes


476
477
478
# File 'lib/omega/server/registry.rb', line 476

def backup_excludes
  @backup_excludes
end

#nodeObject

Returns the value of attribute node


60
61
62
# File 'lib/omega/server/registry.rb', line 60

def node
  @node
end

#retrievalObject

Returns the value of attribute retrieval


71
72
73
# File 'lib/omega/server/registry.rb', line 71

def retrieval
  @retrieval
end

#userObject

Returns the value of attribute user


62
63
64
# File 'lib/omega/server/registry.rb', line 62

def user
  @user
end

#validation_methodsObject

Returns the value of attribute validation_methods


64
65
66
# File 'lib/omega/server/registry.rb', line 64

def validation_methods
  @validation_methods
end

Instance Method Details

#<<(entity) ⇒ Object

Add entity to local registry.

Invokes registered validation callbacks before adding to ensure enitity should be added. If any validation returns false, entity will not be added.

Raises :added event on self w/ entity


122
123
124
125
126
127
128
129
130
131
132
# File 'lib/omega/server/registry.rb', line 122

def <<(entity)
  init_registry
  add = false
  @lock.synchronize {
    add = @validation_methods.all? { |v| v.call(@entities, entity) }
    @entities << entity if add
  }

  self.raise_event(:added, entity) if add
  return add
end

#cleanup_event(event) ⇒ Object

Cleanup specified event and handlers Skip event handlers marked as persistant


379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/omega/server/registry.rb', line 379

def cleanup_event(event)
  self.safe_exec { |entities|
    # Lookup event if user specified event id
    event = entities.find { |e| e.is_a?(Event) &&
                                e.id == event     } if event.is_a?(String)
    return if event.nil?

    to_remove =
      entities.select { |e|
        (e.is_a?(Event) && e.id == event.id) ||
        (e.is_a?(EventHandler) && e.matches?(event) && !e.persist) }

    # TODO optional event 'graveyard'
    @entities -= to_remove
  }
end

#clear!Object

Clear all entities tracked by local registry


107
108
109
110
111
112
# File 'lib/omega/server/registry.rb', line 107

def clear!
  init_registry
  @lock.synchronize {
    @entities = []
  }
end

#delete(&selector) ⇒ Object

Remove entity from local registry. Entity removed will be first entity for which selector returns true.

Raises :delete event on self w/ deleted entity


138
139
140
141
142
143
144
145
146
147
148
# File 'lib/omega/server/registry.rb', line 138

def delete(&selector)
  init_registry
  delete = false
  @lock.synchronize {
    entity = @entities.find(&selector)
    delete = !entity.nil?
    @entities.delete(entity) if delete
  }
  self.raise_event(:deleted, entity) if delete
  return delete
end

#entities(&select) ⇒ Object

Return entities for which selector proc returns true

Note only copies of entities will be returned, not the actual entities themselves


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/omega/server/registry.rb', line 82

def entities(&select)
  init_registry
  @lock.synchronize {
    # by default return everything
    select = proc { |e| true } if select.nil?

    # registry entities
    rentities = @entities.select(&select)

    # invoke retrieval to update each registry entity
    rentities.each { |r| @retrieval.call(r) }

    # we use json serialization to perform a deep clone
    result = Array.new(RJR::JSONParser.parse(rentities.to_json))

    result
  }
end

#entity(&select) ⇒ Object

Return first entity which selector proc returns true


102
103
104
# File 'lib/omega/server/registry.rb', line 102

def entity(&select)
  self.entities(&select).first
end

#exclude_from_backup(cl) ⇒ Object


478
479
480
# File 'lib/omega/server/registry.rb', line 478

def exclude_from_backup(cl)
  @backup_excludes << cl
end

#joinObject

Join all event loop workers


276
277
278
279
280
# File 'lib/omega/server/registry.rb', line 276

def join
  init_registry
  @workers.each { |w| w.join }
  self
end

#on(eid, &bl) ⇒ Object

Register block to be invoked on specified event(s)


218
219
220
221
222
223
224
225
226
# File 'lib/omega/server/registry.rb', line 218

def on(eid, &bl)
  init_registry
  @lock.synchronize {
    eid = [eid] unless eid.is_a?(Array)
    eid.each { |id|
      @event_handlers[id] << bl
    }
  }
end

#proxies_for(&selector) ⇒ Object

Return proxy objects for entities specified by selector which may be used to update entities safely w/out going directly through the registry

TODO invalidate proxies if corresponding entities are deleted ?


188
189
190
191
192
193
194
# File 'lib/omega/server/registry.rb', line 188

def proxies_for(&selector)
  init_registry
  @lock.synchronize {
    @entities.select(&selector).
              collect { |e| ProxyEntity.new(e, self) }
  }
end

#proxy_for(&selector) ⇒ Object

Return a single proxy object for the first matched entity, nil if not found


198
199
200
# File 'lib/omega/server/registry.rb', line 198

def proxy_for(&selector)
  proxies_for(&selector).first
end

#raise_event(event, *params) ⇒ Object

Raises specified event, invoking registered handlers


229
230
231
232
233
234
235
236
237
238
# File 'lib/omega/server/registry.rb', line 229

def raise_event(event, *params)
  init_registry
  handlers = []
  @lock.synchronize{
    handlers =
      @event_handlers[event] if @event_handlers.has_key?(event)
  }
  handlers.each { |h| h.call *params }
  nil
end

#restore(io) ⇒ Object

Restore state


495
496
497
498
499
500
# File 'lib/omega/server/registry.rb', line 495

def restore(io)
  init_registry
  io.each_line { |json|
    self << RJR::JSONParser.parse(json)
  }
end

#run(&lp) ⇒ Object

Return the specified event loop in a new worker

The workers will delay for the amount of type specified by the return value of the event loop before running it again.


246
247
248
249
250
251
252
# File 'lib/omega/server/registry.rb', line 246

def run(&lp)
  init_registry
  @lock.synchronize {
    @event_loops << lp
    start_worker(lp) unless @terminate.nil? || @terminate
  }
end

#running?Boolean

Return boolean indicating if events loops are running


283
284
285
286
287
288
289
# File 'lib/omega/server/registry.rb', line 283

def running?
  init_registry
  @lock.synchronize {
    !@terminate &&
    @workers.collect { |w| w.status }.all? { |s| ['sleep', 'run'].include?(s) }
  }
end

#safe_execObject

Safely execute a block of code in the context of the local registry.

Pasess the raw entities array to block for unrestricted querying/manipulation (be careful!)


208
209
210
211
212
213
# File 'lib/omega/server/registry.rb', line 208

def safe_exec
  init_registry
  @lock.synchronize {
    yield @entities
  }
end

#save(io) ⇒ Object

Save state


483
484
485
486
487
488
489
490
491
492
# File 'lib/omega/server/registry.rb', line 483

def save(io)
  init_registry
  @lock.synchronize {
    @entities.each { |entity|
      should_exclude = @backup_excludes.any? { |exclude_class|
                                entity.kind_of?(exclude_class) }
      io.write entity.to_json + "\n" unless should_exclude
    }
  }
end

#startObject

Star the event loop workers


255
256
257
258
259
260
261
262
263
264
# File 'lib/omega/server/registry.rb', line 255

def start
  init_registry
  @lock.synchronize {
    @terminate = false
    @event_loops.each { |lp|
      start_worker(lp)
    }
  }
  self
end

#stopObject

Stop the event loop works and subsequent invocations


267
268
269
270
271
272
273
# File 'lib/omega/server/registry.rb', line 267

def stop
  init_registry
  @lock.synchronize {
    @terminate = true
  }
  self
end

#to_sObject

other


504
505
506
507
508
# File 'lib/omega/server/registry.rb', line 504

def to_s
  @lock.synchronize {
    "#{self.class}-#{@entities.size}/#{@event_loops.size}/#{@workers.size}"
  }
end

#update(entity, &selector) ⇒ Object

Update entity in local registry.

Entity updated will be first entity for which the selector proc returns true. The entity being updated must define the 'update' method which takes another entity which to copy attributes from/etc.

Raises :updated event on self with updated entity


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/omega/server/registry.rb', line 158

def update(entity, &selector)
  # TODO default selector ? (such as with_id)
  init_registry
  rentity = nil
  old_entity = nil
  @lock.synchronize {
    # select entity from registry
    rentity = @entities.find &selector

    unless rentity.nil?
      # copy it
      old_entity = RJR::JSONParser.parse(rentity.to_json)

      # update it
      rentity.update(entity)
    end

  }

  # TODO make sure proxy operations are kept in sync w/ update operations
  #   (see proxy_for below and ProxyEntity definition)
  self.raise_event(:updated, rentity, old_entity) unless rentity.nil?
  return !rentity.nil?
end

#validation_callback(&bl) ⇒ Object

Add validation method to registry


67
68
69
# File 'lib/omega/server/registry.rb', line 67

def validation_callback(&bl)
  @validation_methods << bl
end