tengine_core 0.5.28
Sign up to get free protection for your applications and to get access to all the features.
- 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,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/core'
|
3
|
+
|
4
|
+
class Tengine::Core::Schedule
|
5
|
+
include Mongoid::Document
|
6
|
+
include Mongoid::Timestamps
|
7
|
+
|
8
|
+
# statuses
|
9
|
+
SCHEDULED = 0
|
10
|
+
INVALID = 1
|
11
|
+
FIRED = 2
|
12
|
+
|
13
|
+
field :event_type_name, :type => String
|
14
|
+
field :scheduled_at , :type => Time , :default => proc { Time.now }
|
15
|
+
field :status , :type => Integer, :default => SCHEDULED
|
16
|
+
field :source_name , :type => String
|
17
|
+
field :properties , :type => Hash , :default => proc { Hash.new }
|
18
|
+
|
19
|
+
index([ [:scheduled_at, Mongo::ASCENDING], [:status, Mongo::ASCENDING], ])
|
20
|
+
index([ [:status, Mongo::ASCENDING], ])
|
21
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'daemons'
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'mongoid'
|
5
|
+
require 'uuid'
|
6
|
+
|
7
|
+
$LOAD_PATH.push File.expand_path("../../../../lib/", __FILE__)
|
8
|
+
|
9
|
+
require 'tengine/core'
|
10
|
+
require 'tengine/event'
|
11
|
+
require 'tengine/mq'
|
12
|
+
|
13
|
+
# explicit loading
|
14
|
+
require_relative 'config/atd'
|
15
|
+
require_relative 'method_traceable'
|
16
|
+
require_relative 'schedule'
|
17
|
+
require_relative 'mongoid_fix'
|
18
|
+
|
19
|
+
class Tengine::Core::Scheduler
|
20
|
+
|
21
|
+
def initialize argv
|
22
|
+
@uuid = UUID.new.generate
|
23
|
+
@config = Tengine::Core::Config::Atd.parse argv
|
24
|
+
@daemonize_options = {
|
25
|
+
:app_name => 'tengine_atd',
|
26
|
+
:ARGV => [@config[:action]],
|
27
|
+
:ontop => !@config[:process][:daemon],
|
28
|
+
:multiple => true,
|
29
|
+
:dir_mode => :normal,
|
30
|
+
:dir => File.expand_path(@config[:process][:pid_dir]),
|
31
|
+
}
|
32
|
+
|
33
|
+
Tengine::Core::MethodTraceable.disabled = !@config[:verbose]
|
34
|
+
rescue Exception
|
35
|
+
puts "[#{$!.class.name}] #{$!.message}\n " << $!.backtrace.join("\n ")
|
36
|
+
raise
|
37
|
+
end
|
38
|
+
|
39
|
+
def sender
|
40
|
+
@sender ||= Tengine::Event::Sender.new Tengine::Mq::Suite.new(@config[:event_queue])
|
41
|
+
end
|
42
|
+
|
43
|
+
def pid
|
44
|
+
@pid ||= sprintf "process:%s/%d", ENV["MM_SERVER_NAME"], Process.pid
|
45
|
+
end
|
46
|
+
|
47
|
+
def send_last_event
|
48
|
+
sender.fire "finished.process.atd.tengine", :key => @uuid, :source_name => pid, :sender_name => pid, :occurred_at => Time.now, :level_key => :info, :keep_connection => true
|
49
|
+
sender.stop
|
50
|
+
end
|
51
|
+
|
52
|
+
def send_periodic_event
|
53
|
+
sender.fire "atd.heartbeat.tengine", :key => @uuid, :source_name => pid, :sender_name => pid, :occurred_at => Time.now, :level_key => :debug, :keep_connection => true, :retry_count => 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_scheduled_event sched
|
57
|
+
Tengine.logger.info "Scheduled time (#{sched.scheduled_at}) has come. Now firing #{sched.event_type_name} for #{sched.source_name}"
|
58
|
+
sender.fire sched.event_type_name, :key => sched._id, :source_name => sched.source_name, :sender_name => pid, :occurred_at => Time.now, :level_key => :info, :keep_connection => true, :properties => sched.properties
|
59
|
+
end
|
60
|
+
|
61
|
+
def mark_schedule_done sched
|
62
|
+
# 複数のマシンで複数のatdが複数動いている可能性があり、その場合には複数の
|
63
|
+
# atdが同時に同じエントリに更新をかける可能性はとても高い。そのような状況
|
64
|
+
# でもエラーになってはいけない。
|
65
|
+
Tengine::Core::Schedule.where(
|
66
|
+
:_id => sched.id,
|
67
|
+
:status => Tengine::Core::Schedule::SCHEDULED
|
68
|
+
).update_all(
|
69
|
+
:status => Tengine::Core::Schedule::FIRED
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
def search_for_schedule
|
74
|
+
Tengine::Core::Schedule.where(
|
75
|
+
:scheduled_at.lte => Time.now,
|
76
|
+
:status => Tengine::Core::Schedule::SCHEDULED
|
77
|
+
).each_next_tick do |i|
|
78
|
+
yield i
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def run(__file__)
|
83
|
+
case @config[:action].to_sym
|
84
|
+
when :start
|
85
|
+
start_daemon(__file__)
|
86
|
+
when :stop
|
87
|
+
stop_daemon(__file__)
|
88
|
+
when :restart
|
89
|
+
stop_daemon(__file__)
|
90
|
+
start_daemon(__file__)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def start_daemon(__file__)
|
95
|
+
pdir = File.expand_path @config[:process][:pid_dir]
|
96
|
+
fname = File.basename __file__
|
97
|
+
cwd = Dir.getwd
|
98
|
+
# Daemons.run_proc(fname, :ARGV => [@config[:action]], :multiple => true, :ontop => !@config[:process][:daemon], :dir_mode => :normal, :dir => pdir) do
|
99
|
+
Daemons.run_proc(fname, @daemonize_options) do
|
100
|
+
Dir.chdir(cwd) { self.start }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def stop_daemon(__file__)
|
105
|
+
fname = File.basename __file__
|
106
|
+
Daemons.run_proc(fname, @daemonize_options)
|
107
|
+
end
|
108
|
+
|
109
|
+
def shutdown
|
110
|
+
EM.run do
|
111
|
+
EM.cancel_timer @periodic if @periodic
|
112
|
+
send_last_event
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def start
|
117
|
+
@config.setup_loggers
|
118
|
+
|
119
|
+
Mongoid.config.from_hash @config[:db]
|
120
|
+
Mongoid.config.option :persist_in_safe_mode, :default => true
|
121
|
+
|
122
|
+
require 'amqp'
|
123
|
+
Mongoid.logger = AMQP::Session.logger = Tengine.logger
|
124
|
+
|
125
|
+
EM.run do
|
126
|
+
sender.wait_for_connection do
|
127
|
+
@invalidate = EM.add_periodic_timer 1 do # !!! MAGIC NUMBER
|
128
|
+
search_for_schedule do |sched|
|
129
|
+
send_scheduled_event sched
|
130
|
+
mark_schedule_done sched
|
131
|
+
end
|
132
|
+
end
|
133
|
+
int = @config[:heartbeat][:atd][:interval].to_i
|
134
|
+
if int and int > 0
|
135
|
+
@periodic = EM.add_periodic_timer int do
|
136
|
+
send_periodic_event
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
extend Tengine::Core::MethodTraceable
|
144
|
+
method_trace(*instance_methods(false))
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Local Variables:
|
149
|
+
# mode: ruby
|
150
|
+
# coding: utf-8-unix
|
151
|
+
# indent-tabs-mode: nil
|
152
|
+
# tab-width: 4
|
153
|
+
# ruby-indent-level: 2
|
154
|
+
# fill-column: 79
|
155
|
+
# default-justification: full
|
156
|
+
# End:
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'tengine/core'
|
2
|
+
|
3
|
+
require 'selectable_attr'
|
4
|
+
|
5
|
+
module Tengine::Core::SelectableAttr
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include ::SelectableAttr::Base
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def selectable_attr_with_i18n_scope(attr_name, *args, &block)
|
13
|
+
enum = selectable_attr_without_i18n_scope(attr_name, *args, &block)
|
14
|
+
enum.i18n_scope('selectable_attrs', self.name.underscore, attr_name.to_s)
|
15
|
+
enum
|
16
|
+
end
|
17
|
+
alias_method_chain :selectable_attr, :i18n_scope
|
18
|
+
|
19
|
+
def multi_selectable_attr_with_i18n_scope(attr_name, *args, &block)
|
20
|
+
enum = multi_selectable_attr_without_i18n_scope(attr_name, *args, &block)
|
21
|
+
enum.i18n_scope('selectable_attrs', self.name.underscore, attr_name.to_s)
|
22
|
+
enum
|
23
|
+
end
|
24
|
+
alias_method_chain :multi_selectable_attr, :i18n_scope
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/core'
|
3
|
+
|
4
|
+
class Tengine::Core::Session
|
5
|
+
include Mongoid::Document
|
6
|
+
include Mongoid::Timestamps
|
7
|
+
include Tengine::Core::CollectionAccessible
|
8
|
+
include Tengine::Core::OptimisticLock
|
9
|
+
|
10
|
+
field :lock_version, :type => Integer, :default => 1
|
11
|
+
field :properties, :type => Hash, :default => {}
|
12
|
+
map_yaml_accessor :properties
|
13
|
+
field :system_properties, :type => Hash, :default => {}
|
14
|
+
map_yaml_accessor :system_properties
|
15
|
+
|
16
|
+
has_one :driver, :class_name => "Tengine::Core::Driver"
|
17
|
+
|
18
|
+
# 元々の[]と[]=メソッドをオーバーライドしているので要注意
|
19
|
+
def [](key); properties[key]; end
|
20
|
+
def []=(key, value); properties[key] = value; end
|
21
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/core'
|
3
|
+
|
4
|
+
require 'active_support/core_ext/array/extract_options'
|
5
|
+
require 'active_support/hash_with_indifferent_access'
|
6
|
+
|
7
|
+
class Tengine::Core::SessionWrapper
|
8
|
+
|
9
|
+
def initialize(source, options = {})
|
10
|
+
@options = options || {}
|
11
|
+
@source = source
|
12
|
+
end
|
13
|
+
|
14
|
+
def system_properties
|
15
|
+
@source.system_properties
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
@source.properties[key.to_s]
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(*args, &block)
|
23
|
+
return if @options[:ignore_update]
|
24
|
+
__update__(:properties, *args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def system_update(*args, &block)
|
28
|
+
__update__(:system_properties, *args, &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def __update__(target_name, *args, &block)
|
33
|
+
if block_given?
|
34
|
+
options = args.extract_options!
|
35
|
+
retry_count = options[:retry] || 5
|
36
|
+
idx = 1
|
37
|
+
while idx <= retry_count
|
38
|
+
values = ActiveSupport::HashWithIndifferentAccess.new(__get_properties__(target_name, idx > 0))
|
39
|
+
yield(values)
|
40
|
+
return if __find_and_modify__(target_name, values)
|
41
|
+
idx += 1
|
42
|
+
end
|
43
|
+
raise Tengine::Core::OptimisticLock::RetryOverError, "retried #{retry_count} times but failed to update"
|
44
|
+
else
|
45
|
+
properties = args.first
|
46
|
+
new_vals = __get_properties__(target_name).merge(properties.stringify_keys)
|
47
|
+
@source.send("#{target_name}=", new_vals)
|
48
|
+
@source.save!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# テストで同時に値を取得したことを再現するために、
|
53
|
+
# データを取得するメソッドで待ち合わせするフックとなるようにメソッドに分けています
|
54
|
+
def __get_properties__(target_name, reload = false)
|
55
|
+
@source.reload if reload
|
56
|
+
@source.send(target_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def __find_and_modify__(target_name, values)
|
60
|
+
result = Tengine::Core::Session.collection.find_and_modify({
|
61
|
+
:query => {:_id => @source.id, :lock_version => @source.lock_version},
|
62
|
+
:update => { target_name => values, :lock_version => @source.lock_version + 1}
|
63
|
+
})
|
64
|
+
result
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'tengine/core'
|
2
|
+
|
3
|
+
class Tengine::Core::Setting
|
4
|
+
include Mongoid::Document
|
5
|
+
include Tengine::Core::FindByName
|
6
|
+
|
7
|
+
field :name, :type => String
|
8
|
+
field :value
|
9
|
+
|
10
|
+
validates :name, :presence => true, :uniqueness => true
|
11
|
+
|
12
|
+
index :name, :unique => true
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def dsl_version
|
16
|
+
document = first(:conditions => {:name => "dsl_version"})
|
17
|
+
raise Mongoid::Errors::DocumentNotFound.new(Tengine::Core::Setting, "dsl_version") unless document
|
18
|
+
document.value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/core'
|
3
|
+
|
4
|
+
module Tengine::Core::Validation
|
5
|
+
|
6
|
+
class Definition
|
7
|
+
attr_reader :format, :description
|
8
|
+
def initialize(format, description)
|
9
|
+
@format, @description = format.freeze, description.freeze
|
10
|
+
end
|
11
|
+
def message
|
12
|
+
"は#{description}でなければなりません"
|
13
|
+
end
|
14
|
+
def options
|
15
|
+
{:with => format, :message => message}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# ベース名
|
20
|
+
BASE_NAME = Definition.new(
|
21
|
+
/\A[A-Za-z_][\w\-]*\Z/,
|
22
|
+
"英文字またはアンダースコアから始まり、英文字、アンダースコア、ハイフンまたは数字で構成される文字列").freeze
|
23
|
+
|
24
|
+
# イベント種別名
|
25
|
+
EVENT_TYPE_NAME = Definition.new(
|
26
|
+
/\A[A-Za-z_][\w\-\.\:]*\Z/,
|
27
|
+
"英文字またはアンダースコアから始まり、英文字、アンダースコア、ハイフン、ドット、コロンまたは数字で構成される文字列").freeze
|
28
|
+
|
29
|
+
# リソース識別子
|
30
|
+
RESOURCE_IDENTIFIER_PROTOCOL_FORMAT = /\A\w+\Z/.freeze
|
31
|
+
RESOURCE_IDENTIFIER = Definition.new(
|
32
|
+
/\A#{RESOURCE_IDENTIFIER_PROTOCOL_FORMAT.source}:#{BASE_NAME.format.source}(?:\/#{BASE_NAME.format.source})*\Z/,
|
33
|
+
"'プロトコル:要素1/要素2/.../要素N'という構造を持つ文字列(プロトコルは英数字あるいはアンダースコア、要素は英数字あるいはアンダースコアかハイフン)"
|
34
|
+
).freeze
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine_core'
|
3
|
+
|
4
|
+
module Tengine::Errors
|
5
|
+
|
6
|
+
# Tengineが提供するAPIによってデータが見つからないことを示す例外です。
|
7
|
+
# railsの場合、ActionDispatch::ShowExceptions.rescue_responses を使って
|
8
|
+
# 以下のように設定して使用することを想定しています。
|
9
|
+
#
|
10
|
+
# ActionDispatch::ShowExceptions.rescue_responses.update({
|
11
|
+
# "Tengine::Errors::NotFound" => :not_found,
|
12
|
+
# })
|
13
|
+
#
|
14
|
+
# see http://d.hatena.ne.jp/takihiro/20100318/1268864801
|
15
|
+
class NotFound < StandardError
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/rspec'
|
3
|
+
|
4
|
+
# Kernelのcontextをラップするクラスです
|
5
|
+
class Tengine::RSpec::ContextWrapper
|
6
|
+
attr_accessor :__driver__
|
7
|
+
|
8
|
+
def initialize(kernel)
|
9
|
+
@kernel = kernel
|
10
|
+
@context = @kernel.context
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive(event_type_name, options = {})
|
14
|
+
mock_headers = Object.new
|
15
|
+
mock_headers.should_receive(:ack)
|
16
|
+
raw_event = Tengine::Event.new({:event_type_name => event_type_name}.update(options || {}))
|
17
|
+
@kernel.process_message(mock_headers, raw_event.to_json)
|
18
|
+
end
|
19
|
+
|
20
|
+
def should_receive(*args)
|
21
|
+
@context.should_receive(*args)
|
22
|
+
end
|
23
|
+
|
24
|
+
def should_not_receive(*args)
|
25
|
+
@context.should_not_receive(*args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def should_fire(*args)
|
29
|
+
@kernel.should_receive(:fire).with(*args)
|
30
|
+
end
|
31
|
+
def should_not_fire(*args)
|
32
|
+
if args.empty?
|
33
|
+
@kernel.should_not_receive(:fire)
|
34
|
+
else
|
35
|
+
@kernel.should_not_receive(:fire).with(*args)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def __driver_class__
|
40
|
+
@__driver_class__ ||= __driver__.target_class_name.constantize
|
41
|
+
end
|
42
|
+
|
43
|
+
def __driver_object__
|
44
|
+
unless @__driver_object__
|
45
|
+
@__driver_object__ = __driver_class__.new
|
46
|
+
__driver_class__.stub(:new).and_return(@__driver_object__)
|
47
|
+
end
|
48
|
+
@__driver_object__
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'tengine/rspec'
|
3
|
+
|
4
|
+
# イベントドライバのテストのためのメソッドを追加するモジュールです。
|
5
|
+
# includeしてお使いください。
|
6
|
+
module Tengine::RSpec::Extension
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def target_dsl(dsl_path)
|
11
|
+
before do
|
12
|
+
Tengine::Core::Driver.delete_all
|
13
|
+
Tengine::Core::Session.delete_all
|
14
|
+
@__dsl_path__ = dsl_path
|
15
|
+
@__config__ = Tengine::Core::Config::Core.new({
|
16
|
+
:tengined => { :load_path => @__dsl_path__ },
|
17
|
+
})
|
18
|
+
@__bootstrap__ = Tengine::Core::Bootstrap.new(@__config__)
|
19
|
+
@__kernel__ = @__bootstrap__.kernel
|
20
|
+
@__kernel__.bind
|
21
|
+
@__kernel__.evaluate
|
22
|
+
# @__bootstrap__.load_dsl
|
23
|
+
# @__kernel__ = Tengine::Core::Kernel.new(@__config__)
|
24
|
+
# @__kernel__.bind
|
25
|
+
@__tengine__ = Tengine::RSpec::ContextWrapper.new(@__kernel__)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def driver(driver_name)
|
30
|
+
before do
|
31
|
+
@__driver__ = Tengine::Core::Driver.first(:conditions => {:name => driver_name})
|
32
|
+
if @__driver__
|
33
|
+
session = @__driver__.session
|
34
|
+
@__session__ = Tengine::Core::SessionWrapper.new(session)
|
35
|
+
@__tengine__.__driver__ = @__driver__
|
36
|
+
else
|
37
|
+
raise "No driver named ``#{driver_name}'' was found."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module InstanceMethods
|
44
|
+
def session
|
45
|
+
@__session__
|
46
|
+
end
|
47
|
+
|
48
|
+
def tengine
|
49
|
+
@__tengine__
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|