Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
8356dcac
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,发现更多精彩内容 >>
提交
8356dcac
编写于
10月 01, 2016
作者:
M
Matthew Draper
提交者:
GitHub
10月 01, 2016
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #26646 from matthewd/cable-buffer
Buffer writes to the cable sockets
上级
4f2d1d6c
5d92089b
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
100 addition
and
12 deletion
+100
-12
actioncable/CHANGELOG.md
actioncable/CHANGELOG.md
+5
-0
actioncable/lib/action_cable/connection/stream.rb
actioncable/lib/action_cable/connection/stream.rb
+54
-3
actioncable/lib/action_cable/connection/stream_event_loop.rb
actioncable/lib/action_cable/connection/stream_event_loop.rb
+38
-8
actioncable/test/stubs/test_server.rb
actioncable/test/stubs/test_server.rb
+3
-1
未找到文件。
actioncable/CHANGELOG.md
浏览文件 @
8356dcac
*
Buffer writes to websocket connections, to avoid blocking threads
that could be doing more useful things.
*Matthew Draper*, *Tinco Andringa*
*
Protect against concurrent writes to a websocket connection from
multiple threads; the underlying OS write is not always threadsafe.
...
...
actioncable/lib/action_cable/connection/stream.rb
浏览文件 @
8356dcac
...
...
@@ -14,6 +14,9 @@ def initialize(event_loop, socket)
@rack_hijack_io
=
nil
@write_lock
=
Mutex
.
new
@write_head
=
nil
@write_buffer
=
Queue
.
new
end
def
each
(
&
callback
)
...
...
@@ -30,14 +33,62 @@ def shutdown
end
def
write
(
data
)
@write_lock
.
synchronize
do
return
@rack_hijack_io
.
write
(
data
)
if
@rack_hijack_io
return
@stream_send
.
call
(
data
)
if
@stream_send
if
@stream_send
return
@stream_send
.
call
(
data
)
end
if
@write_lock
.
try_lock
begin
if
@write_head
.
nil?
&&
@write_buffer
.
empty?
written
=
@rack_hijack_io
.
write_nonblock
(
data
,
exception:
false
)
case
written
when
:wait_writable
# proceed below
when
data
.
bytesize
return
data
.
bytesize
else
@write_head
=
data
.
byteslice
(
written
,
data
.
bytesize
)
@event_loop
.
writes_pending
@rack_hijack_io
return
data
.
bytesize
end
end
ensure
@write_lock
.
unlock
end
end
@write_buffer
<<
data
@event_loop
.
writes_pending
@rack_hijack_io
data
.
bytesize
rescue
EOFError
,
Errno
::
ECONNRESET
@socket_object
.
client_gone
end
def
flush_write_buffer
@write_lock
.
synchronize
do
loop
do
if
@write_head
.
nil?
return
true
if
@write_buffer
.
empty?
@write_head
=
@write_buffer
.
pop
end
written
=
@rack_hijack_io
.
write_nonblock
(
@write_head
,
exception:
false
)
case
written
when
:wait_writable
return
false
when
@write_head
.
bytesize
@write_head
=
nil
else
@write_head
=
@write_head
.
byteslice
(
written
,
@write_head
.
bytesize
)
return
false
end
end
end
end
def
receive
(
data
)
@socket_object
.
parse
(
data
)
end
...
...
actioncable/lib/action_cable/connection/stream_event_loop.rb
浏览文件 @
8356dcac
...
...
@@ -5,7 +5,7 @@ module ActionCable
module
Connection
class
StreamEventLoop
def
initialize
@nio
=
@thread
=
nil
@nio
=
@
executor
=
@
thread
=
nil
@map
=
{}
@stopping
=
false
@todo
=
Queue
.
new
...
...
@@ -20,13 +20,14 @@ def timer(interval, &block)
def
post
(
task
=
nil
,
&
block
)
task
||=
block
Concurrent
.
global_io_executor
<<
task
spawn
@executor
<<
task
end
def
attach
(
io
,
stream
)
@todo
<<
lambda
do
@map
[
io
]
=
stream
@
nio
.
register
(
io
,
:r
)
@map
[
io
]
=
@nio
.
register
(
io
,
:r
)
@
map
[
io
].
value
=
stream
end
wakeup
end
...
...
@@ -39,6 +40,15 @@ def detach(io, stream)
wakeup
end
def
writes_pending
(
io
)
@todo
<<
lambda
do
if
monitor
=
@map
[
io
]
monitor
.
interests
=
:rw
end
end
wakeup
end
def
stop
@stopping
=
true
wakeup
if
@nio
...
...
@@ -52,6 +62,13 @@ def spawn
return
if
@thread
&&
@thread
.
status
@nio
||=
NIO
::
Selector
.
new
@executor
||=
Concurrent
::
ThreadPoolExecutor
.
new
(
min_threads:
1
,
max_threads:
10
,
max_queue:
0
,
)
@thread
=
Thread
.
new
{
run
}
return
true
...
...
@@ -77,12 +94,25 @@ def run
monitors
.
each
do
|
monitor
|
io
=
monitor
.
io
stream
=
@map
[
io
]
stream
=
monitor
.
value
begin
stream
.
receive
io
.
read_nonblock
(
4096
)
rescue
IO
::
WaitReadable
next
if
monitor
.
writable?
if
stream
.
flush_write_buffer
monitor
.
interests
=
:r
end
next
unless
monitor
.
readable?
end
incoming
=
io
.
read_nonblock
(
4096
,
exception:
false
)
case
incoming
when
:wait_readable
next
when
nil
stream
.
close
else
stream
.
receive
incoming
end
rescue
# We expect one of EOFError or Errno::ECONNRESET in
# normal operation (when the client goes away). But if
...
...
actioncable/test/stubs/test_server.rb
浏览文件 @
8356dcac
...
...
@@ -28,7 +28,9 @@ def event_loop
@event_loop
||=
if
@config
.
use_faye
ActionCable
::
Connection
::
FayeEventLoop
.
new
else
ActionCable
::
Connection
::
StreamEventLoop
.
new
ActionCable
::
Connection
::
StreamEventLoop
.
new
.
tap
do
|
loop
|
loop
.
instance_variable_set
(
:@executor
,
Concurrent
.
global_io_executor
)
end
end
end
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录