Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
二次元的罪恶王冠
beego
提交
43560ded
B
beego
项目概览
二次元的罪恶王冠
/
beego
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
B
beego
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
43560ded
编写于
10月 05, 2020
作者:
M
Ming Deng
提交者:
GitHub
10月 05, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4246 from jianzhiyao/frt/seperate_orm_alone
seperate orm alone & deadlock in task module
上级
b89d9511
c435d231
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
182 addition
and
74 deletion
+182
-74
pkg/adapter/toolbox/task.go
pkg/adapter/toolbox/task.go
+5
-0
pkg/adapter/toolbox/task_test.go
pkg/adapter/toolbox/task_test.go
+4
-0
pkg/client/orm/filter/prometheus/filter.go
pkg/client/orm/filter/prometheus/filter.go
+9
-13
pkg/client/orm/filter/prometheus/filter_test.go
pkg/client/orm/filter/prometheus/filter_test.go
+7
-6
pkg/task/govenor_command.go
pkg/task/govenor_command.go
+3
-3
pkg/task/task.go
pkg/task/task.go
+117
-43
pkg/task/task_test.go
pkg/task/task_test.go
+37
-9
未找到文件。
pkg/adapter/toolbox/task.go
浏览文件 @
43560ded
...
...
@@ -212,6 +212,11 @@ func DeleteTask(taskname string) {
task
.
DeleteTask
(
taskname
)
}
// ClearTask clear all tasks
func
ClearTask
()
{
task
.
ClearTask
()
}
// MapSorter sort map for tasker
type
MapSorter
task
.
MapSorter
...
...
pkg/adapter/toolbox/task_test.go
浏览文件 @
43560ded
...
...
@@ -22,6 +22,8 @@ import (
)
func
TestParse
(
t
*
testing
.
T
)
{
defer
ClearTask
()
tk
:=
NewTask
(
"taska"
,
"0/30 * * * * *"
,
func
()
error
{
fmt
.
Println
(
"hello world"
);
return
nil
})
err
:=
tk
.
Run
()
if
err
!=
nil
{
...
...
@@ -34,6 +36,8 @@ func TestParse(t *testing.T) {
}
func
TestSpec
(
t
*
testing
.
T
)
{
defer
ClearTask
()
wg
:=
&
sync
.
WaitGroup
{}
wg
.
Add
(
2
)
tk1
:=
NewTask
(
"tk1"
,
"0 12 * * * *"
,
func
()
error
{
fmt
.
Println
(
"tk1"
);
return
nil
})
...
...
pkg/client/orm/filter/prometheus/filter.go
浏览文件 @
43560ded
...
...
@@ -23,7 +23,6 @@ import (
"github.com/prometheus/client_golang/prometheus"
"github.com/astaxie/beego/pkg/client/orm"
"github.com/astaxie/beego/pkg/server/web"
)
// FilterChainBuilder is an extension point,
...
...
@@ -35,27 +34,24 @@ import (
// actually we only records metrics of invoking "QueryTable" and "QueryTableWithCtx"
type
FilterChainBuilder
struct
{
summaryVec
prometheus
.
ObserverVec
AppName
string
ServerName
string
RunMode
string
}
func
NewFilterChainBuilder
()
*
FilterChainBuilder
{
summaryVec
:=
prometheus
.
NewSummaryVec
(
prometheus
.
SummaryOpts
{
func
(
builder
*
FilterChainBuilder
)
FilterChain
(
next
orm
.
Filter
)
orm
.
Filter
{
builder
.
summaryVec
=
prometheus
.
NewSummaryVec
(
prometheus
.
SummaryOpts
{
Name
:
"beego"
,
Subsystem
:
"orm_operation"
,
ConstLabels
:
map
[
string
]
string
{
"server"
:
web
.
BConfig
.
ServerName
,
"env"
:
web
.
BConfig
.
RunMode
,
"appname"
:
web
.
BConfig
.
AppName
,
"server"
:
builder
.
ServerName
,
"env"
:
builder
.
RunMode
,
"appname"
:
builder
.
AppName
,
},
Help
:
"The statics info for orm operation"
,
},
[]
string
{
"method"
,
"name"
,
"duration"
,
"insideTx"
,
"txName"
})
prometheus
.
MustRegister
(
summaryVec
)
return
&
FilterChainBuilder
{
summaryVec
:
summaryVec
,
}
}
func
(
builder
*
FilterChainBuilder
)
FilterChain
(
next
orm
.
Filter
)
orm
.
Filter
{
return
func
(
ctx
context
.
Context
,
inv
*
orm
.
Invocation
)
[]
interface
{}
{
startTime
:=
time
.
Now
()
res
:=
next
(
ctx
,
inv
)
...
...
pkg/client/orm/filter/prometheus/filter_test.go
浏览文件 @
43560ded
...
...
@@ -24,14 +24,15 @@ import (
"github.com/astaxie/beego/pkg/client/orm"
)
func
TestFilterChainBuilder_FilterChain
(
t
*
testing
.
T
)
{
builder
:=
NewFilterChainBuilder
()
assert
.
NotNil
(
t
,
builder
.
summaryVec
)
filter
:=
builder
.
FilterChain
(
func
(
ctx
context
.
Context
,
inv
*
orm
.
Invocation
)
[]
interface
{}
{
func
TestFilterChainBuilder_FilterChain1
(
t
*
testing
.
T
)
{
next
:=
func
(
ctx
context
.
Context
,
inv
*
orm
.
Invocation
)
[]
interface
{}
{
inv
.
Method
=
"coming"
return
[]
interface
{}{}
})
}
builder
:=
&
FilterChainBuilder
{}
filter
:=
builder
.
FilterChain
(
next
)
assert
.
NotNil
(
t
,
builder
.
summaryVec
)
assert
.
NotNil
(
t
,
filter
)
inv
:=
&
orm
.
Invocation
{}
...
...
pkg/task/govenor_command.go
浏览文件 @
43560ded
...
...
@@ -28,8 +28,8 @@ type listTaskCommand struct {
}
func
(
l
*
listTaskCommand
)
Execute
(
params
...
interface
{})
*
governor
.
Result
{
resultList
:=
make
([][]
string
,
0
,
len
(
A
dminTaskList
))
for
tname
,
tk
:=
range
A
dminTaskList
{
resultList
:=
make
([][]
string
,
0
,
len
(
globalTaskManager
.
a
dminTaskList
))
for
tname
,
tk
:=
range
globalTaskManager
.
a
dminTaskList
{
result
:=
[]
string
{
template
.
HTMLEscapeString
(
tname
),
template
.
HTMLEscapeString
(
tk
.
GetSpec
(
nil
)),
...
...
@@ -65,7 +65,7 @@ func (r *runTaskCommand) Execute(params ...interface{}) *governor.Result {
}
}
if
t
,
ok
:=
A
dminTaskList
[
tn
];
ok
{
if
t
,
ok
:=
globalTaskManager
.
a
dminTaskList
[
tn
];
ok
{
err
:=
t
.
Run
(
context
.
Background
())
if
err
!=
nil
{
return
&
governor
.
Result
{
...
...
pkg/task/task.go
浏览文件 @
43560ded
...
...
@@ -31,13 +31,28 @@ type bounds struct {
names
map
[
string
]
uint
}
// The bounds for each field.
var
(
AdminTaskList
map
[
string
]
Tasker
type
taskManager
struct
{
adminTaskList
map
[
string
]
Tasker
taskLock
sync
.
RWMutex
stop
chan
bool
changed
chan
bool
isstart
bool
started
bool
}
func
newTaskManager
()
*
taskManager
{
return
&
taskManager
{
adminTaskList
:
make
(
map
[
string
]
Tasker
),
taskLock
:
sync
.
RWMutex
{},
stop
:
make
(
chan
bool
),
changed
:
make
(
chan
bool
),
started
:
false
,
}
}
// The bounds for each field.
var
(
globalTaskManager
*
taskManager
seconds
=
bounds
{
0
,
59
,
nil
}
minutes
=
bounds
{
0
,
59
,
nil
}
hours
=
bounds
{
0
,
23
,
nil
}
...
...
@@ -398,32 +413,58 @@ func dayMatches(s *Schedule, t time.Time) bool {
// StartTask start all tasks
func
StartTask
()
{
taskLock
.
Lock
()
defer
taskLock
.
Unlock
()
if
isstart
{
globalTaskManager
.
StartTask
()
}
// StopTask stop all tasks
func
StopTask
()
{
globalTaskManager
.
StopTask
()
}
// AddTask add task with name
func
AddTask
(
taskName
string
,
t
Tasker
)
{
globalTaskManager
.
AddTask
(
taskName
,
t
)
}
// DeleteTask delete task with name
func
DeleteTask
(
taskName
string
)
{
globalTaskManager
.
DeleteTask
(
taskName
)
}
// ClearTask clear all tasks
func
ClearTask
()
{
globalTaskManager
.
ClearTask
()
}
// StartTask start all tasks
func
(
m
*
taskManager
)
StartTask
()
{
m
.
taskLock
.
Lock
()
defer
m
.
taskLock
.
Unlock
()
if
m
.
started
{
// If already started, no need to start another goroutine.
return
}
isstart
=
true
m
.
started
=
true
registerCommands
()
go
run
()
go
m
.
run
()
}
func
run
()
{
func
(
m
*
taskManager
)
run
()
{
now
:=
time
.
Now
()
.
Local
()
for
_
,
t
:=
range
A
dminTaskList
{
for
_
,
t
:=
range
m
.
a
dminTaskList
{
t
.
SetNext
(
nil
,
now
)
}
for
{
// we only use RLock here because NewMapSorter copy the reference, do not change any thing
taskLock
.
RLock
()
sortList
:=
NewMapSorter
(
A
dminTaskList
)
taskLock
.
RUnlock
()
m
.
taskLock
.
RLock
()
sortList
:=
NewMapSorter
(
m
.
a
dminTaskList
)
m
.
taskLock
.
RUnlock
()
sortList
.
Sort
()
var
effective
time
.
Time
if
len
(
A
dminTaskList
)
==
0
||
sortList
.
Vals
[
0
]
.
GetNext
(
context
.
Background
())
.
IsZero
()
{
if
len
(
m
.
a
dminTaskList
)
==
0
||
sortList
.
Vals
[
0
]
.
GetNext
(
context
.
Background
())
.
IsZero
()
{
// If there are no entries yet, just sleep - it still handles new entries
// and stop requests.
effective
=
now
.
AddDate
(
10
,
0
,
0
)
...
...
@@ -442,49 +483,84 @@ func run() {
e
.
SetNext
(
nil
,
effective
)
}
continue
case
<-
changed
:
case
<-
m
.
changed
:
now
=
time
.
Now
()
.
Local
()
taskLock
.
Lock
()
for
_
,
t
:=
range
A
dminTaskList
{
m
.
taskLock
.
Lock
()
for
_
,
t
:=
range
m
.
a
dminTaskList
{
t
.
SetNext
(
nil
,
now
)
}
taskLock
.
Unlock
()
m
.
taskLock
.
Unlock
()
continue
case
<-
stop
:
case
<-
m
.
stop
:
m
.
taskLock
.
Lock
()
if
m
.
started
{
m
.
started
=
false
}
m
.
taskLock
.
Unlock
()
return
}
}
}
// StopTask stop all tasks
func
StopTask
()
{
taskLock
.
Lock
()
defer
taskLock
.
Unlock
()
if
isstart
{
isstart
=
false
stop
<-
true
}
func
(
m
*
taskManager
)
StopTask
()
{
go
func
()
{
m
.
stop
<-
true
}()
}
// AddTask add task with name
func
AddTask
(
taskname
string
,
t
Tasker
)
{
taskLock
.
Lock
()
defer
taskLock
.
Unl
ock
()
func
(
m
*
taskManager
)
AddTask
(
taskname
string
,
t
Tasker
)
{
isChanged
:=
false
m
.
taskLock
.
L
ock
()
t
.
SetNext
(
nil
,
time
.
Now
()
.
Local
())
AdminTaskList
[
taskname
]
=
t
if
isstart
{
changed
<-
true
m
.
adminTaskList
[
taskname
]
=
t
if
m
.
started
{
isChanged
=
true
}
m
.
taskLock
.
Unlock
()
if
isChanged
{
go
func
()
{
m
.
changed
<-
true
}()
}
}
// DeleteTask delete task with name
func
DeleteTask
(
taskname
string
)
{
taskLock
.
Lock
()
defer
taskLock
.
Unlock
()
delete
(
AdminTaskList
,
taskname
)
if
isstart
{
changed
<-
true
func
(
m
*
taskManager
)
DeleteTask
(
taskname
string
)
{
isChanged
:=
false
m
.
taskLock
.
Lock
()
delete
(
m
.
adminTaskList
,
taskname
)
if
m
.
started
{
isChanged
=
true
}
m
.
taskLock
.
Unlock
()
if
isChanged
{
go
func
()
{
m
.
changed
<-
true
}()
}
}
// ClearTask clear all tasks
func
(
m
*
taskManager
)
ClearTask
()
{
isChanged
:=
false
m
.
taskLock
.
Lock
()
m
.
adminTaskList
=
make
(
map
[
string
]
Tasker
)
if
m
.
started
{
isChanged
=
true
}
m
.
taskLock
.
Unlock
()
if
isChanged
{
go
func
()
{
m
.
changed
<-
true
}()
}
}
...
...
@@ -637,7 +713,5 @@ func all(r bounds) uint64 {
}
func
init
()
{
AdminTaskList
=
make
(
map
[
string
]
Tasker
)
stop
=
make
(
chan
bool
)
changed
=
make
(
chan
bool
)
globalTaskManager
=
newTaskManager
()
}
pkg/task/task_test.go
浏览文件 @
43560ded
...
...
@@ -26,6 +26,8 @@ import (
)
func
TestParse
(
t
*
testing
.
T
)
{
m
:=
newTaskManager
()
defer
m
.
ClearTask
()
tk
:=
NewTask
(
"taska"
,
"0/30 * * * * *"
,
func
(
ctx
context
.
Context
)
error
{
fmt
.
Println
(
"hello world"
)
return
nil
...
...
@@ -34,24 +36,50 @@ func TestParse(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
AddTask
(
"taska"
,
tk
)
StartTask
()
time
.
Sleep
(
6
*
time
.
Second
)
StopTask
()
m
.
AddTask
(
"taska"
,
tk
)
m
.
StartTask
()
time
.
Sleep
(
3
*
time
.
Second
)
m
.
StopTask
()
}
func
TestModifyTaskListAfterRunning
(
t
*
testing
.
T
)
{
m
:=
newTaskManager
()
defer
m
.
ClearTask
()
tk
:=
NewTask
(
"taskb"
,
"0/30 * * * * *"
,
func
(
ctx
context
.
Context
)
error
{
fmt
.
Println
(
"hello world"
)
return
nil
})
err
:=
tk
.
Run
(
nil
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
m
.
AddTask
(
"taskb"
,
tk
)
m
.
StartTask
()
go
func
()
{
m
.
DeleteTask
(
"taskb"
)
}()
go
func
()
{
m
.
AddTask
(
"taskb1"
,
tk
)
}()
time
.
Sleep
(
3
*
time
.
Second
)
m
.
StopTask
()
}
func
TestSpec
(
t
*
testing
.
T
)
{
m
:=
newTaskManager
()
defer
m
.
ClearTask
()
wg
:=
&
sync
.
WaitGroup
{}
wg
.
Add
(
2
)
tk1
:=
NewTask
(
"tk1"
,
"0 12 * * * *"
,
func
(
ctx
context
.
Context
)
error
{
fmt
.
Println
(
"tk1"
);
return
nil
})
tk2
:=
NewTask
(
"tk2"
,
"0,10,20 * * * * *"
,
func
(
ctx
context
.
Context
)
error
{
fmt
.
Println
(
"tk2"
);
wg
.
Done
();
return
nil
})
tk3
:=
NewTask
(
"tk3"
,
"0 10 * * * *"
,
func
(
ctx
context
.
Context
)
error
{
fmt
.
Println
(
"tk3"
);
wg
.
Done
();
return
nil
})
AddTask
(
"tk1"
,
tk1
)
AddTask
(
"tk2"
,
tk2
)
AddTask
(
"tk3"
,
tk3
)
StartTask
()
defer
StopTask
()
m
.
AddTask
(
"tk1"
,
tk1
)
m
.
AddTask
(
"tk2"
,
tk2
)
m
.
AddTask
(
"tk3"
,
tk3
)
m
.
StartTask
()
defer
m
.
StopTask
()
select
{
case
<-
time
.
After
(
200
*
time
.
Second
)
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录