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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +40 -0
- data/Gemfile.lock +95 -0
- data/README.md +54 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/bin/tengine_atd +8 -0
- data/bin/tengine_heartbeat_watchd +8 -0
- data/bin/tengined +182 -0
- data/examples/VERSION +1 -0
- data/examples/uc01_execute_processing_for_event.rb +11 -0
- data/examples/uc02_fire_another_event.rb +16 -0
- data/examples/uc03_2handlers_for_1event.rb +16 -0
- data/examples/uc08_if_both_a_and_b_occurs.rb +11 -0
- data/examples/uc10_if_the_event_occurs_at_the_server.rb +15 -0
- data/examples/uc50_commit_event_at_first.rb +17 -0
- data/examples/uc51_commit_event_at_first_submit.rb +29 -0
- data/examples/uc52_commit_event_after_all_handler_submit.rb +31 -0
- data/examples/uc52_never_commit_event_unless_all_handler_submit.rb +31 -0
- data/examples/uc60_event_in_handler.rb +18 -0
- data/examples/uc62_session_in_driver.rb +16 -0
- data/examples/uc64_safety_countup.rb +14 -0
- data/examples/uc70_driver_enabled_on_activation.rb +13 -0
- data/examples/uc71_driver_disabled_on_activation.rb +14 -0
- data/examples/uc72_setup_eventmachine.rb +17 -0
- data/examples/uc80_raise_io_error.rb +10 -0
- data/examples/uc81_raise_runtime_error.rb +10 -0
- data/examples2/driver01.rb +18 -0
- data/examples2/driver02.rb +19 -0
- data/examples2/uc08_if_both_a_and_b_occurs.rb +13 -0
- data/examples2/uc10_if_the_event_occurs_at_the_server.rb +18 -0
- data/examples2/uc51_commit_event_at_first_submit_1.rb +16 -0
- data/examples2/uc51_commit_event_at_first_submit_2.rb +17 -0
- data/examples2/uc51_commit_event_at_first_submit_3.rb +17 -0
- data/examples2/uc62_session_in_driver.rb +16 -0
- data/examples2/uc71_driver_disabled_on_activation.rb +16 -0
- data/failure_examples/VERSION +1 -0
- data/failure_examples/uc53_submit_outside_of_handler.rb +15 -0
- data/failure_examples/uc61_event_outside_of_handler.rb +12 -0
- data/failure_examples/uc63_session_outside_of_driver.rb +13 -0
- data/lib/tengine/core.rb +74 -0
- data/lib/tengine/core/bootstrap.rb +123 -0
- data/lib/tengine/core/collection_accessible.rb +34 -0
- data/lib/tengine/core/config.rb +10 -0
- data/lib/tengine/core/config/atd.rb +225 -0
- data/lib/tengine/core/config/core.rb +319 -0
- data/lib/tengine/core/config/heartbeat_watcher.rb +229 -0
- data/lib/tengine/core/connection_test/.gitignore +1 -0
- data/lib/tengine/core/connection_test/fire_bar_on_foo.rb +16 -0
- data/lib/tengine/core/driveable.rb +213 -0
- data/lib/tengine/core/driver.rb +69 -0
- data/lib/tengine/core/driver/finder.rb +42 -0
- data/lib/tengine/core/dsl_evaluator.rb +110 -0
- data/lib/tengine/core/dsl_filter_def.rb +11 -0
- data/lib/tengine/core/dsl_loader.rb +108 -0
- data/lib/tengine/core/event.rb +145 -0
- data/lib/tengine/core/event/finder.rb +82 -0
- data/lib/tengine/core/event_exception_reportable.rb +88 -0
- data/lib/tengine/core/event_wrapper.rb +21 -0
- data/lib/tengine/core/find_by_name.rb +31 -0
- data/lib/tengine/core/handler.rb +152 -0
- data/lib/tengine/core/handler_path.rb +33 -0
- data/lib/tengine/core/heartbeat_watcher.rb +161 -0
- data/lib/tengine/core/io_to_logger.rb +22 -0
- data/lib/tengine/core/kernel.rb +510 -0
- data/lib/tengine/core/kernel_runtime.rb +91 -0
- data/lib/tengine/core/method_traceable.rb +38 -0
- data/lib/tengine/core/mongoid_fix.rb +19 -0
- data/lib/tengine/core/mutex.rb +177 -0
- data/lib/tengine/core/optimistic_lock.rb +69 -0
- data/lib/tengine/core/plugins.rb +54 -0
- data/lib/tengine/core/schedule.rb +21 -0
- data/lib/tengine/core/scheduler.rb +156 -0
- data/lib/tengine/core/selectable_attr.rb +29 -0
- data/lib/tengine/core/session.rb +21 -0
- data/lib/tengine/core/session_wrapper.rb +68 -0
- data/lib/tengine/core/setting.rb +21 -0
- data/lib/tengine/core/validation.rb +36 -0
- data/lib/tengine/errors.rb +18 -0
- data/lib/tengine/rspec.rb +8 -0
- data/lib/tengine/rspec/context_wrapper.rb +51 -0
- data/lib/tengine/rspec/extension.rb +53 -0
- data/lib/tengine_core.rb +23 -0
- data/spec/factories/tengine_core_drivers.rb +10 -0
- data/spec/factories/tengine_core_events.rb +14 -0
- data/spec/factories/tengine_core_handler_paths.rb +9 -0
- data/spec/factories/tengine_core_handlers.rb +9 -0
- data/spec/factories/tengine_core_sessions.rb +9 -0
- data/spec/mongoid.yml +35 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/support/mongo_index_key_log.rb +91 -0
- data/spec/tengine/core/bootstrap_spec.rb +278 -0
- data/spec/tengine/core/bugfix/bind_dsl_file_in_multi_byte_dir_spec.rb +21 -0
- data/spec/tengine/core/bugfix/enabled_on_activation_spec.rb +112 -0
- data/spec/tengine/core/bugfix/receive_event_spec.rb +133 -0
- data/spec/tengine/core/bugfix/use_dsl_version_method.rb +12 -0
- data/spec/tengine/core/bugfix/use_dsl_version_method_spec.rb +28 -0
- data/spec/tengine/core/bugfix/use_event_in_handler_dsl.rb +11 -0
- 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
- 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
- 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
- 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
- data/spec/tengine/core/config/atd_spec.rb +62 -0
- data/spec/tengine/core/config/core_spec.rb +479 -0
- data/spec/tengine/core/config/heartbeat_watcher_spec.rb +62 -0
- data/spec/tengine/core/config/syntax_error_in_erb.yml.erb +13 -0
- data/spec/tengine/core/config/wrong_category_name.yml.erb +13 -0
- data/spec/tengine/core/config/wrong_field_name.yml.erb +12 -0
- data/spec/tengine/core/config/wrong_yaml.yml.erb +13 -0
- data/spec/tengine/core/config_spec/another_port.yml +54 -0
- data/spec/tengine/core/config_spec/config_with_dir_absolute_load_path.yml +16 -0
- data/spec/tengine/core/config_spec/config_with_dir_relative_load_path.yml +16 -0
- data/spec/tengine/core/config_spec/config_with_file_absolute_load_path.yml +16 -0
- data/spec/tengine/core/config_spec/config_with_file_relative_load_path.yml +16 -0
- data/spec/tengine/core/config_spec/log_config_spec.rb +235 -0
- data/spec/tengine/core/driveable_spec.rb +240 -0
- data/spec/tengine/core/driver_spec.rb +159 -0
- data/spec/tengine/core/dsl_loader_spec.rb +172 -0
- data/spec/tengine/core/dsls/uc08_if_both_a_and_b_occurs_spec.rb +35 -0
- data/spec/tengine/core/dsls/uc10_if_the_event_occurs_at_the_server_spec.rb +58 -0
- data/spec/tengine/core/dsls/uc50_commit_event_at_first_spec.rb +29 -0
- data/spec/tengine/core/dsls/uc52_commit_event_after_all_handler_submit_spec.rb +33 -0
- data/spec/tengine/core/dsls/uc52_never_commit_event_unless_all_handler_submit_spec.rb +37 -0
- data/spec/tengine/core/dsls/uc53_submit_outside_of_handler_spec.rb +37 -0
- data/spec/tengine/core/dsls/uc60_event_in_handler_spec.rb +31 -0
- data/spec/tengine/core/dsls/uc61_event_outside_of_handler_spec.rb +37 -0
- data/spec/tengine/core/dsls/uc62_session_in_driver_spec.rb +36 -0
- data/spec/tengine/core/dsls/uc63_session_outside_of_driver_spec.rb +35 -0
- data/spec/tengine/core/dsls/uc64_safety_countup_spec.rb +134 -0
- data/spec/tengine/core/dsls/uc70_driver_enabled_on_activation_spec.rb +39 -0
- data/spec/tengine/core/dsls/uc71_driver_disabled_on_activation_spec.rb +36 -0
- data/spec/tengine/core/dsls/uc72_setup_eventmachine_spec.rb +39 -0
- data/spec/tengine/core/dsls/uc80_raise_io_error_spec.rb +53 -0
- data/spec/tengine/core/dsls/uc81_raise_runtime_error_spec.rb +49 -0
- data/spec/tengine/core/event/finder_spec.rb +136 -0
- data/spec/tengine/core/event_exception_reportable_spec.rb +33 -0
- data/spec/tengine/core/event_spec.rb +161 -0
- data/spec/tengine/core/event_wrapper_spec.rb +35 -0
- data/spec/tengine/core/handler_path_spec.rb +87 -0
- data/spec/tengine/core/handler_spec.rb +190 -0
- data/spec/tengine/core/heartbeat_watcher_spec.rb +131 -0
- data/spec/tengine/core/io_to_logger_spec.rb +30 -0
- data/spec/tengine/core/kernel_spec.rb +885 -0
- data/spec/tengine/core/mutex_spec.rb +184 -0
- data/spec/tengine/core/optimistic_lock_spec.rb +55 -0
- data/spec/tengine/core/scheculer_spec.rb +121 -0
- data/spec/tengine/core/selectable_attr_spec.rb +30 -0
- data/spec/tengine/core/session_spec.rb +104 -0
- data/spec/tengine/core/setting_spec.rb +79 -0
- data/spec/tengine/core_spec.rb +13 -0
- data/spec/tengine_spec.rb +14 -0
- data/tengine_core.gemspec +248 -0
- data/tmp/log/.gitignore +1 -0
- data/tmp/tengined_status/.gitignore +1 -0
- metadata +421 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'pathname'
|
|
3
|
+
|
|
4
|
+
module Tengine::Core::DslLoader
|
|
5
|
+
include Tengine::Core::DslEvaluator
|
|
6
|
+
|
|
7
|
+
attr_accessor :__kernel__
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# どのようなポリシーでackを返すのかをイベント種別名毎に指定できます。
|
|
11
|
+
#
|
|
12
|
+
# @param [Symbol] policy ackポリシー
|
|
13
|
+
# @param [[Symbol/String]] args イベント種別名の配列
|
|
14
|
+
#
|
|
15
|
+
# 例:
|
|
16
|
+
# {include:file:examples/uc50_commit_event_at_first.rb}
|
|
17
|
+
#
|
|
18
|
+
# 例:
|
|
19
|
+
# {include:file:examples/uc51_commit_event_at_first_submit.rb}
|
|
20
|
+
#
|
|
21
|
+
# 例:
|
|
22
|
+
# {include:file:examples/uc52_commit_event_after_all_handler_submit.rb}
|
|
23
|
+
#
|
|
24
|
+
def ack_policy(policy, *args)
|
|
25
|
+
args.each{|arg| @__kernel__.add_ack_policy(arg, policy)}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# このメソッドにブロックを渡すことで、Tengineコアが使用するEventMachineの初期化を行うために設定を行うことができます。
|
|
29
|
+
#
|
|
30
|
+
# 例:
|
|
31
|
+
# {include:file:examples/uc72_setup_eventmachine.rb}
|
|
32
|
+
#
|
|
33
|
+
def setup_eventmachine(&block)
|
|
34
|
+
return unless block
|
|
35
|
+
@__kernel__.em_setup_blocks << block
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# イベントドライバを登録します。
|
|
39
|
+
#
|
|
40
|
+
# イベントドライバはonメソッドで定義されるイベントハンドラを持つことができます。
|
|
41
|
+
# イベントドライバは実行時のユーザーによる有効化、無効化の対象になります。
|
|
42
|
+
# 無効化されたイベントドライバのイベントハンドラは、イベントが発生した際に
|
|
43
|
+
# それがフィルタにマッチしたとしても、その処理を実行しません。
|
|
44
|
+
# つまりイベントハンドラの有効化、無効化は、それをまとめているイベントドライバ毎に
|
|
45
|
+
# 指定することが可能です。
|
|
46
|
+
#
|
|
47
|
+
# @param [String] name イベントドライバ名
|
|
48
|
+
# @param [Hash] options オプション
|
|
49
|
+
# @option options [String] :enabled_on_activation 実行時に有効にするならばtrue、でなければfalse。デフォルトはtrue
|
|
50
|
+
# @return [Tengine::Core::Driver]
|
|
51
|
+
# @see #on
|
|
52
|
+
#
|
|
53
|
+
# 例:
|
|
54
|
+
# {include:file:examples/uc01_execute_processing_for_event.rb}
|
|
55
|
+
def driver(name, options = {}, &block)
|
|
56
|
+
unless block_given?
|
|
57
|
+
# Tengine::Core::stdout.info("no block given at #{caller.first}")
|
|
58
|
+
return
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if dsl_version_document = Tengine::Core::Setting.first(:conditions => {:name => "dsl_version"})
|
|
62
|
+
dsl_version_document.value = config.dsl_version
|
|
63
|
+
dsl_version_document.save!
|
|
64
|
+
else
|
|
65
|
+
Tengine::Core::Setting.create!(:name => "dsl_version", :value => config.dsl_version)
|
|
66
|
+
end
|
|
67
|
+
c = config
|
|
68
|
+
klass = Class.new
|
|
69
|
+
const_name = name.to_s.camelize
|
|
70
|
+
# if Object.constants.include?(const_name) || defined?(const_name)
|
|
71
|
+
# puts "#{const_name} is already defined\n " << caller.join("\n ")
|
|
72
|
+
# end
|
|
73
|
+
Object.send :remove_const, const_name if Object.const_defined? const_name
|
|
74
|
+
Object.const_set(const_name, klass)
|
|
75
|
+
klass.module_eval do
|
|
76
|
+
include Tengine::Core::Driveable::ByDsl
|
|
77
|
+
self.singleton_class.config = c
|
|
78
|
+
self.singleton_class.options = options
|
|
79
|
+
include Tengine::Core::Driveable
|
|
80
|
+
end
|
|
81
|
+
begin
|
|
82
|
+
klass.module_eval(&block)
|
|
83
|
+
rescue Exception => e
|
|
84
|
+
driver = klass.driver
|
|
85
|
+
driver.destroy if driver && !driver.new_record?
|
|
86
|
+
raise e
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @see Tengine::Core::DslBinder#session
|
|
91
|
+
def session
|
|
92
|
+
raise Tengine::Core::DslError, "session is not available outside of event driver block." unless @__session__
|
|
93
|
+
@__session_wrapper__ ||= Tengine::Core::SessionWrapper.new(@__session__)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def fire(*args, &blcok)
|
|
97
|
+
options = args.extract_options!
|
|
98
|
+
options[:keep_connection] = true
|
|
99
|
+
args = args + [options]
|
|
100
|
+
Tengine::Event.fire(*args, &blcok)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# 現時点ではMM1との互換性のためのダミーのメソッドです
|
|
104
|
+
# 必要があれば将来ちゃんと役割を見直して復活するかもしれません
|
|
105
|
+
def dsl_version(*args)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'tengine/core'
|
|
3
|
+
|
|
4
|
+
require 'selectable_attr'
|
|
5
|
+
|
|
6
|
+
class Tengine::Core::Event
|
|
7
|
+
autoload :Finder, 'tengine/core/event/finder'
|
|
8
|
+
|
|
9
|
+
include Mongoid::Document
|
|
10
|
+
include Mongoid::Timestamps
|
|
11
|
+
include Tengine::Core::Validation
|
|
12
|
+
include Tengine::Core::SelectableAttr
|
|
13
|
+
include Tengine::Core::CollectionAccessible
|
|
14
|
+
|
|
15
|
+
field :lock_version , :type => Integer, :default => -(2**63)
|
|
16
|
+
field :event_type_name, :type => String
|
|
17
|
+
field :key , :type => String
|
|
18
|
+
field :source_name , :type => String
|
|
19
|
+
field :occurred_at , :type => Time
|
|
20
|
+
field :level , :type => Integer, :default => 2
|
|
21
|
+
field :confirmed , :type => Boolean
|
|
22
|
+
field :sender_name , :type => String
|
|
23
|
+
field :properties , :type => Hash
|
|
24
|
+
map_yaml_accessor :properties
|
|
25
|
+
|
|
26
|
+
validates :event_type_name, :presence => true, :format => EVENT_TYPE_NAME.options
|
|
27
|
+
|
|
28
|
+
# 以下の2つはバリデーションを設定したいところですが、外部からの入力は極力保存できる
|
|
29
|
+
# ようにしたいのでバリデーションを外します。
|
|
30
|
+
# validates :source_name, :presence => true #, :format => RESOURCE_IDENTIFIER.options
|
|
31
|
+
# validates :sender_name, :presence => true #, :format => RESOURCE_IDENTIFIER.options
|
|
32
|
+
|
|
33
|
+
# 複数の経路から同じ意味のイベントが複数個送られる場合に
|
|
34
|
+
# これらを重複して登録しないようにユニーク制約を設定
|
|
35
|
+
index :key, unique: true
|
|
36
|
+
# :unique => trueのindexを設定しているので、uniquenessのバリデーションは設定しません
|
|
37
|
+
validates :key, :presence => true #, :uniqueness => true
|
|
38
|
+
|
|
39
|
+
index([ [:event_type_name, Mongo::ASCENDING], [:confirmed, Mongo::ASCENDING], ])
|
|
40
|
+
index([ [:event_type_name, Mongo::ASCENDING], [:level, Mongo::ASCENDING], [:occurred_at, Mongo::DESCENDING], ])
|
|
41
|
+
index([ [:event_type_name, Mongo::ASCENDING], [:occurred_at, Mongo::ASCENDING], ])
|
|
42
|
+
index([ [:event_type_name, Mongo::ASCENDING], [:source_name, Mongo::ASCENDING], ])
|
|
43
|
+
index([ [:level, Mongo::ASCENDING], [:sender_name, Mongo::ASCENDING], [:occurred_at, Mongo::DESCENDING], ])
|
|
44
|
+
index([ [:level, Mongo::ASCENDING], [:occurred_at, Mongo::DESCENDING], ])
|
|
45
|
+
index([ [:source_name, Mongo::ASCENDING], [:level, Mongo::ASCENDING], [:occurred_at, Mongo::DESCENDING], ])
|
|
46
|
+
|
|
47
|
+
# selectable_attrを使ってます
|
|
48
|
+
# see http://github.com/akm/selectable_attr
|
|
49
|
+
# http://github.com/akm/selectable_attr_rails
|
|
50
|
+
selectable_attr :level do
|
|
51
|
+
entry 1, :debug , "debug"
|
|
52
|
+
entry 2, :info , "info"
|
|
53
|
+
entry 3, :warn , "warn"
|
|
54
|
+
entry 4, :error , "error"
|
|
55
|
+
entry 5, :fatal , "fatal"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
attr_accessor :kernel # tengined実行時に処理しているカーネルのインスタンスを保持します
|
|
59
|
+
|
|
60
|
+
def to_hash
|
|
61
|
+
ret = attributes.dup # <- dup ?
|
|
62
|
+
ret.delete "_id"
|
|
63
|
+
ret
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# TODO: Tengine::Core::OptimisticLockを拡張して、ここでも使えるよう
|
|
67
|
+
# にする。現状は同じようなコードが複数箇所にあってよくない。
|
|
68
|
+
|
|
69
|
+
# @yield [event] Yields the (possibly new) event.
|
|
70
|
+
# @yieldparam [Tengine::Core::Event] event The event in question.
|
|
71
|
+
# @yieldreturn [Boolean] Return false, and it will just break the execution. Otherwise, it tries to update the event.
|
|
72
|
+
# @param [Hash] condition Criteria to find a document.
|
|
73
|
+
# @param [Numeric] retry_max (3) Maximum number of retry attempts to save the event.
|
|
74
|
+
# @return [Tengine::Core::Event] The event in question if update succeeded, false if retry_max reached, or nil if the block exited with false.
|
|
75
|
+
# @raise [Mongo::OperationFailure] Any exceptions that happened inside will be propagated outside.
|
|
76
|
+
def self.find_or_create_then_update_with_block condition, retry_max = 3
|
|
77
|
+
# * とある条件を満たすイベントがあれば、それを上書きしたい。
|
|
78
|
+
# * なければ、新規作成したい。
|
|
79
|
+
# * でもアトミックにやりたい。
|
|
80
|
+
# * ないとおもって新規作成しようとしたら裏でイベントが生えていたら、上書きモードでやり直したい。
|
|
81
|
+
# * あるとおもって上書きしようとしたら裏でイベントが消えていたら、新規作成モードでやり直したい。
|
|
82
|
+
# * という要求をできるだけ高速に処理したい。
|
|
83
|
+
|
|
84
|
+
the_event = nil
|
|
85
|
+
retries = -1
|
|
86
|
+
results = nil
|
|
87
|
+
|
|
88
|
+
case collection.driver.db.connection when Mongo::ReplSetConnection then
|
|
89
|
+
safemode = { :w => "majority", :wtimeout => 1024, } # mongodb 2.0+, 参加しているレプリカセットの多数派に書き込んだ時点でOK扱い
|
|
90
|
+
else
|
|
91
|
+
safemode = true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
while true do
|
|
95
|
+
return false if retries >= retry_max # retryしすぎ
|
|
96
|
+
|
|
97
|
+
retries += 1
|
|
98
|
+
# あればとってくる
|
|
99
|
+
if the_event and not the_event.new_record?
|
|
100
|
+
the_event.reload
|
|
101
|
+
else
|
|
102
|
+
the_event = where(condition).first || new(condition)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return nil if not yield(the_event) # ユザーによる意図的な中断
|
|
106
|
+
|
|
107
|
+
hash = the_event.as_document.dup # <- dup ?
|
|
108
|
+
hash.delete "_id"
|
|
109
|
+
hash['lock_version'] = the_event.lock_version + 1
|
|
110
|
+
hash['created_at'] ||= Time.at(Time.now.to_i)
|
|
111
|
+
hash['updated_at'] = Time.at(Time.now.to_i)
|
|
112
|
+
|
|
113
|
+
begin
|
|
114
|
+
results = collection.driver.update(
|
|
115
|
+
{ :key => the_event.key, :lock_version => the_event.lock_version },
|
|
116
|
+
{ "$set" => hash },
|
|
117
|
+
{ :upsert => true, :safe => safemode, :multiple => false }
|
|
118
|
+
)
|
|
119
|
+
rescue Mongo::OperationFailure => e
|
|
120
|
+
# upsert = trueだがindexのunique制約があるので重複したkeyは
|
|
121
|
+
# 作成不可、lock_versionの更新失敗はこちらに来る。これは意
|
|
122
|
+
# 図した動作なのでraiseしない。
|
|
123
|
+
Tengine.logger.debug "retrying due to mongodb error #{e}"
|
|
124
|
+
# lock_versionが存在しない可能性(そのような古いDBを引きずっている等)
|
|
125
|
+
collection.driver.update(
|
|
126
|
+
{ :key => the_event.key, :lock_version => { "$exists" => false } },
|
|
127
|
+
{ "$set" => { :lock_version => -(2**63) } },
|
|
128
|
+
{ :upsert => false, :safe => $safemode, :multiple => false }
|
|
129
|
+
)
|
|
130
|
+
else
|
|
131
|
+
if results["error"]
|
|
132
|
+
raise Mongo::OperationFailure, results["error"]
|
|
133
|
+
elsif results["upserted"]
|
|
134
|
+
# *hack* _idを消してupsertしたので、このとき_idは新しくなっている
|
|
135
|
+
the_event.write_attributes "_id" => results["upserted"]
|
|
136
|
+
the_event.reload
|
|
137
|
+
return the_event
|
|
138
|
+
else
|
|
139
|
+
the_event.reload
|
|
140
|
+
return the_event
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'tengine/core/event'
|
|
3
|
+
|
|
4
|
+
class Tengine::Core::Event::Finder
|
|
5
|
+
|
|
6
|
+
include ::SelectableAttr::Base
|
|
7
|
+
|
|
8
|
+
ATTRIBUTE_NAMES = [
|
|
9
|
+
:event_type_name,
|
|
10
|
+
:key,
|
|
11
|
+
:source_name,
|
|
12
|
+
:occurred_at_start,
|
|
13
|
+
:occurred_at_end,
|
|
14
|
+
:level_ids,
|
|
15
|
+
:confirmed,
|
|
16
|
+
:sender_name,
|
|
17
|
+
:properties,
|
|
18
|
+
:reflesh_interval, # 更新間隔
|
|
19
|
+
].freeze
|
|
20
|
+
|
|
21
|
+
ATTRIBUTE_NAMES.each{|name| attr_accessor(name)}
|
|
22
|
+
|
|
23
|
+
# 通知レベル
|
|
24
|
+
multi_selectable_attr :level, :enum => Tengine::Core::Event.level_enum
|
|
25
|
+
|
|
26
|
+
def initialize(attrs = {})
|
|
27
|
+
attrs = {
|
|
28
|
+
:level_ids => default_level_ids
|
|
29
|
+
}.update(attrs || {})
|
|
30
|
+
attrs.each do |attr, v|
|
|
31
|
+
send("#{attr}=", v) unless v.blank?
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def attributes
|
|
36
|
+
ATTRIBUTE_NAMES.inject({}){|d, name| d[name] = send(name); d}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# デフォルトでは通知レベルがすべて選択された状態にする
|
|
40
|
+
def default_level_ids
|
|
41
|
+
result = []
|
|
42
|
+
Tengine::Core::Event.level_entries.each do |entry|
|
|
43
|
+
result << entry.id
|
|
44
|
+
end
|
|
45
|
+
return result
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def paginate(page = nil)
|
|
49
|
+
result = scope(Tengine::Core::Event)
|
|
50
|
+
if page || result.respond_to?(:page)
|
|
51
|
+
result = result.page(page)
|
|
52
|
+
end
|
|
53
|
+
result
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def scope(criteria)
|
|
57
|
+
result = criteria
|
|
58
|
+
result = result.where(:event_type_name => str_or_regexp(event_type_name)) if event_type_name
|
|
59
|
+
result = result.where(:key => key) if key
|
|
60
|
+
result = result.where(:source_name => str_or_regexp(source_name)) if source_name
|
|
61
|
+
result = result.where(:occurred_at.gte => occurred_at_start) if occurred_at_start
|
|
62
|
+
result = result.where(:occurred_at.lte => occurred_at_end) if occurred_at_end
|
|
63
|
+
result = result.any_in(:level => level_ids) if level_ids
|
|
64
|
+
result = result.where(:confirmed => confirmed) if confirmed
|
|
65
|
+
result = result.where(:sender_name => str_or_regexp(sender_name)) if sender_name
|
|
66
|
+
result = result.where(:properties => properties) if properties
|
|
67
|
+
# ソート
|
|
68
|
+
result = result.desc(:occurred_at)
|
|
69
|
+
result
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
def str_or_regexp(val)
|
|
74
|
+
if val =~ %r{\A\/(.+)\/\Z}
|
|
75
|
+
/#{$1}/
|
|
76
|
+
else
|
|
77
|
+
/\A#{Regexp.escape(val)}/
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'tengine/core'
|
|
2
|
+
|
|
3
|
+
module Tengine::Core::EventExceptionReportable
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
FIRE_ALL = lambda do |kernel, dsl_context, event, exception|
|
|
7
|
+
kernel.fire("#{event.event_type_name}.error.tengined",
|
|
8
|
+
:properties => {
|
|
9
|
+
:original_event => event.to_json,
|
|
10
|
+
:error_class_name => exception.class.name,
|
|
11
|
+
:error_message => exception.message,
|
|
12
|
+
:error_backtrace => exception.backtrace,
|
|
13
|
+
# :block_source_location => '%s:%d' % block.source_location,
|
|
14
|
+
})
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
FIRE_EXCEPT_TESTING_ERROR = lambda do |kernel, dsl_context, event, exception|
|
|
18
|
+
if exception.class.name =~ /^Test::|^MiniTest::|^RSpec::|^Spec::/
|
|
19
|
+
raise exception
|
|
20
|
+
else
|
|
21
|
+
FIRE_ALL.call(kernel, dsl_context, event, exception)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
RAISE_ALL = lambda do |kernel, dsl_context, event, exception|
|
|
26
|
+
raise exception
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
EVENT_EXCEPTION_REPORTERS = {
|
|
30
|
+
:fire_all => FIRE_ALL,
|
|
31
|
+
:raise_all => RAISE_ALL,
|
|
32
|
+
:except_test => FIRE_EXCEPT_TESTING_ERROR,
|
|
33
|
+
}.freeze
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
def to_reporter(reporter)
|
|
37
|
+
if reporter.is_a?(Symbol)
|
|
38
|
+
result = EVENT_EXCEPTION_REPORTERS[reporter]
|
|
39
|
+
raise NameError, "Unknown reporter: #{reporter.inspect}" unless result
|
|
40
|
+
result
|
|
41
|
+
elsif reporter.respond_to?(:call)
|
|
42
|
+
reporter
|
|
43
|
+
else
|
|
44
|
+
raise ArgumentError, "Invalid reporter: #{reporter.inspect}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module ClassMethods
|
|
50
|
+
def event_exception_reporter
|
|
51
|
+
unless defined?(@event_exception_reporter)
|
|
52
|
+
@event_exception_reporter = FIRE_ALL
|
|
53
|
+
end
|
|
54
|
+
@event_exception_reporter
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def event_exception_reporter=(reporter)
|
|
58
|
+
@event_exception_reporter =
|
|
59
|
+
Tengine::Core::EventExceptionReportable.to_reporter(reporter)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def temp_exception_reporter(reporter)
|
|
63
|
+
backup = self.event_exception_reporter
|
|
64
|
+
begin
|
|
65
|
+
self.event_exception_reporter = reporter
|
|
66
|
+
yield if block_given?
|
|
67
|
+
ensure
|
|
68
|
+
self.event_exception_reporter = backup
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
module InstanceMethods
|
|
75
|
+
def report_on_exception(dsl_context, event)
|
|
76
|
+
begin
|
|
77
|
+
yield
|
|
78
|
+
rescue Exception => e
|
|
79
|
+
Tengine.logger.error("[#{e.class.name}] #{e.message}\n " << e.backtrace.join("\n "))
|
|
80
|
+
if reporter = Tengine::Core::Kernel.event_exception_reporter
|
|
81
|
+
reporter.call(self, dsl_context, event, e)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
require 'tengine/core'
|
|
3
|
+
|
|
4
|
+
class Tengine::Core::EventWrapper
|
|
5
|
+
|
|
6
|
+
def initialize(source)
|
|
7
|
+
@source = source
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
[:event_type_name, :key, :source_name, :occurred_at,
|
|
11
|
+
:level, :confirmed, :sender_name, :properties,].each do |attr_name|
|
|
12
|
+
class_eval(<<-EOS)
|
|
13
|
+
def #{attr_name}; @source.#{attr_name}; end
|
|
14
|
+
EOS
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def [](key)
|
|
18
|
+
properties[key.to_s]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|