Class: Zack::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/zack/server.rb

Overview

Server side for RPC calls.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tube_name, opts = {}) ⇒ Server

Initializes a zack server. To specify which class should be the target of the RPC call, you must either give the :factory or the :simple argument.

:simple expects a class. This class will be constructed each time a request is made. Then the method will be called on the class.

:factory expects a callable (a block or something that has #call) and is passed the control object for the request (see Cod for an explanation of this). You can chose to ignore the control and just use the block to produce an object that is linked to the rest of your program. Or you can link to the rest of the program and the control at the same time.

Note that in any case, one object instance _per call_ is created. This is to discourage creating stateful servers. If you still want to do that, well you will just have to code around the limitation, now won’t you.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/zack/server.rb', line 28

def initialize(tube_name, opts={})
  @server = opts[:server]

  if opts.has_key? :factory
    @factory = opts[:factory]
  elsif opts.has_key? :simple
    klass = opts[:simple]
    @factory = lambda { |ctl| klass.new }
  else
    raise ArgumentError, "Either :factory or :simple argument must be given." 
  end
 
  channel = Cod.beanstalk(tube_name, server)
  @service = channel.service
end

Instance Attribute Details

#factoryObject (readonly)

Returns the value of attribute factory.



7
8
9
# File 'lib/zack/server.rb', line 7

def factory
  @factory
end

#serverObject (readonly)

Returns the value of attribute server.



8
9
10
# File 'lib/zack/server.rb', line 8

def server
  @server
end

#serviceObject (readonly)

Returns the value of attribute service.



6
7
8
# File 'lib/zack/server.rb', line 6

def service
  @service
end

Instance Method Details

#handle_request(exception_handler = nil) ⇒ Object

Handles exactly one request.



46
47
48
49
50
51
52
53
# File 'lib/zack/server.rb', line 46

def handle_request(exception_handler=nil)
  service.one { |(sym, args), control|
    exception_handling(exception_handler, control) do
      # p [sym, args]
      process_request(control, sym, args)
    end
  }
end

#process_request(control, sym, args) ⇒ Object

Processes exactly one request, but doesn’t define how the request gets here.



58
59
60
61
62
# File 'lib/zack/server.rb', line 58

def process_request(control, sym, args)
  instance = factory.call(control)

  instance.send(sym, *args)
end

#run(messages = nil, &exception_handler) ⇒ Object

Runs the server and keeps running until the world ends (or the process, whichever comes first). If you pass a non-nil messages argument, the server will process that many messages and then quit. (Maybe you will want to respawn the server from time to time?)

Any exception that is raised inside the RPC code will be passed to the exception_handler block:

server.run do |exception, control|
  # control is the service control object from cod. You can exercise
  # fine grained message control using this. 
  log.fatal exception
end

If you don’t reraise exceptions from the exception handler block, they will be caught and the server will stay running.



81
82
83
84
85
86
87
88
89
90
# File 'lib/zack/server.rb', line 81

def run(messages=nil, &exception_handler)
  loop do
    handle_request(exception_handler)

    if messages
      messages -= 1
      break if messages <= 0
    end
  end
end