Class: MarilynRPC::ServiceCache

Inherits:
Object
  • Object
show all
Defined in:
lib/marilyn-rpc/service_cache.rb

Overview

# This class represents a per connection cache of the service instances.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeServiceCache

creates the service cache



7
8
9
# File 'lib/marilyn-rpc/service_cache.rb', line 7

def initialize
  @services = {}
end

Instance Attribute Details

#usernameString?

the username of a authenticated user oder nil

Returns:

  • (String, nil)

    the current value of username



3
4
5
# File 'lib/marilyn-rpc/service_cache.rb', line 3

def username
  @username
end

Instance Method Details

#call(envelope) ⇒ MarilynRPC::CallResponseMail, MarilynRPC::Gentleman

call a service in the service cache

Parameters:

  • envelope (MarilynRPC::Envelope)

    the envelope that contains the request subject (mail), that should be handled

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/marilyn-rpc/service_cache.rb', line 16

def call(envelope)
  mail = MarilynRPC::MailFactory.unpack(envelope)
  tag = mail.tag
  
  if mail.is_a?(MarilynRPC::CallRequestMail) # handle a call request
    # fetch the service and check if the user has the permission to access the
    # service
    service = lookup(mail.path)
    method = mail.method.to_sym
    if service.class.__methods_with_authentication__[method] && !@username 
      raise MarilynRPC::PermissionDeniedError.new("No permission to access" \
            " the #{service.class.name}##{method}")
    end

    # call the service instance using the argument of the mail
    #puts "call #{mail.method}@#{mail.path} with #{mail.args.inspect}"
    result = service.__send__(method, *mail.args)
    #puts "result => #{result.inspect}"

    # no direct result, register callback
    if result.is_a? MarilynRPC::Gentleman
      result.tag = tag # set the correct mail tag for the answer
      result
    else # direct response
      MarilynRPC::Envelope.new(MarilynRPC::CallResponseMail.new(tag, result).encode, 
                               MarilynRPC::CallResponseMail::TYPE).encode
    end
  else
    raise MarilynRPC::BrokenEnvelopeError.new("Expected CallRequestMail Object!")
  end
rescue MarilynRPC::BrokenEnvelopeError => exception
  MarilynRPC::Envelope.new(MarilynRPC::ExceptionMail.new(nil, exception).encode, 
                           MarilynRPC::ExceptionMail::TYPE).encode
rescue => exception
  #puts exception
  #puts exception.backtrace.join("\n   ")
  MarilynRPC::Envelope.new(MarilynRPC::ExceptionMail.new(tag, exception).encode, 
                           MarilynRPC::ExceptionMail::TYPE).encode
end

#disconnect!Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

issue the disconnect callbacks for all living services of this connection



77
78
79
80
81
# File 'lib/marilyn-rpc/service_cache.rb', line 77

def disconnect!
  @services.each do |path, service|
    service.__run_callbacks__(:after_disconnect)
  end
end

#lookup(path) ⇒ Object

get the service from the cache or the service registry

Parameters:

  • path (Object)

    the path to the service (using the regestry)

Returns:

  • (Object)

    the service object or raises an ArgumentError



59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/marilyn-rpc/service_cache.rb', line 59

def lookup(path)
  # lookup the service in the cache
  if service = @services[path]
    return service
  # it's not in the cache, so try lookup in the service registry
  elsif service = MarilynRPC::Service.__registry__[path]
    @services[path] = service.new
    @services[path].service_cache = self
    @services[path].__run_callbacks__(:after_connect)
    return @services[path]
  else
    raise MarilynRPC::UnknownServiceError.new("Service #{path} unknown!")
  end
end