Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
b881be73
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b881be73
编写于
9月 14, 2012
作者:
J
Jeremy Kemper
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Always run jobs using a consumer, even in synchronous & test queues, to ensure shared behavior.
上级
e08a564e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
108 addition
and
69 deletion
+108
-69
activesupport/lib/active_support/queueing.rb
activesupport/lib/active_support/queueing.rb
+49
-32
activesupport/test/queueing/synchronous_queue_test.rb
activesupport/test/queueing/synchronous_queue_test.rb
+27
-0
activesupport/test/queueing/test_queue_test.rb
activesupport/test/queueing/test_queue_test.rb
+2
-2
activesupport/test/queueing/threaded_consumer_test.rb
activesupport/test/queueing/threaded_consumer_test.rb
+30
-35
未找到文件。
activesupport/lib/active_support/queueing.rb
浏览文件 @
b881be73
...
...
@@ -2,17 +2,33 @@
require
'thread'
module
ActiveSupport
# A Queue that simply inherits from STDLIB's Queue.
Everytime
this
# queue is used, Rails automatically s
ets up a ThreadedConsumer
#
to consume it
.
# A Queue that simply inherits from STDLIB's Queue.
When
this
# queue is used, Rails automatically s
tarts a job runner in a
#
background thread
.
class
Queue
<
::
Queue
attr_writer
:consumer
def
initialize
(
consumer_options
=
{})
super
()
@consumer_options
=
consumer_options
end
def
consumer
@consumer
||=
ThreadedQueueConsumer
.
new
(
self
,
@consumer_options
)
end
# Drain the queue, running all jobs in a different thread. This method
# may not be available on production queues.
def
drain
# run the jobs in a separate thread so assumptions of synchronous
# jobs are caught in test mode.
consumer
.
drain
end
end
class
SynchronousQueue
<
::
Queue
class
SynchronousQueue
<
Queue
def
push
(
job
)
result
=
nil
Thread
.
new
{
result
=
job
.
run
}.
join
result
super
.
tap
{
drain
}
end
alias
<<
push
alias
enq
push
...
...
@@ -25,7 +41,7 @@ def push(job)
#
# Jobs are run in a separate thread to catch mistakes where code
# assumes that the job is run in the same thread.
class
TestQueue
<
::
Queue
class
TestQueue
<
Queue
# Get a list of the jobs off this queue. This method may not be
# available on production queues.
def
jobs
...
...
@@ -38,14 +54,6 @@ def jobs
def
push
(
job
)
super
Marshal
.
load
(
Marshal
.
dump
(
job
))
end
# Drain the queue, running all jobs in a different thread. This method
# may not be available on production queues.
def
drain
# run the jobs in a separate thread so assumptions of synchronous
# jobs are caught in test mode.
Thread
.
new
{
pop
.
run
until
empty?
}.
join
end
end
# A container for multiple queues. This class delegates to a default Queue
...
...
@@ -82,25 +90,17 @@ def []=(queue_name, queue)
# queue and joins the thread, which will ensure that all jobs
# are executed before the process finally dies.
class
ThreadedQueueConsumer
def
self
.
start
(
queue
,
logger
=
nil
)
new
(
queue
,
logger
).
start
def
self
.
start
(
*
args
)
new
(
*
args
).
start
end
def
initialize
(
queue
,
logger
=
nil
)
@queue
=
queue
@logger
=
logger
def
initialize
(
queue
,
options
=
{}
)
@queue
=
queue
@logger
=
options
[
:logger
]
end
def
start
@thread
=
Thread
.
new
do
while
job
=
@queue
.
pop
begin
job
.
run
rescue
Exception
=>
e
handle_exception
e
end
end
end
@thread
=
Thread
.
new
{
consume
}
self
end
...
...
@@ -109,8 +109,25 @@ def shutdown
@thread
.
join
end
def
handle_exception
(
e
)
@logger
.
error
"Job Error:
#{
e
.
message
}
\n
#{
e
.
backtrace
.
join
(
"
\n
"
)
}
"
if
@logger
def
drain
Thread
.
new
{
run
(
@queue
.
pop
)
until
@queue
.
empty?
}.
join
end
def
consume
while
job
=
@queue
.
pop
run
job
end
end
def
run
(
job
)
job
.
run
rescue
Exception
=>
exception
handle_exception
job
,
exception
end
def
handle_exception
(
job
,
exception
)
raise
unless
@logger
@logger
.
error
"Job Error:
#{
exception
.
message
}
\n
#{
exception
.
backtrace
.
join
(
"
\n
"
)
}
"
end
end
end
activesupport/test/queueing/synchronous_queue_test.rb
0 → 100644
浏览文件 @
b881be73
require
'abstract_unit'
require
'active_support/queueing'
class
SynchronousQueueTest
<
ActiveSupport
::
TestCase
class
Job
attr_reader
:ran
def
run
;
@ran
=
true
end
end
class
ExceptionRaisingJob
def
run
;
raise
end
end
def
setup
@queue
=
ActiveSupport
::
SynchronousQueue
.
new
end
def
test_runs_jobs_immediately
job
=
Job
.
new
@queue
.
push
job
assert
job
.
ran
assert_raises
RuntimeError
do
@queue
.
push
ExceptionRaisingJob
.
new
end
end
end
activesupport/test/queueing/test_queue_test.rb
浏览文件 @
b881be73
...
...
@@ -12,7 +12,7 @@ def run
end
end
def
test_drain_raises
def
test_drain_raises
_exceptions_from_running_jobs
@queue
.
push
ExceptionRaisingJob
.
new
assert_raises
(
RuntimeError
)
{
@queue
.
drain
}
end
...
...
@@ -41,8 +41,8 @@ def same_initial_id?(other_id)
end
def
test_contents
assert
@queue
.
empty?
job
=
EquivalentJob
.
new
assert
@queue
.
empty?
@queue
.
push
job
refute
@queue
.
empty?
assert_equal
job
,
@queue
.
pop
...
...
activesupport/test/queueing/threaded_consumer_test.rb
浏览文件 @
b881be73
...
...
@@ -5,7 +5,7 @@
class
TestThreadConsumer
<
ActiveSupport
::
TestCase
class
Job
attr_reader
:id
def
initialize
(
id
,
&
block
)
def
initialize
(
id
=
1
,
&
block
)
@id
=
id
@block
=
block
end
...
...
@@ -16,83 +16,78 @@ def run
end
def
setup
@queue
=
ActiveSupport
::
Queue
.
new
@logger
=
ActiveSupport
::
LogSubscriber
::
TestHelper
::
MockLogger
.
new
@
consumer
=
ActiveSupport
::
ThreadedQueueConsumer
.
start
(
@queue
,
@logger
)
@
queue
=
ActiveSupport
::
Queue
.
new
(
logger:
@logger
)
end
def
teardown
@queue
.
push
nil
@queue
.
drain
end
test
"the jobs are executed"
do
ran
=
false
job
=
Job
.
new
(
1
)
do
ran
=
true
end
job
=
Job
.
new
{
ran
=
true
}
@queue
.
push
job
sleep
0.1
@queue
.
drain
assert_equal
true
,
ran
end
test
"the jobs are not executed synchronously"
do
ran
=
false
job
=
Job
.
new
(
1
)
do
sleep
0.1
ran
=
true
end
run
,
ran
=
Queue
.
new
,
Queue
.
new
job
=
Job
.
new
{
ran
.
push
run
.
pop
}
@queue
.
consumer
.
start
@queue
.
push
job
assert_equal
false
,
ran
assert
ran
.
empty?
run
.
push
true
assert_equal
true
,
ran
.
pop
end
test
"shutting down the queue synchronously drains the jobs"
do
runnable
=
::
Queue
.
new
ran
=
false
job
=
Job
.
new
(
1
)
do
job
=
Job
.
new
do
sleep
0.1
ran
=
true
end
@queue
.
consumer
.
start
@queue
.
push
job
assert_equal
false
,
ran
@consumer
.
shutdown
@queue
.
consumer
.
shutdown
assert_equal
true
,
ran
end
test
"log job that raises an exception"
do
job
=
Job
.
new
(
1
)
do
raise
"RuntimeError: Error!"
end
job
=
Job
.
new
{
raise
"RuntimeError: Error!"
}
@queue
.
push
job
sleep
0.1
@queue
.
drain
assert_equal
1
,
@logger
.
logged
(
:error
).
size
assert_match
(
/Job Error: RuntimeError: Error!/
,
@logger
.
logged
(
:error
).
last
)
assert_match
'Job Error: RuntimeError: Error!'
,
@logger
.
logged
(
:error
).
last
end
test
"test overriding exception handling"
do
@consumer
.
shutdown
@consumer
=
Class
.
new
(
ActiveSupport
::
ThreadedQueueConsumer
)
do
attr_reader
:last_error
def
handle_exception
(
e
)
@last_error
=
e
.
message
@queue
.
consumer
.
instance_eval
do
def
handle_exception
(
job
,
exception
)
@last_error
=
exception
.
message
end
end
.
start
(
@queue
)
job
=
Job
.
new
(
1
)
do
raise
"RuntimeError: Error!"
def
last_error
@last_error
end
end
job
=
Job
.
new
{
raise
"RuntimeError: Error!"
}
@queue
.
push
job
sleep
0.1
@queue
.
drain
assert_equal
"RuntimeError: Error!"
,
@consumer
.
last_error
assert_equal
"RuntimeError: Error!"
,
@
queue
.
consumer
.
last_error
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录