Class: Jerbil::ServiceRecord

Inherits:
Object
  • Object
show all
Defined in:
lib/jerbil/service.rb

Overview

Define a service record for a service to register with Jerbil

Used internally by Broker and JerbilService to record information about running services. Is made available to users through the JerbilService::Client interface where it can be used, for example, to get the service’s key.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, env, verify_callback = :verify_callback, stop_callback = nil) ⇒ ServiceRecord

create a new service record object

Note that the callback parameters do not really need to be considered if you are using JerbilService::Base

Warning - if your hostname is not fully qualified this may not work as expected if you DNS server does not provide expected reverse lookup. Consider using ‘hostname -f` although *nix dependent.

Parameters:

  • name (Symbol)

    identifying the service - needs to match /etc/services or create fails with the exception InvalidService

  • env (Symbol)

    identify the service’s environment. Allows multiple services to operate for development etc

  • verify_callback (Symbol) (defaults to: :verify_callback)

    being the name of the method to call to check that the service is working

  • stop_callback (Symbol) (defaults to: nil)

    as above but the method stops the service

Raises:

  • (InvalidService)

    if the service is not registered through /etc/services



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/jerbil/service.rb', line 48

def initialize(name, env, verify_callback=:verify_callback, stop_callback=nil)
  
  # gethostname may npt provide the fqdn
  @host = Socket.gethostname
  if @host.split('.').length == 1 then
    # no domain name
    @host = Socket.gethostbyname(@host).first
  end
  @name = name
  begin
    @port = Socket.getservbyname(@name.to_s)
  rescue
    raise InvalidService, "No service registered as: #{name}"
  end

  # now increment it if not production
  @port += 1 if env == :test
  @port += 2 if env == :dev

  @env = env
  @key = Digest::SHA1.hexdigest(Time.now.to_s + rand(12341234).to_s)[1..10]
  @pid = Process.pid
  @verify_callback = verify_callback
  @stop_callback = stop_callback
  @lock = nil
  @address = @host + ':' + @port.to_s
  @registered_at = nil
  @access_count = 0
  @accessed_at = nil
  @close = true
end

Instance Attribute Details

#access_countObject (readonly)

the number of times the service has been accessed on Jerbil since it was registered



98
99
100
# File 'lib/jerbil/service.rb', line 98

def access_count
  @access_count
end

#accessed_atObject (readonly)

the date/time at which the service was last accessed



100
101
102
# File 'lib/jerbil/service.rb', line 100

def accessed_at
  @accessed_at
end

#addressObject (readonly)

the full DRb address used to contact the service This is only required by Jerbil and should not be needed by the casual user.



91
92
93
# File 'lib/jerbil/service.rb', line 91

def address
  @address
end

#envObject (readonly)

environment the service is running in



83
84
85
# File 'lib/jerbil/service.rb', line 83

def env
  @env
end

#hostObject (readonly)

the host on which the service is running



87
88
89
# File 'lib/jerbil/service.rb', line 87

def host
  @host
end

#keyObject (readonly)

the key needed to access the service



85
86
87
# File 'lib/jerbil/service.rb', line 85

def key
  @key
end

#nameObject (readonly)

name of the service



81
82
83
# File 'lib/jerbil/service.rb', line 81

def name
  @name
end

#portObject (readonly)

the port used by the service



93
94
95
# File 'lib/jerbil/service.rb', line 93

def port
  @port
end

#registered_atObject (readonly)

the date/time at which the service was registered with Jerbil



95
96
97
# File 'lib/jerbil/service.rb', line 95

def registered_at
  @registered_at
end

Instance Method Details

#==(rhs) ⇒ Object

compares services directly and returns true if they have the same name, env, host and key

Parameters:



158
159
160
# File 'lib/jerbil/service.rb', line 158

def ==(rhs)
  self.matches?(:name=>rhs.name, :env=>rhs.env, :host=>rhs.host, :key=>rhs.key)
end

#argsObject

return a hash containing the find arguments for self



120
121
122
# File 'lib/jerbil/service.rb', line 120

def args
  {:name=>@name, :env=>@env, :host=>@host, :key=>@key}
end

#closeObject

close the connection to the service



205
206
207
# File 'lib/jerbil/service.rb', line 205

def close
  DRb.stop_service if @close
end

#connect(verify = true) ⇒ Object

connect to the service represented by this record

You do not need to use this method if you use JerbilService::Client to manage the client-server interface direct.

This return a DRb session for the given service set verify to true (default) to call the services keep_alive method

Parameters:

  • verify (Boolean) (defaults to: true)

    if the service is running immedaitely after connecting

Raises:

  • (ServiceCallbackMissing)

    if the verify method in this record does not match the methods of the service being connected to (you have mucked it up!)

  • (ServiceConnectError)

    if any other exception is raised during the connect process.



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/jerbil/service.rb', line 176

def connect(verify=true)
  self.start_drb_if_needed
  service = DRbObject.new(nil, "druby://#{@address}")
  key = service.send(@verify_callback, @key) if verify
  return service
rescue NoMethodError
  raise ServiceCallbackMissing
rescue
  raise ServiceConnectError

end

#drb_addressObject

convenience method to assist JerbilService actions

drb_address makes it easier to start a DRb server, which is done outside this class because it should only be done under specific circumstances, and not by the general users of this class



194
195
196
# File 'lib/jerbil/service.rb', line 194

def drb_address
  "druby://#{@host}:#{@port}"
end

#identObject

return a string containing the name, env, host etc



115
116
117
# File 'lib/jerbil/service.rb', line 115

def ident
  "#{@name}[#{@env}]@#{@address}"
end

#local?Boolean

is the service local to the caller?

Returns:

  • (Boolean)


199
200
201
# File 'lib/jerbil/service.rb', line 199

def local?
  return @host == Socket.gethostname
end

#log_accessObject

method to allow Jerbil to record an access to this service



109
110
111
112
# File 'lib/jerbil/service.rb', line 109

def log_access
  @accessed_at = Time.now
  @access_count += 1
end

#matches?(args = {}) ⇒ Boolean

compare services according to a set of arguments

This will return true if the service matches the given keys. An argument of nil matches all services. Uses the same arguments as Broker#find except that it will ignore the :ignore_access argument!

Parameters:

  • args (Hash) (defaults to: {})

    search arguments

Options Hash (args):

  • :name (String)

    to match exactly the name of the service

  • :env (Symbol)

    to match the services environment (:dev, :test, :prod)

  • :host (String)

    to match exactly the name of the host on which the service is running

  • :key (String)

    to match exactly the service key

  • :ignore_access (Boolean)

    do not count this call as an access

Returns:

  • (Boolean)


133
134
135
136
137
138
139
140
141
# File 'lib/jerbil/service.rb', line 133

def matches?(args={})
  options = {:name => nil, :env => nil, :host=>nil, :key => nil}.merge(args)
  is_equal = true
  is_equal = @name == options[:name] unless options[:name].nil?
  is_equal = is_equal && @env == options[:env] unless options[:env].nil?
  is_equal = is_equal && @host == options[:host] unless options[:host].nil?
  is_equal = is_equal && @key == options[:key] unless options[:key].nil?
  return is_equal
end

#registerObject

method to allow Jerbil to set when the service was registered



103
104
105
106
# File 'lib/jerbil/service.rb', line 103

def register
  @registered_at = Time.now
  @accessed_at = @registered_at
end

#same_service?(rhs) ⇒ Boolean

compares services directly and returns true if they have the same name, env, and host.

Note that this ignores the service records key, allowing you to find instances of the same service e.g. that have previously been registered.

Parameters:

Returns:

  • (Boolean)


150
151
152
# File 'lib/jerbil/service.rb', line 150

def same_service?(rhs)
  self.matches?(:name=>rhs.name, :env=>rhs.env, :host=>rhs.host)
end