carioca 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5725ebfdae23b3175784bfc8f961a8ee5d31c455
4
+ data.tar.gz: 564985d9a48ab2e72017dca0b08d0c556ae0627b
5
+ SHA512:
6
+ metadata.gz: 7690724ad858c0f2a29f48bde4b7dd1674afdc9ed9a3cb0a5adfecb00b55e0338a33ddee6842829783140684f3e3bd2f014eabee48ab07c45f0468ce1d33207d
7
+ data.tar.gz: 6a3ab862d8c13fab2ddb0ac9fb7de1fd3ef4d6ce47e83750254e242dc36de6a68eaee9efe720840421744d39540f4c5b7f964b6895983c50b5dc14303bf43b6e
data/Gemfile CHANGED
@@ -1,11 +1,4 @@
1
1
  source "http://rubygems.org"
2
- gem "yard-rspec"
3
- gem "rspec", :require => "spec"
4
- gem "rake"
5
- gem "yard"
6
- gem "rdoc"
7
- gem "rcov"
8
- gem "roodi"
9
- gem "uuid"
10
- gem "methodic"
11
- gem "code_statistics"
2
+
3
+ gemspec
4
+
@@ -1,31 +1,29 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- code_statistics (0.2.13)
5
- diff-lcs (1.1.3)
6
- json (1.6.5)
7
- macaddr (1.0.0)
8
- methodic (0.2)
9
- rake (0.9.2.2)
10
- rcov (1.0.0)
11
- rdoc (3.12)
12
- json (~> 1.4)
4
+ diff-lcs (1.2.1)
5
+ macaddr (1.6.1)
6
+ systemu (~> 2.5.0)
7
+ methodic (1.2)
8
+ rake (10.0.4)
9
+ rdoc (4.0.0)
13
10
  roodi (2.2.0)
14
11
  ruby_parser (~> 2.3.0)
15
- rspec (2.9.0)
16
- rspec-core (~> 2.9.0)
17
- rspec-expectations (~> 2.9.0)
18
- rspec-mocks (~> 2.9.0)
19
- rspec-core (2.9.0)
20
- rspec-expectations (2.9.0)
21
- diff-lcs (~> 1.1.3)
22
- rspec-mocks (2.9.0)
12
+ rspec (2.13.0)
13
+ rspec-core (~> 2.13.0)
14
+ rspec-expectations (~> 2.13.0)
15
+ rspec-mocks (~> 2.13.0)
16
+ rspec-core (2.13.1)
17
+ rspec-expectations (2.13.0)
18
+ diff-lcs (>= 1.1.3, < 2.0)
19
+ rspec-mocks (2.13.0)
23
20
  ruby_parser (2.3.1)
24
21
  sexp_processor (~> 3.0)
25
22
  sexp_processor (3.2.0)
26
- uuid (2.3.1)
23
+ systemu (2.5.2)
24
+ uuid (2.3.7)
27
25
  macaddr (~> 1.0)
28
- yard (0.7.5)
26
+ yard (0.8.5.2)
29
27
  yard-rspec (0.1)
30
28
  yard
31
29
 
@@ -33,10 +31,8 @@ PLATFORMS
33
31
  ruby
34
32
 
35
33
  DEPENDENCIES
36
- code_statistics
37
34
  methodic
38
35
  rake
39
- rcov
40
36
  rdoc
41
37
  roodi
42
38
  rspec
data/README.md CHANGED
@@ -14,6 +14,9 @@ Carioca provide :
14
14
  - a complete Configuration Agent
15
15
  - A service Registry (base on IOC/DI pattern)
16
16
 
17
+ [![Build Status](https://travis-ci.org/lecid/carioca.png?branch=master)](https://travis-ci.org/lecid/carioca)
18
+
19
+
17
20
  ## Installation
18
21
 
19
22
  In a valid Ruby environment :
data/Rakefile CHANGED
@@ -5,7 +5,6 @@ require 'rake'
5
5
  require "rake/clean"
6
6
  require "rubygems/package_task"
7
7
  require "rdoc/task"
8
- require 'code_statistics'
9
8
  require 'rspec/core/rake_task'
10
9
  require 'yard'
11
10
  require 'yard/rake/yardoc_task.rb'
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{carioca}
3
3
  s.author = "Romain GEORGES"
4
- s.version = "1.0"
4
+ s.version = "1.1"
5
5
  s.date = %q{2013-02-18}
6
6
  s.summary = %q{Carioca : Configuration Agent and Registry with Inversion Of Control for your Applications}
7
7
  s.email = %q{romain@ultragreen.net}
@@ -9,8 +9,15 @@ Gem::Specification.new do |s|
9
9
  s.description = %q{Carioca : provide a full IoC light Container for designing your applications}
10
10
  s.has_rdoc = true
11
11
  s.files = Dir['*/*/*/*'] + Dir['*/*/*'] + Dir['*/*'] + Dir['*']
12
- s.bindir = nil
13
- s.add_dependency('methodic', '>= 1.2')
12
+ s.add_development_dependency('rspec')
13
+ s.add_development_dependency('yard')
14
+ s.add_development_dependency('rdoc')
15
+ s.add_development_dependency('roodi')
16
+ s.add_development_dependency('uuid')
17
+ s.add_development_dependency('code_statistics')
18
+ s.add_development_dependency('yard-rspec')
19
+ s.add_dependency('dorsal')
20
+ s.add_dependency('methodic')
14
21
  s.required_ruby_version = '>= 1.8.1'
15
22
  s.rdoc_options << '--title' << 'Carioca : Gem documentation' << '--main' << 'doc/manual.rdoc' << '--line-numbers'
16
23
  # << '--diagram'
@@ -1,4 +1,6 @@
1
+
1
2
  #!/usr/bin/env ruby
3
+ # -*- coding: utf-8 -*-
2
4
  #---
3
5
  # Author : Romain GEORGES
4
6
  # type : gem component library
@@ -8,9 +10,8 @@
8
10
  require 'yaml'
9
11
  require 'rubygems'
10
12
  require 'methodic'
11
- require 'services'
12
- require 'daemons'
13
- require 'carioca_private'
13
+ require 'carioca/services'
14
+ require 'carioca/private'
14
15
 
15
16
 
16
17
 
@@ -48,7 +49,10 @@ module Carioca
48
49
  private :require_service
49
50
  private :instanciate_service
50
51
  private :kill_service
51
-
52
+ private :scan_instance_suffix
53
+ private :kill_distributed_service
54
+ private :shutdown_ring_if_empty
55
+
52
56
 
53
57
  @@inst = nil
54
58
 
@@ -62,10 +66,9 @@ module Carioca
62
66
  # registry = Carioca::Services::Registry.init :file => 'myservices.registry' # or
63
67
  # registry = Carioca::Services::Registry.init :file => 'myservices.registry', :debug => true
64
68
  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
+ options = Methodic::get_options(_options)
70
+ options.specify_defaults_values :file => './services.registry', :debug => false, :name => 'Carioca'
71
+ options.merge
69
72
  @@inst = new(options) if @@inst.nil?
70
73
  return @@inst
71
74
  end
@@ -98,6 +101,14 @@ module Carioca
98
101
  # p registry.debug
99
102
  # @attr_reader [TrueClass,FalseClass] debug a boolean of the current debug status
100
103
  attr_reader :debug
104
+
105
+ # @example
106
+ # registry = Carioca::Services::Registry.init
107
+ # p registry.name
108
+ # registry.name = 'Agent'
109
+ # @attr_reader [String] the name of the Registry, used for distributed services
110
+ # @note default value is 'Carioca'
111
+ attr_accessor :name
101
112
 
102
113
  # writer accessor for debug (interaction with log service)
103
114
  # @example
@@ -129,22 +140,18 @@ module Carioca
129
140
  options.specify_class_of :name => String
130
141
  options.specify_presence_of([:name])
131
142
  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
143
+ @log.debug('Carioca') { "Service logger can't be unloaded" } if @log and options[:name] == 'logger'
144
+ return false if options[:name] == 'logger'
145
+ if @loaded_services.include?(options[:name]) then
146
+ options = scan_instance_suffix(options)
147
+ return kill_distributed_service options if @list[options[:shortname]][:distributed]
148
+ return kill_service options
142
149
  else
143
150
  @log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log
144
- return false
151
+ return false
145
152
  end
146
-
147
153
  end
154
+
148
155
 
149
156
  # register a new service in registry added to @list
150
157
  # @param [Hash] _options the options hash, key are :symbols
@@ -155,17 +162,14 @@ module Carioca
155
162
  # @option _options [String] :description the description of the service (required)
156
163
  # @option _options [Hash] :init_options the params of the service, keys are symbols
157
164
  # @option _options [Array] :requires the list of [String] services name required to load this service
165
+ # @option _options [TruClass|FalseClass] :distributed if service must be load as a distributed service
158
166
  # @return [TrueClass,FalseClass] true if service is added
159
167
  # @raise ArgumentError when :type is not in [:gem,:file,:builtin]
160
168
  def register_service(_options)
161
169
  options = Methodic.get_options(_options)
162
170
  options.specify_classes_of({:name => String, :resource => String, :description => String, :type => Symbol, :service => String })
163
171
  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 }
172
+ cond = Proc::new{|option| if [:gem,:gem_file,:file,:builtin].include? option then true else false end }
169
173
  options.specify_condition_for :type => cond
170
174
  options.validate!
171
175
  _name = _options.delete(:name)
@@ -253,16 +257,15 @@ module Carioca
253
257
  options.specify_classes_of :name => String
254
258
  options.specify_presences_of [:name]
255
259
  options.validate!
256
-
257
- if @loaded_services.include? options[:name] then
260
+ options = scan_instance_suffix(options)
261
+ dist = (@list[options[:shortname]][:distributed].nil?)? false : @list[options[:shortname]][:distributed]
262
+ if dist and @loaded_services.include? options[:name] then
263
+ @log.debug('Carioca') { "Restarting distributed service #{options[:name]}"} if @log
264
+ kill_distributed_service options
265
+ elsif @loaded_services.include? options[:name] then
258
266
  @log.debug('Carioca') { "Restarting service #{options[:name]}"} if @log
259
- kill_service :name => options[:name]
267
+ kill_service options
260
268
  end
261
- if options[:name] =~ /.*_.*/ then
262
- (options[:shortname],options[:instance]) = options[:name].split(/_/)
263
- else
264
- options[:shortname] = options[:name]
265
- end
266
269
  verify_requires_dependancies(options)
267
270
  require_service(options)
268
271
  return instanciate_service(options)
@@ -276,13 +279,16 @@ module Carioca
276
279
  # @return [TrueClass,FalseClass] true if registry closed successfully
277
280
  def close
278
281
  @log.debug('Carioca') { "closing Registry ..." }
282
+ options = Hash::new
279
283
  @loaded_services.keys.each do |service|
280
- next if service == 'logger'
281
- @log.debug('Carioca') { "Stopping service #{service} ..."}
282
- self.stop_service :name => service
284
+ options[:name] = service
285
+ options = scan_instance_suffix(options)
286
+ next if options[:name] == 'logger'
287
+ kill_distributed_service :name => options[:name], :preserve => true if @list[options[:shortname]][:distributed]
288
+ kill_service options unless @list[options[:shortname]][:distributed]
283
289
  end
284
290
  @log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" }
285
- kill_service 'logger'
291
+ kill_service :name => 'logger'
286
292
  return true
287
293
  end
288
294
 
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ #---
3
+ # Author : Romain GEORGES
4
+ # type : gem component library
5
+ # obj : Carioca Exceptions definition Module
6
+ #---
7
+
8
+ # Exception overload class for Carioca
9
+ class RegistryError < Exception; end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ #---
3
+ # Author : Romain GEORGES
4
+ # type : gem component library
5
+ # obj : Carioca Helpers definition Module
6
+ #---
7
+
8
+ class Class
9
+ # Usage:
10
+ # prelaod_service :name => 'service', :params => { :arg => 'value'}
11
+ def preload_service(_options = {})
12
+ Carioca::Services::Registry.init.start_service _options
13
+ end
14
+
15
+ def use_configuration(_options = {})
16
+ options = Methodic.get_options(_options)
17
+ options.specify_classes_of :with_file => String
18
+ options.specify_default_value_of :with_file => 'services/registry.yml'
19
+ options.merge
20
+ options.validate!
21
+ Carioca::Services::Registry.init.start_service :name => 'configuration', :params => { :config_file => options[:with_file]}
22
+ end
23
+ end
24
+
25
+
26
+ Module.class_eval do
27
+ def init_registry _options={}
28
+ options = Methodic.get_options(_options)
29
+ options.specify_classes_of :with_file => String
30
+ options.specify_default_value_of :with_file => 'services/registry.yml'
31
+ options.merge
32
+ options.validate!
33
+ Carioca::Services::Registry.init :file => options[:with_file]
34
+ end
35
+ end
@@ -0,0 +1,170 @@
1
+ #!/usr/bin/env ruby
2
+ #---
3
+ # Author : Romain GEORGES
4
+ # type : gem component library
5
+ # obj : Carioca Private Module (mixin for Carioca::Services::Registry)
6
+ #---
7
+
8
+ # private methods to mixin Carioca::Services::Registry
9
+ # @private
10
+ module PrivateMethodsCariocaServicesRegistry
11
+
12
+
13
+ # private initializer
14
+ def initialize(_options)
15
+ @logger_not_in_reg = false
16
+ @debug = _options[:debug]
17
+ @registry_filename = _options[:file]
18
+ @name = _options[:name]
19
+ @list = Hash::new
20
+ load if File::exist?(@registry_filename)
21
+ unless @list.include?('logger') then
22
+ self.register_service({:name => 'logger',
23
+ :service => 'Carioca::Services::InternalLogger',
24
+ :resource => 'logger',
25
+ :description => "The standard ruby Logger internal wrapper Service",
26
+ :type => :builtin,
27
+ :init_options => { :target => "/tmp/log.file"}})
28
+ @logger_not_in_reg = true
29
+ end
30
+ @loaded_services = Hash::new
31
+ # preload logger service
32
+ @log = self.start_service :name => 'logger'
33
+ @log.level =(@debug)? Logger::DEBUG : Logger::INFO
34
+ @log.debug('Carioca') { "Registry started, service logger preloaded" }
35
+ @log.debug('Carioca') { "Logger registered, not in configured registry" } if @logger_not_in_reg
36
+ end
37
+
38
+ # verify dependancies in services structure
39
+ # in @list from a service defition
40
+ # in _options and start it if needed
41
+ def verify_requires_dependancies(_options)
42
+ _name = _options[:shortname]
43
+ if @list[_name].include?(:requires) then
44
+ @list[_name][:requires].each do |service|
45
+ raise RegistryError::new 'Missing Required depedancy #{service}' unless @list.keys.include? service
46
+ unless @loaded_services.include?(service) then
47
+ @log.debug('Carioca') { "Registry dependancy found and not loaded : #{service}" }
48
+ restart_service :name => service
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ # require file for a service
55
+ # from a service definition in _options
56
+ def require_service(_options)
57
+ _name = _options[:shortname]
58
+ sym = ":#{@list[_name][:service].split('::').last}"
59
+ case @list[_name][:type]
60
+ when :file then
61
+ require @list[_name][:resource]
62
+ when :builtin then
63
+ _file = Carioca::Services::search_builtins _name
64
+ if _file then
65
+ require _file
66
+ else
67
+ raise RegistryError::new("Config failed")
68
+ end
69
+ when :gem then
70
+ require @list[_name][:resource]
71
+ when :gem_file then
72
+ (_name,_file) = @list[_name][:resource].split(':')
73
+ _dfile = Carioca::Services::search_file_in_gem _name,_file
74
+ if _dfile then
75
+ require _dfile
76
+ else
77
+ raise RegistryError::new("Config failed")
78
+ end
79
+ else
80
+ raise RegistryError::new("Config failed")
81
+ end
82
+ end
83
+
84
+
85
+ # scan for <service>_<instance> and rewrite options with :name and :shortname, :instance
86
+ def scan_instance_suffix(options)
87
+ if options[:name] =~ /.*_.*/ then
88
+ (options[:shortname],options[:instance]) = options[:name].split(/_/)
89
+ else
90
+ options[:shortname] = options[:name]
91
+ end
92
+ return options
93
+ end
94
+
95
+ #shutdown ring server if empty
96
+ def shutdown_ring_if_empty
97
+ get_ring if @ring_server.nil?
98
+ if @ring_server.list_services.empty? then
99
+ @log.debug('Carioca') { "Stopping Ultragreen Ring server if no distributed services found" }
100
+ @dorsal_controller.stop_ring_server
101
+ end
102
+ end
103
+
104
+ # run a ring servier instance or get existing
105
+ def get_ring
106
+ @dorsal_controller = start_service :name => 'dorsal'
107
+ @ring_server = @dorsal_controller.bind_to_ring
108
+ if @ring_server.nil? then
109
+ @dorsal_controller.start_ring_server
110
+ @ring_server = @dorsal_controller.bind_to_ring
111
+ @log.debug('Carioca') { "Starting new Ring Server" } if @log
112
+ else
113
+ @log.debug('Carioca') { "Getting already started Ring Server" } if @log
114
+ end
115
+ end
116
+
117
+ # instanciate Object from class defintion of a service defined in
118
+ # the service definition in _opts
119
+ def instanciate_service(_opts)
120
+ _name = _opts[:shortname]
121
+ dist = (@list[_name][:distributed].nil?)? false : @list[_name][:distributed]
122
+ get_ring if dist
123
+ @list[_name][:init_options].merge! _opts[:params] unless _opts[:params].nil?
124
+ @obj = Object::new
125
+ if @list[_name][:init_options].nil? then
126
+ eval("@obj = #{@list[_name][:service]}::new")
127
+ else
128
+ eval("@obj = #{@list[_name][:service]}::new(@list[_name][:init_options])")
129
+ end
130
+ if dist then
131
+ @ring_server.start_service({ :name => _opts[:name], :object => @obj, :description => @list[_name][:description], :owner => @name })
132
+ @loaded_services[_opts[:name]] = @ring_server.bind_to_service :name => _opts[:name]
133
+ else
134
+ @loaded_services[_opts[:name]] = @obj
135
+ end
136
+ return @loaded_services[_opts[:name]]
137
+ end
138
+
139
+ # call the garbage method of a service if exist and
140
+ # Delete from the loaded services list
141
+ def kill_service(options)
142
+ @log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log
143
+ @loaded_services[options[:name]].garbage if @loaded_services[options[:name]].respond_to? :garbage
144
+ @loaded_services.delete(options[:name])
145
+ return true
146
+ end
147
+
148
+ def kill_distributed_service(options)
149
+ preserve = (options[:preserve].nil?)? false : options[:preserve]
150
+ get_ring if @ring_server.nil?
151
+ if @ring_server.list_services.include?(options[:name]) then
152
+ if options[:preserve] and @ring_server.list_services[options[:name]][:owner] != @name then
153
+ @log.debug('Carioca') { "Unlinking distributed Service #{options[:name]} owned by #{@name}." } if @log
154
+ else
155
+ @ring_server.destroy_service :name => options[:name]
156
+ @log.debug('Carioca') { "Killing distributed Service #{options[:name]}." } if @log
157
+ end
158
+ @loaded_services.delete(options[:name])
159
+ shutdown_ring_if_empty
160
+ return true
161
+ else
162
+ @log.debug('Carioca') { "Distributed service #{options[:name]} not in ring" } if @log
163
+ return false
164
+ end
165
+ end
166
+
167
+
168
+ end # end of PrivateMethodsCariocaServicesRegistry
169
+
170
+