tengine_core 0.5.28

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.
Files changed (156) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +40 -0
  4. data/Gemfile.lock +95 -0
  5. data/README.md +54 -0
  6. data/Rakefile +44 -0
  7. data/VERSION +1 -0
  8. data/bin/tengine_atd +8 -0
  9. data/bin/tengine_heartbeat_watchd +8 -0
  10. data/bin/tengined +182 -0
  11. data/examples/VERSION +1 -0
  12. data/examples/uc01_execute_processing_for_event.rb +11 -0
  13. data/examples/uc02_fire_another_event.rb +16 -0
  14. data/examples/uc03_2handlers_for_1event.rb +16 -0
  15. data/examples/uc08_if_both_a_and_b_occurs.rb +11 -0
  16. data/examples/uc10_if_the_event_occurs_at_the_server.rb +15 -0
  17. data/examples/uc50_commit_event_at_first.rb +17 -0
  18. data/examples/uc51_commit_event_at_first_submit.rb +29 -0
  19. data/examples/uc52_commit_event_after_all_handler_submit.rb +31 -0
  20. data/examples/uc52_never_commit_event_unless_all_handler_submit.rb +31 -0
  21. data/examples/uc60_event_in_handler.rb +18 -0
  22. data/examples/uc62_session_in_driver.rb +16 -0
  23. data/examples/uc64_safety_countup.rb +14 -0
  24. data/examples/uc70_driver_enabled_on_activation.rb +13 -0
  25. data/examples/uc71_driver_disabled_on_activation.rb +14 -0
  26. data/examples/uc72_setup_eventmachine.rb +17 -0
  27. data/examples/uc80_raise_io_error.rb +10 -0
  28. data/examples/uc81_raise_runtime_error.rb +10 -0
  29. data/examples2/driver01.rb +18 -0
  30. data/examples2/driver02.rb +19 -0
  31. data/examples2/uc08_if_both_a_and_b_occurs.rb +13 -0
  32. data/examples2/uc10_if_the_event_occurs_at_the_server.rb +18 -0
  33. data/examples2/uc51_commit_event_at_first_submit_1.rb +16 -0
  34. data/examples2/uc51_commit_event_at_first_submit_2.rb +17 -0
  35. data/examples2/uc51_commit_event_at_first_submit_3.rb +17 -0
  36. data/examples2/uc62_session_in_driver.rb +16 -0
  37. data/examples2/uc71_driver_disabled_on_activation.rb +16 -0
  38. data/failure_examples/VERSION +1 -0
  39. data/failure_examples/uc53_submit_outside_of_handler.rb +15 -0
  40. data/failure_examples/uc61_event_outside_of_handler.rb +12 -0
  41. data/failure_examples/uc63_session_outside_of_driver.rb +13 -0
  42. data/lib/tengine/core.rb +74 -0
  43. data/lib/tengine/core/bootstrap.rb +123 -0
  44. data/lib/tengine/core/collection_accessible.rb +34 -0
  45. data/lib/tengine/core/config.rb +10 -0
  46. data/lib/tengine/core/config/atd.rb +225 -0
  47. data/lib/tengine/core/config/core.rb +319 -0
  48. data/lib/tengine/core/config/heartbeat_watcher.rb +229 -0
  49. data/lib/tengine/core/connection_test/.gitignore +1 -0
  50. data/lib/tengine/core/connection_test/fire_bar_on_foo.rb +16 -0
  51. data/lib/tengine/core/driveable.rb +213 -0
  52. data/lib/tengine/core/driver.rb +69 -0
  53. data/lib/tengine/core/driver/finder.rb +42 -0
  54. data/lib/tengine/core/dsl_evaluator.rb +110 -0
  55. data/lib/tengine/core/dsl_filter_def.rb +11 -0
  56. data/lib/tengine/core/dsl_loader.rb +108 -0
  57. data/lib/tengine/core/event.rb +145 -0
  58. data/lib/tengine/core/event/finder.rb +82 -0
  59. data/lib/tengine/core/event_exception_reportable.rb +88 -0
  60. data/lib/tengine/core/event_wrapper.rb +21 -0
  61. data/lib/tengine/core/find_by_name.rb +31 -0
  62. data/lib/tengine/core/handler.rb +152 -0
  63. data/lib/tengine/core/handler_path.rb +33 -0
  64. data/lib/tengine/core/heartbeat_watcher.rb +161 -0
  65. data/lib/tengine/core/io_to_logger.rb +22 -0
  66. data/lib/tengine/core/kernel.rb +510 -0
  67. data/lib/tengine/core/kernel_runtime.rb +91 -0
  68. data/lib/tengine/core/method_traceable.rb +38 -0
  69. data/lib/tengine/core/mongoid_fix.rb +19 -0
  70. data/lib/tengine/core/mutex.rb +177 -0
  71. data/lib/tengine/core/optimistic_lock.rb +69 -0
  72. data/lib/tengine/core/plugins.rb +54 -0
  73. data/lib/tengine/core/schedule.rb +21 -0
  74. data/lib/tengine/core/scheduler.rb +156 -0
  75. data/lib/tengine/core/selectable_attr.rb +29 -0
  76. data/lib/tengine/core/session.rb +21 -0
  77. data/lib/tengine/core/session_wrapper.rb +68 -0
  78. data/lib/tengine/core/setting.rb +21 -0
  79. data/lib/tengine/core/validation.rb +36 -0
  80. data/lib/tengine/errors.rb +18 -0
  81. data/lib/tengine/rspec.rb +8 -0
  82. data/lib/tengine/rspec/context_wrapper.rb +51 -0
  83. data/lib/tengine/rspec/extension.rb +53 -0
  84. data/lib/tengine_core.rb +23 -0
  85. data/spec/factories/tengine_core_drivers.rb +10 -0
  86. data/spec/factories/tengine_core_events.rb +14 -0
  87. data/spec/factories/tengine_core_handler_paths.rb +9 -0
  88. data/spec/factories/tengine_core_handlers.rb +9 -0
  89. data/spec/factories/tengine_core_sessions.rb +9 -0
  90. data/spec/mongoid.yml +35 -0
  91. data/spec/spec_helper.rb +48 -0
  92. data/spec/support/mongo_index_key_log.rb +91 -0
  93. data/spec/tengine/core/bootstrap_spec.rb +278 -0
  94. data/spec/tengine/core/bugfix/bind_dsl_file_in_multi_byte_dir_spec.rb +21 -0
  95. data/spec/tengine/core/bugfix/enabled_on_activation_spec.rb +112 -0
  96. data/spec/tengine/core/bugfix/receive_event_spec.rb +133 -0
  97. data/spec/tengine/core/bugfix/use_dsl_version_method.rb +12 -0
  98. data/spec/tengine/core/bugfix/use_dsl_version_method_spec.rb +28 -0
  99. data/spec/tengine/core/bugfix/use_event_in_handler_dsl.rb +11 -0
  100. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/206/343/202/231/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215/source_location_encoding.rb +35 -0
  101. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/206/343/202/231/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215//351/235/236ASCII/343/201/256/343/203/225/343/202/241/343/202/244/343/203/253/345/220/215_dsl.rb +38 -0
  102. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/207/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215/source_location_encoding.rb +35 -0
  103. data/spec/tengine/core/bugfix//351/235/236ACSII/343/201/256/343/203/207/343/202/243/343/203/254/343/202/257/343/203/210/343/203/252/345/220/215//351/235/236ASCII/343/201/256/343/203/225/343/202/241/343/202/244/343/203/253/345/220/215_dsl.rb +38 -0
  104. data/spec/tengine/core/config/atd_spec.rb +62 -0
  105. data/spec/tengine/core/config/core_spec.rb +479 -0
  106. data/spec/tengine/core/config/heartbeat_watcher_spec.rb +62 -0
  107. data/spec/tengine/core/config/syntax_error_in_erb.yml.erb +13 -0
  108. data/spec/tengine/core/config/wrong_category_name.yml.erb +13 -0
  109. data/spec/tengine/core/config/wrong_field_name.yml.erb +12 -0
  110. data/spec/tengine/core/config/wrong_yaml.yml.erb +13 -0
  111. data/spec/tengine/core/config_spec/another_port.yml +54 -0
  112. data/spec/tengine/core/config_spec/config_with_dir_absolute_load_path.yml +16 -0
  113. data/spec/tengine/core/config_spec/config_with_dir_relative_load_path.yml +16 -0
  114. data/spec/tengine/core/config_spec/config_with_file_absolute_load_path.yml +16 -0
  115. data/spec/tengine/core/config_spec/config_with_file_relative_load_path.yml +16 -0
  116. data/spec/tengine/core/config_spec/log_config_spec.rb +235 -0
  117. data/spec/tengine/core/driveable_spec.rb +240 -0
  118. data/spec/tengine/core/driver_spec.rb +159 -0
  119. data/spec/tengine/core/dsl_loader_spec.rb +172 -0
  120. data/spec/tengine/core/dsls/uc08_if_both_a_and_b_occurs_spec.rb +35 -0
  121. data/spec/tengine/core/dsls/uc10_if_the_event_occurs_at_the_server_spec.rb +58 -0
  122. data/spec/tengine/core/dsls/uc50_commit_event_at_first_spec.rb +29 -0
  123. data/spec/tengine/core/dsls/uc52_commit_event_after_all_handler_submit_spec.rb +33 -0
  124. data/spec/tengine/core/dsls/uc52_never_commit_event_unless_all_handler_submit_spec.rb +37 -0
  125. data/spec/tengine/core/dsls/uc53_submit_outside_of_handler_spec.rb +37 -0
  126. data/spec/tengine/core/dsls/uc60_event_in_handler_spec.rb +31 -0
  127. data/spec/tengine/core/dsls/uc61_event_outside_of_handler_spec.rb +37 -0
  128. data/spec/tengine/core/dsls/uc62_session_in_driver_spec.rb +36 -0
  129. data/spec/tengine/core/dsls/uc63_session_outside_of_driver_spec.rb +35 -0
  130. data/spec/tengine/core/dsls/uc64_safety_countup_spec.rb +134 -0
  131. data/spec/tengine/core/dsls/uc70_driver_enabled_on_activation_spec.rb +39 -0
  132. data/spec/tengine/core/dsls/uc71_driver_disabled_on_activation_spec.rb +36 -0
  133. data/spec/tengine/core/dsls/uc72_setup_eventmachine_spec.rb +39 -0
  134. data/spec/tengine/core/dsls/uc80_raise_io_error_spec.rb +53 -0
  135. data/spec/tengine/core/dsls/uc81_raise_runtime_error_spec.rb +49 -0
  136. data/spec/tengine/core/event/finder_spec.rb +136 -0
  137. data/spec/tengine/core/event_exception_reportable_spec.rb +33 -0
  138. data/spec/tengine/core/event_spec.rb +161 -0
  139. data/spec/tengine/core/event_wrapper_spec.rb +35 -0
  140. data/spec/tengine/core/handler_path_spec.rb +87 -0
  141. data/spec/tengine/core/handler_spec.rb +190 -0
  142. data/spec/tengine/core/heartbeat_watcher_spec.rb +131 -0
  143. data/spec/tengine/core/io_to_logger_spec.rb +30 -0
  144. data/spec/tengine/core/kernel_spec.rb +885 -0
  145. data/spec/tengine/core/mutex_spec.rb +184 -0
  146. data/spec/tengine/core/optimistic_lock_spec.rb +55 -0
  147. data/spec/tengine/core/scheculer_spec.rb +121 -0
  148. data/spec/tengine/core/selectable_attr_spec.rb +30 -0
  149. data/spec/tengine/core/session_spec.rb +104 -0
  150. data/spec/tengine/core/setting_spec.rb +79 -0
  151. data/spec/tengine/core_spec.rb +13 -0
  152. data/spec/tengine_spec.rb +14 -0
  153. data/tengine_core.gemspec +248 -0
  154. data/tmp/log/.gitignore +1 -0
  155. data/tmp/tengined_status/.gitignore +1 -0
  156. metadata +421 -0
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ class Uc62SessionInDriver
5
+ include Tengine::Core::Driveable
6
+
7
+ session.update(:foo => 100) # ドライバ登録時にそのセッションに キー:foo に対して 値100 を設定する。
8
+
9
+ on:event62
10
+ def event62
11
+ value = session[:foo]
12
+ value +=1
13
+ session.update(:foo => value)
14
+ puts value
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ class Uc71DriverDisabledOnActivation
5
+ include Tengine::Core::Driveable
6
+ include Tengine::Core::Driveable::ByDsl
7
+
8
+ self.singleton_class.options = { :enabled_on_activation => false }
9
+
10
+ # イベントに対応する処理の実行する
11
+ on:event71
12
+ def event71
13
+ puts "handler71"
14
+ end
15
+
16
+ end
@@ -0,0 +1 @@
1
+ 20110902213500
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ # submitメソッドは、ハンドラ内でのみ使用できるので、ハンドラ外で使用した場合例外がraiseされる。
5
+ # loadでもbindでも途中で失敗し、Tengineコアのプロセスは終了する
6
+ ack_policy(:at_first, :event53)
7
+
8
+ driver :driver53 do
9
+ submit # SyntaxErrorなどではなく、Tengine::Core::DslErrorがraiseされる
10
+
11
+ on:event53 do
12
+ puts "handler53"
13
+ end
14
+
15
+ end
@@ -0,0 +1,12 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ # eventメソッドはハンドラ内でのみ使用できるものなのでその外で使用したら例外がraiseされる。
5
+ # loadでもbindでも途中で失敗し、Tengineコアのプロセスは終了する
6
+
7
+ driver :driver61 do
8
+ event # SyntaxErrorではなく、Tengine::Core::DslErrorがraiseされる
9
+
10
+ on:event61 do
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ # sessionメソッドは、ドライバ内でのみ使用できるので、ドライバ外で使用した場合例外がraiseされる。
5
+ # loadでもbindでも途中で失敗し、Tengineコアのプロセスは終了する
6
+
7
+ session # SyntaxErrorなどではなく、Tengine::Core::DslErrorがraiseされる
8
+
9
+ driver :driver63 do
10
+
11
+ on:event63 do
12
+ end
13
+ end
@@ -0,0 +1,74 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine_core'
3
+ require 'logger'
4
+
5
+ module Tengine::Core
6
+ # base
7
+ autoload :Bootstrap , 'tengine/core/bootstrap'
8
+ autoload :Config , 'tengine/core/config'
9
+ autoload :Kernel , 'tengine/core/kernel'
10
+ autoload :Driveable , 'tengine/core/driveable'
11
+ autoload :KernelRuntime , 'tengine/core/kernel_runtime'
12
+ autoload :DslEvaluator , 'tengine/core/dsl_evaluator'
13
+ autoload :DslLoader , 'tengine/core/dsl_loader'
14
+ autoload :DslFilterDef , 'tengine/core/dsl_filter_def'
15
+ autoload :Plugins , 'tengine/core/plugins'
16
+
17
+ # models
18
+ autoload :Event , 'tengine/core/event'
19
+ autoload :Driver , 'tengine/core/driver'
20
+ autoload :Session , 'tengine/core/session'
21
+ autoload :Handler , 'tengine/core/handler'
22
+ autoload :HandlerPath, 'tengine/core/handler_path'
23
+ autoload :Setting , 'tengine/core/setting'
24
+ autoload :Schedule , 'tengine/core/schedule'
25
+
26
+ # model wrappers
27
+ autoload :EventWrapper , 'tengine/core/event_wrapper'
28
+ autoload :SessionWrapper, 'tengine/core/session_wrapper'
29
+
30
+ # utilities
31
+ autoload :CollectionAccessible, 'tengine/core/collection_accessible'
32
+ autoload :IoToLogger , 'tengine/core/io_to_logger'
33
+ autoload :SelectableAttr , 'tengine/core/selectable_attr'
34
+ autoload :MethodTraceable , 'tengine/core/method_traceable'
35
+ autoload :OptimisticLock , 'tengine/core/optimistic_lock'
36
+ autoload :Validation , 'tengine/core/validation'
37
+ autoload :EventExceptionReportable, 'tengine/core/event_exception_reportable'
38
+ autoload :FindByName , 'tengine/core/find_by_name'
39
+ autoload :Mutex , 'tengine/core/mutex'
40
+
41
+ class << self
42
+ # Tengine::Coreの正常時の動きをアプリケーション運用者が確認できる内容を出力するロガー
43
+ # ログレベルがinfoでも出力する内容は少ない
44
+ def stdout_logger
45
+ @stdout_logger ||= Logger.new(STDOUT)
46
+ end
47
+ attr_writer :stdout_logger
48
+
49
+ # Tengine::Coreの異常発生時の動きをアプリケーション運用者が確認できる内容を出力するロガー
50
+ def stderr_logger
51
+ @stderr_logger ||= Logger.new(STDERR)
52
+ end
53
+ attr_writer :stderr_logger
54
+
55
+ # リリースされたtengine_coreパッケージのバージョンを返します
56
+ def version
57
+ File.read(File.expand_path("../../VERSION", File.dirname(__FILE__))).strip
58
+ end
59
+ end
60
+
61
+ # 設定に問題があることを示す例外
62
+ class ConfigError < StandardError
63
+ end
64
+
65
+ # DSLの記述に問題があることを示す例外
66
+ class DslError < ::Tengine::DslError
67
+ end
68
+
69
+ # カーネルの動作で問題が発生した場合にraiseする例外
70
+ class KernelError < StandardError
71
+ end
72
+
73
+
74
+ end
@@ -0,0 +1,123 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ require 'tengine/event'
5
+ require 'tengine/mq'
6
+ require 'eventmachine'
7
+
8
+ class Tengine::Core::Bootstrap
9
+
10
+ attr_accessor :config
11
+ attr_writer :kernel
12
+
13
+ def initialize(hash)
14
+ @config = Tengine::Core::Config::Core[hash]
15
+ prepare_trap
16
+ end
17
+
18
+ def prepare_trap; Signal.trap(:HUP) { kernel.stop } end
19
+
20
+ DEBUG_CONFIG_ATTRS = [:dsl_dir_path, :dsl_file_paths, :dsl_version_path, :dsl_version].freeze
21
+
22
+ def boot
23
+ Tengine::Core.stdout_logger.debug(DEBUG_CONFIG_ATTRS.map{|attr| "#{attr}: " << config.send(attr).inspect}.join(", "))
24
+ case config[:action]
25
+ when "load" then load_dsl
26
+ when "start" then
27
+ load_dsl # unless config[:tengined][:skip_load]
28
+ start_kernel do
29
+ # ここでイベントを待つ
30
+ end
31
+ when "test" then test_connection
32
+ when "enable" then enable_drivers
33
+ else
34
+ raise ArgumentError, "config[:action] in boot method must be test|load|start|enable but was #{config[:action]} "
35
+ end
36
+ end
37
+
38
+ def load_dsl
39
+ if dsl_version_document = Tengine::Core::Setting.first(:conditions => {:name => "dsl_version"})
40
+ dsl_version_document.value = config.dsl_version
41
+ dsl_version_document.save!
42
+ else
43
+ Tengine::Core::Setting.create!(:name => "dsl_version", :value => config.dsl_version)
44
+ end
45
+ Tengine.plugins.notify(self, :load_dsl) do
46
+ context = kernel.dsl_context
47
+ context.__evaluate__
48
+ end
49
+ end
50
+
51
+ def kernel
52
+ @kernel ||= Tengine::Core::Kernel.new(config)
53
+ end
54
+
55
+ def start_kernel(&block)
56
+ Tengine.plugins.notify(self, :start_kernel) do
57
+ kernel.start(&block)
58
+ end
59
+ end
60
+
61
+ def stop_kernel
62
+ Tengine.plugins.notify(self, :stop_kernel) do
63
+ kernel.stop
64
+ end
65
+ end
66
+
67
+ def enable_drivers
68
+ drivers = Tengine::Core::Driver.where(:version => config.dsl_version, :enabled_on_activation => true)
69
+ drivers.each{ |d| d.update_attribute(:enabled, true) }
70
+ end
71
+
72
+ def test_connection
73
+ config[:tengined][:load_path] = File.expand_path("connection_test/fire_bar_on_foo.rb", File.dirname(__FILE__))
74
+ config.prepare_dir_and_paths(true)
75
+
76
+ begin
77
+ load_dsl
78
+ start_kernel do |mq| # このブロックは Tengine::Core::Kernel#activateのEM.runに渡されたブロックから呼び出されます。
79
+ teardown = lambda do |result|
80
+ EM.next_tick do
81
+ Tengine::Core.stdout_logger.info(result)
82
+ stop_kernel
83
+ end
84
+ end
85
+ # http://keijinsonyaban.blogspot.com/2010/12/eventmachine.html のEM.defer(op, callback)を参照
86
+ EM.defer(lambda{start_connection_test(mq)}, teardown)
87
+ end
88
+ Tengine::Core::stdout_logger.info("Connection test success.")
89
+ rescue Exception => e
90
+ Tengine::Core::stderr_logger.error("Connection test failure: [#{e.class.name}] #{e.message}")
91
+ end
92
+ end
93
+
94
+ def start_connection_test(mq)
95
+ require 'timeout'
96
+ timeout(10) do
97
+ connection_test_completed = false
98
+ Tengine.callback_for_test = lambda do |event_type_name|
99
+ case event_type_name
100
+ when :foo then
101
+ Tengine::Core.stdout_logger.info("handing :foo successfully.")
102
+ when :bar then
103
+ Tengine::Core.stdout_logger.info("handing :bar successfully.")
104
+ connection_test_completed = true
105
+ else
106
+ Tengine::Core.stderr_logger.error("Unexpected event: #{event_type_name}")
107
+ end
108
+ end
109
+ Tengine::Event.instance_variable_set(:@mq_suite, mq)
110
+ Tengine::Event.fire(:foo, :level_key => :info, :keep_connection => true)
111
+ loop do
112
+ sleep(0.1)
113
+ return if connection_test_completed
114
+ end
115
+ end
116
+ end
117
+
118
+ # 自動でログ出力する
119
+ extend Tengine::Core::MethodTraceable
120
+ method_trace(:prepare_trap, :boot, :load_dsl, :start_kernel, :stop_kernel,
121
+ :enable_drivers, :test_connection, :start_connection_test)
122
+
123
+ end
@@ -0,0 +1,34 @@
1
+ require 'tengine/core'
2
+
3
+ module Tengine::Core::CollectionAccessible
4
+
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def array_text_accessor(attr_name, options = {})
9
+ options = {:delimeter => ","}.update(options || {})
10
+ delimeter = options[:delimeter]
11
+ self.module_eval(<<-"EOS", __FILE__, __LINE__ + 1)
12
+ def #{attr_name}_text
13
+ #{attr_name} ? #{attr_name}.join(#{delimeter.inspect}) : ""
14
+ end
15
+ def #{attr_name}_text=(value)
16
+ self.#{attr_name} = value.nil? ? [] :
17
+ value.split(#{delimeter.inspect}).map(&:strip)
18
+ end
19
+ EOS
20
+ end
21
+
22
+ def map_yaml_accessor(attr_name)
23
+ self.module_eval(<<-"EOS", __FILE__, __LINE__ + 1)
24
+ def #{attr_name}_yaml
25
+ YAML.dump({}.update(#{attr_name} || {}))
26
+ end
27
+ def #{attr_name}_yaml=(value)
28
+ self.#{attr_name} = value.blank? ? nil : YAML.load(value)
29
+ end
30
+ EOS
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core'
3
+
4
+ # require 'tengine/core/config/default' # DEFAULT定数と関係するメソッドを定義
5
+
6
+ module Tengine::Core::Config
7
+ autoload :Core, 'tengine/core/config/core'
8
+ autoload :Atd, 'tengine/core/config/atd'
9
+ autoload :HeartbeatWatcher, 'tengine/core/config/heartbeat_watcher'
10
+ end
@@ -0,0 +1,225 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'tengine/core/config'
3
+
4
+ require 'yaml'
5
+ require 'optparse'
6
+ require 'active_support/memoizable'
7
+
8
+ require 'tengine/support/yaml_with_erb'
9
+
10
+ Tengine::Support::Config::Definition::Group.module_eval do
11
+ def symbolize_keys
12
+ to_hash
13
+ end
14
+ end
15
+
16
+ class Tengine::Core::Config::Atd < Tengine::Support::Config::Definition::Suite
17
+ # memoize については http://wota.jp/ac/?date=20081025#p11 などを参照してください
18
+ extend ActiveSupport::Memoizable
19
+
20
+ class << self
21
+ # この辺は以前のTengine::Core::Configとの互換のために用意してあります
22
+ def [](hash_or_suite)
23
+ case hash_or_suite
24
+ when Tengine::Core::Config::Atd then hash_or_suite
25
+ when Hash then
26
+ result = Tengine::Core::Config::Atd.new
27
+ result.load(hash_or_suite)
28
+ result
29
+ else
30
+ raise "unsupported class: #{hash_or_suite.class.inspect}"
31
+ end
32
+ end
33
+
34
+ def default_hash
35
+ new.to_hash
36
+ end
37
+ alias_method :skelton_hash, :default_hash
38
+
39
+ def parse_to_hash(args)
40
+ config = new
41
+ config.parse!(args)
42
+ result = new
43
+ result.config = config.config
44
+ result.to_hash
45
+ end
46
+
47
+ def parse(args)
48
+ config = new
49
+ config.parse!(args)
50
+ config
51
+ end
52
+
53
+ end
54
+
55
+ def initialize(hash_or_filepath = nil)
56
+ build if respond_to?(:build)
57
+ case hash_or_filepath
58
+ when Hash then
59
+ if config = hash_or_filepath[:config]
60
+ load_file(config)
61
+ else
62
+ load(hash_or_filepath)
63
+ end
64
+ when String then load_file(hash_or_filepath)
65
+ end
66
+ end
67
+
68
+ def load_file(filepath)
69
+ super
70
+ rescue Exception => e
71
+ msg = e.message
72
+ unless msg.include?(filepath)
73
+ msg = "#{msg} in #{filepath}"
74
+ end
75
+ raise Tengine::Core::ConfigError, msg
76
+ end
77
+
78
+
79
+ def build
80
+ banner <<EOS
81
+ Usage: tengine_atd [-k action] [-f path_to_config] [-D process_daemon]
82
+ [-o mq_conn_host] [-p mq_conn_port] [-u mq_conn_user]
83
+ [-s mq_conn_pass] [-e mq_exchange_name] [-q mq_queue_name]
84
+ [-G heartbeat_atd_interval]
85
+ EOS
86
+
87
+ field(:action, "start|stop", :type => :string, :default => "start")
88
+ load_config(:config, "path/to/config_file", :type => :string)
89
+
90
+ add(:process, Tengine::Core::Config::Atd::Process)
91
+ field(:db, "settings to connect to db", :type => :hash, :default => {
92
+ 'host' => 'localhost',
93
+ 'port' => 27017,
94
+ 'username' => nil,
95
+ 'password' => nil,
96
+ 'database' => 'tengine_production',
97
+ })
98
+
99
+ group(:heartbeat) do
100
+ add(:atd , Tengine::Core::Config::Core::Heartbeat)
101
+ end
102
+
103
+ group(:event_queue, :hidden => true) do
104
+ add(:connection, AmqpConnection)
105
+ add(:exchange , Tengine::Support::Config::Amqp::Exchange, :defaults => {:name => 'tengine_event_exchange'})
106
+ add(:queue , Tengine::Support::Config::Amqp::Queue , :defaults => {:name => 'tengine_event_queue'})
107
+ end
108
+
109
+ add(:log_common, Tengine::Support::Config::Logger,
110
+ :defaults => {
111
+ :rotation => 3 ,
112
+ :rotation_size => 1024 * 1024,
113
+ :level => 'info' ,
114
+ })
115
+ add(:application_log, Tengine::Core::Config::Atd::LoggerConfig,
116
+ :parameters => {:logger_name => "application"},
117
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
118
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} #{level} #{@process_identifier} #{msg}\n"}
119
+ }
120
+ add(:process_stdout_log, Tengine::Core::Config::Atd::LoggerConfig,
121
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stdout"},
122
+ :dependencies => { :process_config => :process, :log_common => :log_common,}){
123
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDOUT #{@process_identifier} #{msg}\n"}
124
+ }
125
+ add(:process_stderr_log, Tengine::Core::Config::Atd::LoggerConfig,
126
+ :parameters => {:logger_name => "#{File.basename($PROGRAM_NAME)}_#{::Process.pid}_stderr"},
127
+ :dependencies => { :process_config => :process, :log_common => :log_common,},
128
+ :defaults => {
129
+ :output => proc{ process_config.daemon ? "./log/#{logger_name}.log" : "STDERR" }}){
130
+ self.formatter = lambda{|level, t, prog, msg| "#{t.iso8601} STDERR #{@process_identifier} #{msg}\n"}
131
+ }
132
+
133
+ separator("\nGeneral:")
134
+ field(:verbose, "Show detail to this command", :type => :boolean)
135
+ __action__(:version, "show version"){ STDOUT.puts Tengine::Core.version.to_s; exit }
136
+ __action__(:dump_skelton, "dump skelton of config"){ STDOUT.puts YAML.dump(root.to_hash); exit }
137
+ __action__(:help , "show this help message"){ STDOUT.puts option_parser.help; exit }
138
+
139
+ mapping({
140
+ [:action] => :k,
141
+ [:config] => :f,
142
+ [:process, :daemon] => :D,
143
+
144
+ [:event_queue, :connection, :host] => :o,
145
+ [:event_queue, :connection, :port] => :p,
146
+ [:event_queue, :connection, :user] => :u,
147
+ [:event_queue, :connection, :pass] => :s,
148
+ [:event_queue, :exchange , :name] => :e,
149
+ [:event_queue, :queue , :name] => :q,
150
+
151
+ [:heartbeat, :atd, :interval] => :G,
152
+
153
+ [:verbose] => :V,
154
+ [:version] => :v,
155
+ [:help] => :h
156
+ })
157
+ end
158
+
159
+ class Process
160
+ include Tengine::Support::Config::Definition
161
+
162
+ field :daemon, "process works on background.", :type => :boolean, :default => false
163
+ field :pid_dir, "path/to/dir for PID created.", :type => :directory, :default => "./pids"
164
+ end
165
+
166
+ def heartbeat_period
167
+ # [:][:heartbeat_period].to_i
168
+ heartbeat.interval.to_i
169
+ end
170
+
171
+ def heartbeat_enabled?
172
+ heartbeat_period > 0
173
+ end
174
+
175
+ class AmqpConnection < Tengine::Support::Config::Amqp::Connection
176
+ field :vhost, :default => '/'
177
+ field :user , :default => 'guest'
178
+ field :pass , :default => 'guest'
179
+ field :logging, :type => :boolean, :default => false
180
+ field :insist, :type => :boolean, :default => false
181
+ field :auto_reconnect_delay, :type => :integer, :default => 1
182
+ end
183
+
184
+ class LoggerConfig < Tengine::Support::Config::Logger
185
+ parameter :logger_name
186
+ depends :process_config
187
+ depends :log_common
188
+ field :output, {
189
+ :default => proc {
190
+ process_config.daemon ? "./log/#{logger_name}.log" : "STDOUT"
191
+ },
192
+ :default_description => proc {
193
+ "if daemon process then \"./log/#{logger_name}.log\" else \"STDOUT\""
194
+ }
195
+ }
196
+ field :rotation, {
197
+ :default => proc{ log_common.rotation },
198
+ :default_description => proc{ "value of #{log_common.long_opt}-rotation" }
199
+ }
200
+ field :rotation_size, {
201
+ :default => proc{ log_common.rotation_size },
202
+ :default_description => proc{ "value of #{log_common.long_opt}-rotation-size" }
203
+ }
204
+ field :level, {
205
+ :default => proc{ log_common.level },
206
+ :default_description => proc{ "value of #{log_common.long_opt}-level" }
207
+ }
208
+
209
+ def new_logger *;
210
+ super.tap {|i| i.formatter = self.formatter }
211
+ end
212
+ end
213
+
214
+ def setup_loggers
215
+ Tengine.logger = application_log.new_logger
216
+ Tengine::Core.stdout_logger = process_stdout_log.new_logger
217
+ Tengine::Core.stderr_logger = process_stderr_log.new_logger
218
+
219
+ Tengine::Core.stdout_logger.info("#{self.class.name}#setup_loggers complete")
220
+ rescue Exception
221
+ Tengine::Core.stderr_logger.info("#{self.class.name}#setup_loggers failure")
222
+ raise
223
+ end
224
+
225
+ end