Skip to content

Commit b7f4ee9

Browse files
committed
add redis task queue support and improve docs
1 parent 3de99cb commit b7f4ee9

File tree

11 files changed

+157
-9
lines changed

11 files changed

+157
-9
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,4 @@ prime/
7373
*.snap
7474
*.snap-build
7575
*_source.tar.bz2
76+
.DS_Store

custom/conf/app.ini.sample

+5
Original file line numberDiff line numberDiff line change
@@ -716,3 +716,8 @@ IS_INPUT_FILE = false
716716
ENABLED = false
717717
; If you want to add authorization, specify a token here
718718
TOKEN =
719+
720+
[task]
721+
QUEUE_TYPE = redis
722+
QUEUE_LENGTH = 1000
723+
QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+7
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,15 @@ Two special environment variables are passed to the render command:
401401
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links.
402402
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths.
403403

404+
## Task (`task`)
405+
406+
- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`.
407+
- `QUEUE_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`.
408+
- `QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: Task queue connction string, available only when `QUEUE_TYPE` is `redis`. If there is a password of redis, use `addrs=127.0.0.1:6379 password=123 db=0`.
409+
404410
## Other (`other`)
405411

406412
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
407413
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea version information in the footer.
408414
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
415+

docs/content/doc/advanced/config-cheat-sheet.zh-cn.md

+4
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,11 @@ IS_INPUT_FILE = false
234234
- RENDER_COMMAND: 工具的命令行命令及参数。
235235
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。
236236

237+
## Task (`task`)
237238

239+
- `QUEUE_TYPE`: **channel**: 任务队列类型,可以为 `channel``redis`
240+
- `QUEUE_LENGTH`: **1000**: 任务队列长度,当 `QUEUE_TYPE``channel` 时有效。
241+
- `QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: 任务队列连接字符串,当 `QUEUE_TYPE``redis` 时有效。如果redis有密码,则可以 `addrs=127.0.0.1:6379 password=123 db=0`
238242

239243
## Other (`other`)
240244

modules/setting/indexer.go

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
const (
1414
LevelQueueType = "levelqueue"
1515
ChannelQueueType = "channel"
16+
RedisQueueType = "redis"
1617
)
1718

1819
var (

modules/setting/task.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,19 @@ package setting
77
var (
88
// Task settings
99
Task = struct {
10-
QueueType string
11-
QueueLength int
10+
QueueType string
11+
QueueLength int
12+
QueueConnStr string
1213
}{
13-
QueueType: ChannelQueueType,
14-
QueueLength: 1000,
14+
QueueType: ChannelQueueType,
15+
QueueLength: 1000,
16+
QueueConnStr: "addrs=127.0.0.1:6379 db=0",
1517
}
1618
)
1719

1820
func newTaskService() {
1921
sec := Cfg.Section("task")
2022
Task.QueueType = sec.Key("QUEUE_TYPE").MustString(ChannelQueueType)
2123
Task.QueueLength = sec.Key("QUEUE_LENGTH").MustInt(1000)
24+
Task.QueueConnStr = sec.Key("QUEUE_CONN_STR").MustString("addrs=127.0.0.1:6379 db=0")
2225
}

modules/task/queue_redis.go

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package task
6+
7+
import (
8+
"encoding/json"
9+
"errors"
10+
"strconv"
11+
"strings"
12+
"time"
13+
14+
"code.gitea.io/gitea/models"
15+
"code.gitea.io/gitea/modules/log"
16+
17+
"github.com/go-redis/redis"
18+
)
19+
20+
var (
21+
_ Queue = &RedisQueue{}
22+
)
23+
24+
type redisClient interface {
25+
RPush(key string, args ...interface{}) *redis.IntCmd
26+
LPop(key string) *redis.StringCmd
27+
Ping() *redis.StatusCmd
28+
}
29+
30+
// RedisQueue redis queue
31+
type RedisQueue struct {
32+
client redisClient
33+
queueName string
34+
}
35+
36+
func parseConnStr(connStr string) (addrs, password string, dbIdx int, err error) {
37+
fields := strings.Fields(connStr)
38+
for _, f := range fields {
39+
items := strings.SplitN(f, "=", 2)
40+
if len(items) < 2 {
41+
continue
42+
}
43+
switch strings.ToLower(items[0]) {
44+
case "addrs":
45+
addrs = items[1]
46+
case "password":
47+
password = items[1]
48+
case "db":
49+
dbIdx, err = strconv.Atoi(items[1])
50+
if err != nil {
51+
return
52+
}
53+
}
54+
}
55+
return
56+
}
57+
58+
// NewRedisQueue creates single redis or cluster redis queue
59+
func NewRedisQueue(addrs string, password string, dbIdx int) (*RedisQueue, error) {
60+
dbs := strings.Split(addrs, ",")
61+
var queue = RedisQueue{
62+
queueName: "task_queue",
63+
}
64+
if len(dbs) == 0 {
65+
return nil, errors.New("no redis host found")
66+
} else if len(dbs) == 1 {
67+
queue.client = redis.NewClient(&redis.Options{
68+
Addr: strings.TrimSpace(dbs[0]), // use default Addr
69+
Password: password, // no password set
70+
DB: dbIdx, // use default DB
71+
})
72+
} else {
73+
// cluster will ignore db
74+
queue.client = redis.NewClusterClient(&redis.ClusterOptions{
75+
Addrs: dbs,
76+
Password: password,
77+
})
78+
}
79+
if err := queue.client.Ping().Err(); err != nil {
80+
return nil, err
81+
}
82+
return &queue, nil
83+
}
84+
85+
func (r *RedisQueue) Run() error {
86+
for {
87+
bs, err := r.client.LPop(r.queueName).Bytes()
88+
if err != nil {
89+
if err != redis.Nil {
90+
log.Error(4, "LPop failed: %v", err)
91+
}
92+
time.Sleep(time.Millisecond * 100)
93+
continue
94+
}
95+
96+
var task models.Task
97+
err = json.Unmarshal(bs, &task)
98+
if err != nil {
99+
log.Error(4, "Unmarshal task failed: %s", err.Error())
100+
} else {
101+
err = Run(&task)
102+
if err != nil {
103+
log.Error(4, "Run task failed: %s", err.Error())
104+
}
105+
}
106+
107+
time.Sleep(time.Millisecond * 100)
108+
}
109+
return nil
110+
}
111+
112+
// Push implements Queue
113+
func (r *RedisQueue) Push(task *models.Task) error {
114+
bs, err := json.Marshal(task)
115+
if err != nil {
116+
return err
117+
}
118+
return r.client.RPush(r.queueName, bs).Err()
119+
}

modules/task/task.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,17 @@ func Init() error {
3131
switch setting.Task.QueueType {
3232
case setting.ChannelQueueType:
3333
taskQueue = NewChannelQueue(setting.Task.QueueLength)
34+
case setting.RedisQueueType:
35+
addrs, pass, idx, err := parseConnStr(setting.Task.QueueConnStr)
36+
if err != nil {
37+
return err
38+
}
39+
taskQueue, err = NewRedisQueue(addrs, pass, idx)
40+
if err != nil {
41+
return err
42+
}
3443
default:
35-
return fmt.Errorf("Unsupported indexer queue type: %v", setting.Indexer.IssueIndexerQueueType)
44+
return fmt.Errorf("Unsupported task queue type: %v", setting.Task.QueueType)
3645
}
3746

3847
go taskQueue.Run()

public/img/loading.png

-14.3 KB
Loading

public/js/index.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -229,15 +229,14 @@ function updateIssuesMeta(url, action, issueIds, elementId) {
229229
},
230230
success: resolve
231231
})
232-
}
232+
})
233233
}
234234

235235
function initRepoStatusChecker() {
236-
console.log("initRepoStatusChecker")
237236
var migrating = $("#repo_migrating");
238237
if (migrating) {
239238
var repo_name = migrating.attr('repo');
240-
if (typeof repo_nane === 'undefined') {
239+
if (typeof repo_name === 'undefined') {
241240
return
242241
}
243242
$.ajax({

templates/repo/migrating.tmpl

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
{{template "base/alert" .}}
88
<div class="home">
99
<div class="ui stackable middle very relaxed page grid">
10-
<div id="reop_migrating" class="sixteen wide center aligned centered column" repo="{{.Repo.Repository.FullName}}">
10+
<div id="repo_migrating" class="sixteen wide center aligned centered column" repo="{{.Repo.Repository.FullName}}">
1111
<div>
1212
<img src="{{AppSubUrl}}/img/loading.png"/>
1313
</div>

0 commit comments

Comments
 (0)