carioca 0.1 → 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +3 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +4 -0
- data/README.md +236 -0
- data/carioca.gemspec +2 -2
- data/doc/manual.rdoc +192 -3
- data/lib/carioca.rb +277 -187
- data/lib/carioca_private.rb +100 -0
- data/lib/services.rb +58 -2
- data/lib/services/configuration.rb +150 -18
- data/lib/services/debug.rb +15 -12
- data/lib/services/logger.rb +18 -12
- data/spec/carioca_spec.rb +157 -19
- data/spec/config/services.registry +14 -14
- data/spec/samples/dummy.rb +1 -1
- data/spec/samples/otherdummy.rb +10 -0
- data/spec/samples/requireddummy.rb +10 -0
- data/ultragreen_roodi_coding_convention.yml +1 -1
- metadata +10 -7
data/lib/carioca.rb
CHANGED
@@ -1,218 +1,308 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#---
|
3
|
+
# Author : Romain GEORGES
|
4
|
+
# type : gem component library
|
5
|
+
# obj : Carioca Module
|
6
|
+
#---
|
7
|
+
|
1
8
|
require 'yaml'
|
2
9
|
require 'rubygems'
|
3
10
|
require 'methodic'
|
4
11
|
require 'services'
|
5
12
|
require 'daemons'
|
13
|
+
require 'carioca_private'
|
14
|
+
|
6
15
|
|
16
|
+
|
17
|
+
# module Carioca
|
18
|
+
# @author Romain GEORGES <romain@ultragreen.net>
|
19
|
+
# @see http://www.ultragreen.net/projects/carioca
|
20
|
+
# @version 1.0
|
21
|
+
# @note this module is a namespace Carioca
|
7
22
|
module Carioca
|
8
23
|
|
9
|
-
|
10
|
-
|
24
|
+
|
25
|
+
|
26
|
+
# module Services
|
27
|
+
# @note this module is a namespace Carioca::Services
|
28
|
+
module Services
|
11
29
|
|
12
30
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
31
|
+
# class Registry
|
32
|
+
# This class provide the Registry manager for Carioca
|
33
|
+
# @note this class is a Singleton Class to instanciate do not use new (initializer), but :
|
34
|
+
# Carioca::Services::Registry.init options
|
35
|
+
# @example Complete usage
|
36
|
+
# require 'rubygems'
|
37
|
+
# require 'carioca'
|
38
|
+
# registry = Carioca::Services::Registry.init
|
39
|
+
# registry = Carioca::Services::Registry.init :file => 'myservices.registry'
|
40
|
+
# registry = Carioca::Services::Registry.init :file => 'myservices.registry', :debug => true
|
41
|
+
class Registry
|
42
|
+
|
43
|
+
include PrivateMethodsCariocaServicesRegistry
|
22
44
|
|
45
|
+
# for singleton
|
46
|
+
private_class_method :new
|
47
|
+
private :verify_requires_dependancies
|
48
|
+
private :require_service
|
49
|
+
private :instanciate_service
|
50
|
+
private :kill_service
|
51
|
+
|
23
52
|
|
24
|
-
|
53
|
+
@@inst = nil
|
25
54
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
55
|
+
# Singleton constructor for Registry
|
56
|
+
# @param [Hash] _options the options, keys are symbols
|
57
|
+
# @option _options [String] :file The path of your registry YAML definition (see YAML registry format)
|
58
|
+
# @option _options [TrueClass,FalseClass] :debug Boolean activation/deactiviation of the carioca debug mode (log traces)
|
59
|
+
# @return [Carioca::Services::Registry] Singleton class instance of Registry
|
60
|
+
# @example usage
|
61
|
+
# registry = Carioca::Services::Registry.init # or
|
62
|
+
# registry = Carioca::Services::Registry.init :file => 'myservices.registry' # or
|
63
|
+
# registry = Carioca::Services::Registry.init :file => 'myservices.registry', :debug => true
|
64
|
+
def Registry.init(_options = {})
|
65
|
+
options = Methodic::get_options(_options) do |m|
|
66
|
+
m.specify_defaults_value :file => './services.registry', :debug => false
|
67
|
+
m.merge!
|
68
|
+
end
|
69
|
+
@@inst = new(options) if @@inst.nil?
|
70
|
+
return @@inst
|
71
|
+
end
|
72
|
+
|
73
|
+
# @example read
|
74
|
+
# registry = Carioca::Services::Registry.init
|
75
|
+
# p registry.registry_filename
|
76
|
+
# @example write
|
77
|
+
# registry = Carioca::Services::Registry.init
|
78
|
+
# p registry.registry_filename = '/tmp/test.file'
|
79
|
+
# @attr_reader [Hash] list a hash table of all structured registred services definition
|
80
|
+
# (come from file and explicitly registered services)
|
81
|
+
attr_accessor :registry_filename
|
82
|
+
|
83
|
+
# @example
|
84
|
+
# registry = Carioca::Services::Registry.init
|
85
|
+
# p registry.list
|
86
|
+
# @attr_reader [Hash] list a hash table of all structured registred services definition
|
87
|
+
# (come from file and explicitly registered services)
|
88
|
+
attr_reader :list
|
32
89
|
|
33
|
-
|
34
|
-
|
90
|
+
# @example
|
91
|
+
# registry = Carioca::Services::Registry.init
|
92
|
+
# p registry.loaded_services # you should see the logger service Hash definition
|
93
|
+
# @attr_reader [Hash] loaded_services a hash table of all structured loaded services
|
94
|
+
attr_reader :loaded_services
|
95
|
+
|
96
|
+
# @example
|
97
|
+
# registry = Carioca::Services::Registry.init
|
98
|
+
# p registry.debug
|
99
|
+
# @attr_reader [TrueClass,FalseClass] debug a boolean of the current debug status
|
100
|
+
attr_reader :debug
|
101
|
+
|
102
|
+
# writer accessor for debug (interaction with log service)
|
103
|
+
# @example
|
104
|
+
# registry = Carioca::Services::Registry.init
|
105
|
+
# p registry.debug = true
|
106
|
+
# @param [TrueClass,FalseClass] _value true or false to activate/deactivate debug mode
|
107
|
+
# @note interaction with preloaded service logger
|
108
|
+
def debug=(_value)
|
35
109
|
@log.level =(_value)? Logger::DEBUG : Logger::INFO
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
def stop_service(_options)
|
40
|
-
options = Methodic.get_options(_options)
|
41
|
-
options.specify_class_of :name => String
|
42
|
-
options.specify_presence_of([:name])
|
43
|
-
options.validate!
|
44
|
-
if @loaded_services.include?(options[:name]) then
|
45
|
-
@loaded_engines[options[:name]].garbage if @loaded_services[options[:name]].respond_to? :garbage
|
46
|
-
@loaded_services.delete(options[:name])
|
47
|
-
@log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log
|
48
|
-
return true
|
49
|
-
else
|
50
|
-
@log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log
|
51
|
-
return false
|
52
110
|
end
|
53
111
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
return true
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
112
|
+
|
113
|
+
# stop a service, if loaded and different to logger
|
114
|
+
# @param [Hash] _options the options, keys are symbols
|
115
|
+
# @option _options [String] :name The name of the service to stop
|
116
|
+
# @return [TruaClass,FalseClass] true if service effectivly stopped, false if not, or :name == 'logger'
|
117
|
+
# @example usage
|
118
|
+
# registry = Carioca::Services::Registry.init
|
119
|
+
# registry.start_service :name => 'configuration'
|
120
|
+
# registry.stop_service :name => 'configuration'
|
121
|
+
# #=> return true
|
122
|
+
# registry.stop_service :name => 'configuration'
|
123
|
+
# #=> return false
|
124
|
+
# registry.stop_service :name => 'logger'
|
125
|
+
# #=> return false
|
126
|
+
# @note log if debug mode
|
127
|
+
def stop_service(_options)
|
128
|
+
options = Methodic.get_options(_options)
|
129
|
+
options.specify_class_of :name => String
|
130
|
+
options.specify_presence_of([:name])
|
131
|
+
options.validate!
|
132
|
+
if @loaded_services.include?(options[:name]) then
|
133
|
+
# prevent logger services killing
|
134
|
+
if options[:name] == 'logger' then
|
135
|
+
@log.debug('Carioca') { "Service logger can't be unloaded" } if @log
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
# calling private killer
|
139
|
+
kill_service options[:name]
|
140
|
+
@log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log
|
141
|
+
return true
|
142
|
+
else
|
143
|
+
@log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
|
85
147
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
@
|
95
|
-
|
96
|
-
return
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
148
|
+
|
149
|
+
# register a new service in registry added to @list
|
150
|
+
# @param [Hash] _options the options hash, key are :symbols
|
151
|
+
# @option _options [String] :name the name of the service (required)
|
152
|
+
# @option _options [String] :resource the resource, must be a gem name, a fullpath filename, a builtin service (required)
|
153
|
+
# @option _options [Symbol] :type the resource type of the service, must be :gem, :builtin or :file (required)
|
154
|
+
# @option _options [String] :service the realname of the service class with namespace (eg. ExternalServices::Dummy )
|
155
|
+
# @option _options [String] :description the description of the service (required)
|
156
|
+
# @option _options [Hash] :init_options the params of the service, keys are symbols
|
157
|
+
# @option _options [Array] :requires the list of [String] services name required to load this service
|
158
|
+
# @return [TrueClass,FalseClass] true if service is added
|
159
|
+
# @raise ArgumentError when :type is not in [:gem,:file,:builtin]
|
160
|
+
def register_service(_options)
|
161
|
+
options = Methodic.get_options(_options)
|
162
|
+
options.specify_classes_of({:name => String, :resource => String, :description => String, :type => Symbol, :service => String })
|
163
|
+
options.specify_presences_of([:name,:type,:resource,:service])
|
164
|
+
cond = Proc::new{|option| case option
|
165
|
+
when :gem then true
|
166
|
+
when :file then true
|
167
|
+
when :builtin then true
|
168
|
+
else false end }
|
169
|
+
options.specify_condition_for :type => cond
|
170
|
+
options.validate!
|
171
|
+
_name = _options.delete(:name)
|
172
|
+
@list[_name] = _options
|
173
|
+
return true
|
111
174
|
end
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
@
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
175
|
+
|
176
|
+
# unregister a service in registry removed from @list
|
177
|
+
# @param [Hash] _options the options hash, key are :symbols
|
178
|
+
# @option _options [String] :name the name of the service (required)
|
179
|
+
# @raise [RegistryError] if try to unregister logger
|
180
|
+
# @raise [registryerror] if try to unregister a loaded service
|
181
|
+
# @return [TrueClass,FalseClass]
|
182
|
+
def unregister_service(_options = {})
|
183
|
+
options = Methodic.get_options(_options)
|
184
|
+
options.specify_class_of :name => String
|
185
|
+
options.specify_presence_of :name
|
186
|
+
options.validate!
|
187
|
+
raise RegistryError::new("FONDATION : Can't unregistered the logger service" ) if options[:name] == 'logger'
|
188
|
+
raise RegistryError::new("Can't unregistered a loaded service" ) if @loaded_services.include?(options[:name])
|
189
|
+
@list.delete(options[:name])
|
190
|
+
return true
|
123
191
|
end
|
124
|
-
@log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" }
|
125
|
-
self.stop_service :name => 'logger'
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
private
|
130
|
-
# private initializer
|
131
|
-
# @param [String] _filename default = '/data/config/service.registry' filename of the service Registry
|
132
|
-
# @return [Registry] Singleton
|
133
|
-
def initialize(_options)
|
134
|
-
@logger_not_in_reg = false
|
135
|
-
@debug = _options[:debug]
|
136
|
-
@registry_filename = _options[:file]
|
137
|
-
@list = Hash::new
|
138
|
-
load if File::exist?(@registry_filename)
|
139
|
-
unless @list.include?('logger') then
|
140
|
-
self.register_service({:name => 'logger',
|
141
|
-
:service => 'Carioca::Services::InternalLogger',
|
142
|
-
:resource => 'logger',
|
143
|
-
:description => "The standard ruby Logger internal wrapper Service",
|
144
|
-
:type => :builtin,
|
145
|
-
:init_options => { :target => "/tmp/log.file"}})
|
146
|
-
@logger_not_in_reg = true
|
147
|
-
end
|
148
|
-
|
149
|
-
@loaded_services = Hash::new
|
150
192
|
|
151
|
-
@
|
152
|
-
|
153
|
-
@
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
193
|
+
# overload @list (self.list) by adding/reloading the builtins services definition scanned from Carioca gem
|
194
|
+
# alterate @list
|
195
|
+
# @example usage
|
196
|
+
# registry = Carioca::Services::Registry.init :name => '/tmp/empty.file'
|
197
|
+
# registry.discover_builtins
|
198
|
+
# registry.save!
|
199
|
+
def discover_builtins
|
200
|
+
@list.merge! Carioca::Services::discover_builtins
|
201
|
+
end
|
202
|
+
|
203
|
+
# save the registry file in self.registry_filename
|
204
|
+
# @return [TruaClass,FalseClass] true if the file is saved
|
205
|
+
# @example usage
|
206
|
+
# registry = Carioca::Services::Registry.init :file => './empty.file'
|
207
|
+
# registry.discover_builtins
|
208
|
+
# registry.unregister_service :name => 'configuration'
|
209
|
+
# registry.save!
|
210
|
+
def save!
|
211
|
+
res = false
|
212
|
+
File.open(@registry_filename, "w") do |f|
|
213
|
+
res = true if f.write(@list.to_yaml)
|
171
214
|
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
215
|
+
return res
|
216
|
+
end
|
217
|
+
|
218
|
+
# start or get e previously started service in @list
|
219
|
+
# @return [Object] the loaded service class instance
|
220
|
+
# @param [Hash] _options the params, key are symbols
|
221
|
+
# @option _options [String] :name the name of the service
|
222
|
+
# @option _options [Hash] :params the params of the service
|
223
|
+
# @raise [RegistryError] Config Failed, for unconsistant service definition in @list
|
224
|
+
# @example usage
|
225
|
+
# registry = Carioca::Services::Registry.init
|
226
|
+
# config = registry.start_service :name => 'configuration'
|
227
|
+
# proxy = subject.start_service :name => 'debug' , :params => {:service => 'configuration'}
|
228
|
+
def start_service(_options)
|
229
|
+
options = Methodic.get_options(_options)
|
230
|
+
options.specify_classes_of :name => String
|
231
|
+
options.specify_presences_of([:name])
|
232
|
+
options.validate!
|
233
|
+
@log.debug('Carioca') { "getting service #{options[:name]}"} if @log
|
234
|
+
self.restart_service(options) unless @loaded_services.include? options[:name]
|
235
|
+
return @loaded_services[options[:name]]
|
236
|
+
end
|
237
|
+
alias :get_service :start_service
|
238
|
+
|
239
|
+
# start or restart (stop=>start) previously started service in @list
|
240
|
+
# @return [Object] the loaded service class instance
|
241
|
+
# @param [Hash] _options the params, key are symbols
|
242
|
+
# @option _options [String] :name the name of the service
|
243
|
+
# @option _options [Hash] :params the params of the service
|
244
|
+
# @raise [RegistryError] Config Failed, for unconsistant service definition in @list
|
245
|
+
# @example usage
|
246
|
+
# registry = Carioca::Services::Registry.init
|
247
|
+
# config = registry.restart_service :name => 'configuration'
|
248
|
+
# config = registry.restart_service :name => 'configuration' # stop and restart the previous services
|
249
|
+
# proxy = subject.restart_service :name => 'debug' , :params => {:service => 'configuration'}
|
250
|
+
# @note Registry and services are Singleton
|
251
|
+
def restart_service(_options)
|
252
|
+
options = Methodic.get_options(_options)
|
253
|
+
options.specify_classes_of :name => String
|
254
|
+
options.specify_presences_of [:name]
|
255
|
+
options.validate!
|
256
|
+
|
257
|
+
if @loaded_services.include? options[:name] then
|
258
|
+
@log.debug('Carioca') { "Restarting service #{options[:name]}"} if @log
|
259
|
+
kill_service :name => options[:name]
|
260
|
+
end
|
261
|
+
if options[:name] =~ /.*_.*/ then
|
262
|
+
(options[:shortname],options[:instance]) = options[:name].split(/_/)
|
185
263
|
else
|
186
|
-
|
264
|
+
options[:shortname] = options[:name]
|
187
265
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
raise RegistryError::new("Config failed")
|
266
|
+
verify_requires_dependancies(options)
|
267
|
+
require_service(options)
|
268
|
+
return instanciate_service(options)
|
192
269
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
270
|
+
|
271
|
+
# close the registry (finalizer)
|
272
|
+
# * stop all the services
|
273
|
+
# * kill logger
|
274
|
+
# * call private kill_service for each
|
275
|
+
# @note the garbage method hook is call if defined, for each service
|
276
|
+
# @return [TrueClass,FalseClass] true if registry closed successfully
|
277
|
+
def close
|
278
|
+
@log.debug('Carioca') { "closing Registry ..." }
|
279
|
+
@loaded_services.keys.each do |service|
|
280
|
+
next if service == 'logger'
|
281
|
+
@log.debug('Carioca') { "Stopping service #{service} ..."}
|
282
|
+
self.stop_service :name => service
|
283
|
+
end
|
284
|
+
@log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" }
|
285
|
+
kill_service 'logger'
|
286
|
+
return true
|
202
287
|
end
|
203
|
-
@log.debug('Carioca') { "Service #{options[:name]} started" } if @log
|
204
|
-
return @loaded_services[options[:name]]
|
205
|
-
end
|
206
|
-
|
207
|
-
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
end
|
214
288
|
|
289
|
+
# load the registry file from self.registry_filename
|
290
|
+
# @return [Hash] @list the list Structure of the loaded registry
|
291
|
+
# @example usage
|
292
|
+
# registry = Carioca::Services::Registry.init
|
293
|
+
# registry.registry_filename = "./an_other.file"
|
294
|
+
# registry.load #or
|
295
|
+
# registry.reload
|
296
|
+
def load
|
297
|
+
@list = YAML.load_file(@registry_filename)
|
298
|
+
end
|
299
|
+
alias :reload :load
|
300
|
+
|
301
|
+
end # end of Carioca::Services::Registry
|
302
|
+
end # end of Carioca:Services
|
303
|
+
end # end of Carioca
|
215
304
|
|
305
|
+
# Exception overload class for Carioca
|
216
306
|
class RegistryError < Exception; end
|
217
307
|
|
218
308
|
|