Skip to content

Commit 6f9c278

Browse files
authored
Rewrite queue (#24505)
# ⚠️ Breaking Many deprecated queue config options are removed (actually, they should have been removed in 1.18/1.19). If you see the fatal message when starting Gitea: "Please update your app.ini to remove deprecated config options", please follow the error messages to remove these options from your app.ini. Example: ``` 2023/05/06 19:39:22 [E] Removed queue option: `[indexer].ISSUE_INDEXER_QUEUE_TYPE`. Use new options in `[queue.issue_indexer]` 2023/05/06 19:39:22 [E] Removed queue option: `[indexer].UPDATE_BUFFER_LEN`. Use new options in `[queue.issue_indexer]` 2023/05/06 19:39:22 [F] Please update your app.ini to remove deprecated config options ``` Many options in `[queue]` are are dropped, including: `WRAP_IF_NECESSARY`, `MAX_ATTEMPTS`, `TIMEOUT`, `WORKERS`, `BLOCK_TIMEOUT`, `BOOST_TIMEOUT`, `BOOST_WORKERS`, they can be removed from app.ini. # The problem The old queue package has some legacy problems: * complexity: I doubt few people could tell how it works. * maintainability: Too many channels and mutex/cond are mixed together, too many different structs/interfaces depends each other. * stability: due to the complexity & maintainability, sometimes there are strange bugs and difficult to debug, and some code doesn't have test (indeed some code is difficult to test because a lot of things are mixed together). * general applicability: although it is called "queue", its behavior is not a well-known queue. * scalability: it doesn't seem easy to make it work with a cluster without breaking its behaviors. It came from some very old code to "avoid breaking", however, its technical debt is too heavy now. It's a good time to introduce a better "queue" package. # The new queue package It keeps using old config and concept as much as possible. * It only contains two major kinds of concepts: * The "base queue": channel, levelqueue, redis * They have the same abstraction, the same interface, and they are tested by the same testing code. * The "WokerPoolQueue", it uses the "base queue" to provide "worker pool" function, calls the "handler" to process the data in the base queue. * The new code doesn't do "PushBack" * Think about a queue with many workers, the "PushBack" can't guarantee the order for re-queued unhandled items, so in new code it just does "normal push" * The new code doesn't do "pause/resume" * The "pause/resume" was designed to handle some handler's failure: eg: document indexer (elasticsearch) is down * If a queue is paused for long time, either the producers blocks or the new items are dropped. * The new code doesn't do such "pause/resume" trick, it's not a common queue's behavior and it doesn't help much. * If there are unhandled items, the "push" function just blocks for a few seconds and then re-queue them and retry. * The new code doesn't do "worker booster" * Gitea's queue's handlers are light functions, the cost is only the go-routine, so it doesn't make sense to "boost" them. * The new code only use "max worker number" to limit the concurrent workers. * The new "Push" never blocks forever * Instead of creating more and more blocking goroutines, return an error is more friendly to the server and to the end user. There are more details in code comments: eg: the "Flush" problem, the strange "code.index" hanging problem, the "immediate" queue problem. Almost ready for review. TODO: * [x] add some necessary comments during review * [x] add some more tests if necessary * [x] update documents and config options * [x] test max worker / active worker * [x] re-run the CI tasks to see whether any test is flaky * [x] improve the `handleOldLengthConfiguration` to provide more friendly messages * [x] fine tune default config values (eg: length?) ## Code coverage: ![image](https://user-images.githubusercontent.com/2114189/236620635-55576955-f95d-4810-b12f-879026a3afdf.png)
1 parent cb700ae commit 6f9c278

File tree

100 files changed

+2481
-6843
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+2481
-6843
lines changed

cmd/hook.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"code.gitea.io/gitea/modules/private"
1919
repo_module "code.gitea.io/gitea/modules/repository"
2020
"code.gitea.io/gitea/modules/setting"
21-
"code.gitea.io/gitea/modules/util"
2221

2322
"github.com/urfave/cli"
2423
)
@@ -141,7 +140,7 @@ func (d *delayWriter) Close() error {
141140
if d == nil {
142141
return nil
143142
}
144-
stopped := util.StopTimer(d.timer)
143+
stopped := d.timer.Stop()
145144
if stopped || d.buf == nil {
146145
return nil
147146
}

custom/conf/app.example.ini

+2-47
Original file line numberDiff line numberDiff line change
@@ -926,12 +926,6 @@ ROUTER = console
926926
;; Global limit of repositories per user, applied at creation time. -1 means no limit
927927
;MAX_CREATION_LIMIT = -1
928928
;;
929-
;; Mirror sync queue length, increase if mirror syncing starts hanging (DEPRECATED: please use [queue.mirror] LENGTH instead)
930-
;MIRROR_QUEUE_LENGTH = 1000
931-
;;
932-
;; Patch test queue length, increase if pull request patch testing starts hanging (DEPRECATED: please use [queue.pr_patch_checker] LENGTH instead)
933-
;PULL_REQUEST_QUEUE_LENGTH = 1000
934-
;;
935929
;; Preferred Licenses to place at the top of the List
936930
;; The name here must match the filename in options/license or custom/options/license
937931
;PREFERRED_LICENSES = Apache License 2.0,MIT License
@@ -1376,22 +1370,6 @@ ROUTER = console
13761370
;; Set to -1 to disable timeout.
13771371
;STARTUP_TIMEOUT = 30s
13781372
;;
1379-
;; Issue indexer queue, currently support: channel, levelqueue or redis, default is levelqueue (deprecated - use [queue.issue_indexer])
1380-
;ISSUE_INDEXER_QUEUE_TYPE = levelqueue; **DEPRECATED** use settings in `[queue.issue_indexer]`.
1381-
;;
1382-
;; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the path where the queue will be saved.
1383-
;; This can be overridden by `ISSUE_INDEXER_QUEUE_CONN_STR`.
1384-
;; default is queues/common
1385-
;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
1386-
;;
1387-
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
1388-
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of
1389-
;; the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`.
1390-
;ISSUE_INDEXER_QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"; **DEPRECATED** use settings in `[queue.issue_indexer]`.
1391-
;;
1392-
;; Batch queue number, default is 20
1393-
;ISSUE_INDEXER_QUEUE_BATCH_NUMBER = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
1394-
13951373
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13961374
;; Repository Indexer settings
13971375
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1418,8 +1396,6 @@ ROUTER = console
14181396
;; A comma separated list of glob patterns to exclude from the index; ; default is empty
14191397
;REPO_INDEXER_EXCLUDE =
14201398
;;
1421-
;;
1422-
;UPDATE_BUFFER_LEN = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
14231399
;MAX_FILE_SIZE = 1048576
14241400

14251401
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1441,45 +1417,24 @@ ROUTER = console
14411417
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
14421418
;;
14431419
;; Default queue length before a channel queue will block
1444-
;LENGTH = 20
1420+
;LENGTH = 100
14451421
;;
14461422
;; Batch size to send for batched queues
14471423
;BATCH_LENGTH = 20
14481424
;;
14491425
;; Connection string for redis queues this will store the redis connection string.
14501426
;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb
14511427
;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`.
1452-
;CONN_STR = "addrs=127.0.0.1:6379 db=0"
1428+
;CONN_STR = "redis://127.0.0.1:6379/0"
14531429
;;
14541430
;; Provides the suffix of the default redis/disk queue name - specific queues can be overridden within in their [queue.name] sections.
14551431
;QUEUE_NAME = "_queue"
14561432
;;
14571433
;; Provides the suffix of the default redis/disk unique queue set name - specific queues can be overridden within in their [queue.name] sections.
14581434
;SET_NAME = "_unique"
14591435
;;
1460-
;; If the queue cannot be created at startup - level queues may need a timeout at startup - wrap the queue:
1461-
;WRAP_IF_NECESSARY = true
1462-
;;
1463-
;; Attempt to create the wrapped queue at max
1464-
;MAX_ATTEMPTS = 10
1465-
;;
1466-
;; Timeout queue creation
1467-
;TIMEOUT = 15m30s
1468-
;;
1469-
;; Create a pool with this many workers
1470-
;WORKERS = 0
1471-
;;
14721436
;; Dynamically scale the worker pool to at this many workers
14731437
;MAX_WORKERS = 10
1474-
;;
1475-
;; Add boost workers when the queue blocks for BLOCK_TIMEOUT
1476-
;BLOCK_TIMEOUT = 1s
1477-
;;
1478-
;; Remove the boost workers after BOOST_TIMEOUT
1479-
;BOOST_TIMEOUT = 5m
1480-
;;
1481-
;; During a boost add BOOST_WORKERS
1482-
;BOOST_WORKERS = 1
14831438

14841439
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14851440
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

+5-39
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
8989
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: Default private when creating a new repository with push-to-create.
9090
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
9191
`-1` means no limit.
92-
- `PULL_REQUEST_QUEUE_LENGTH`: **1000**: Length of pull request patch test queue, make it. **DEPRECATED** use `LENGTH` in `[queue.pr_patch_checker]`.
93-
as large as possible. Use caution when editing this value.
94-
- `MIRROR_QUEUE_LENGTH`: **1000**: Patch test queue length, increase if pull request patch
95-
testing starts hanging. **DEPRECATED** use `LENGTH` in `[queue.mirror]`.
9692
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
9793
the top of the list. Name must match file name in options/license or custom/options/license.
9894
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
@@ -465,11 +461,6 @@ relation to port exhaustion.
465461
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch, or meilisearch. i.e. http://elastic:changeme@localhost:9200
466462
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
467463
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
468-
- The next 4 configuration values are deprecated and should be set in `queue.issue_indexer` however are kept for backwards compatibility:
469-
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: Issue indexer queue, currently supports:`channel`, `levelqueue`, `redis`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
470-
- `ISSUE_INDEXER_QUEUE_DIR`: **queues/common**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the path where the queue will be saved. **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
471-
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string. When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
472-
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number. **DEPRECATED** use settings in `[queue.issue_indexer]`.
473464

474465
- `REPO_INDEXER_ENABLED`: **false**: Enables code search (uses a lot of disk space, about 6 times more than the repository size).
475466
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch`.
@@ -480,31 +471,21 @@ relation to port exhaustion.
480471
- `REPO_INDEXER_INCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **include** in the index. Use `**.txt` to match any files with .txt extension. An empty list means include all files.
481472
- `REPO_INDEXER_EXCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **exclude** from the index. Files that match this list will not be indexed, even if they match in `REPO_INDEXER_INCLUDE`.
482473
- `REPO_INDEXER_EXCLUDE_VENDORED`: **true**: Exclude vendored files from index.
483-
- `UPDATE_BUFFER_LEN`: **20**: Buffer length of index request. **DEPRECATED** use settings in `[queue.issue_indexer]`.
484474
- `MAX_FILE_SIZE`: **1048576**: Maximum size in bytes of files to be indexed.
485475
- `STARTUP_TIMEOUT`: **30s**: If the indexer takes longer than this timeout to start - fail. (This timeout will be added to the hammer time above for child processes - as bleve will not start until the previous parent is shutdown.) Set to -1 to never timeout.
486476

487477
## Queue (`queue` and `queue.*`)
488478

489479
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
490480

491-
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel` (uses a LevelDB internally), `channel`, `level`, `redis`, `dummy`
492-
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for individual queues can be set in `queue.name` sections but will default to `DATADIR/`**`common`**. (Previously each queue would default to `DATADIR/`**`name`**.) Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
493-
- `LENGTH`: **20**: Maximal queue size before channel queues block
481+
- `TYPE`: **level**: General queue type, currently support: `level` (uses a LevelDB internally), `channel`, `redis`, `dummy`. Invalid types are treated as `level`.
482+
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
483+
- `LENGTH`: **100**: Maximal queue size before channel queues block
494484
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
495-
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
485+
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
496486
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
497-
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to
498-
**`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
499-
- `WRAP_IF_NECESSARY`: **true**: Will wrap queues with a timeoutable queue if the selected queue is not ready to be created - (Only relevant for the level queue.)
500-
- `MAX_ATTEMPTS`: **10**: Maximum number of attempts to create the wrapped queue
501-
- `TIMEOUT`: **GRACEFUL_HAMMER_TIME + 30s**: Timeout the creation of the wrapped queue if it takes longer than this to create.
502-
- Queues by default come with a dynamically scaling worker pool. The following settings configure this:
503-
- `WORKERS`: **0**: Number of initial workers for the queue.
487+
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to **`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
504488
- `MAX_WORKERS`: **10**: Maximum number of worker go-routines for the queue.
505-
- `BLOCK_TIMEOUT`: **1s**: If the queue blocks for this time, boost the number of workers - the `BLOCK_TIMEOUT` will then be doubled before boosting again whilst the boost is ongoing.
506-
- `BOOST_TIMEOUT`: **5m**: Boost workers will timeout after this long.
507-
- `BOOST_WORKERS`: **1**: This many workers will be added to the worker pool if there is a boost.
508489

509490
Gitea creates the following non-unique queues:
510491

@@ -522,21 +503,6 @@ And the following unique queues:
522503
- `mirror`
523504
- `pr_patch_checker`
524505

525-
Certain queues have defaults that override the defaults set in `[queue]` (this occurs mostly to support older configuration):
526-
527-
- `[queue.issue_indexer]`
528-
- `TYPE` this will default to `[queue]` `TYPE` if it is set but if not it will appropriately convert `[indexer]` `ISSUE_INDEXER_QUEUE_TYPE` if that is set.
529-
- `LENGTH` will default to `[indexer]` `UPDATE_BUFFER_LEN` if that is set.
530-
- `BATCH_LENGTH` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_BATCH_NUMBER` if that is set.
531-
- `DATADIR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_DIR` if that is set.
532-
- `CONN_STR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_CONN_STR` if that is set.
533-
- `[queue.mailer]`
534-
- `LENGTH` will default to **100** or whatever `[mailer]` `SEND_BUFFER_LEN` is.
535-
- `[queue.pr_patch_checker]`
536-
- `LENGTH` will default to **1000** or whatever `[repository]` `PULL_REQUEST_QUEUE_LENGTH` is.
537-
- `[queue.mirror]`
538-
- `LENGTH` will default to **1000** or whatever `[repository]` `MIRROR_QUEUE_LENGTH` is.
539-
540506
## Admin (`admin`)
541507

542508
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled

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

-6
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ menu:
4343
- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private``public`。默认值是 `last`表示用户最后创建的Repo的选择。
4444
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库.
4545
- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。
46-
- `PULL_REQUEST_QUEUE_LENGTH`: 小心:合并请求测试队列的长度,尽量放大。
4746

4847
### Repository - Release (`repository.release`)
4948

@@ -111,18 +110,13 @@ menu:
111110
- `ISSUE_INDEXER_CONN_STR`: ****: 工单索引连接字符串,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
112111
- `ISSUE_INDEXER_NAME`: **gitea_issues**: 工单索引名称,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。
113112
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: 工单索引文件存放路径,当索引类型为 `bleve` 时有效。
114-
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: 工单索引队列类型,当前支持 `channel``levelqueue``redis`
115-
- `ISSUE_INDEXER_QUEUE_DIR`: **indexers/issues.queue**: 当 `ISSUE_INDEXER_QUEUE_TYPE``levelqueue` 时,保存索引队列的磁盘路径。
116-
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: 当 `ISSUE_INDEXER_QUEUE_TYPE``redis` 时,保存Redis队列的连接字符串。
117-
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: 队列处理中批量提交数量。
118113

119114
- `REPO_INDEXER_ENABLED`: **false**: 是否启用代码搜索(启用后会占用比较大的磁盘空间,如果是bleve可能需要占用约6倍存储空间)。
120115
- `REPO_INDEXER_TYPE`: **bleve**: 代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`
121116
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: 用于代码搜索的索引文件路径。
122117
- `REPO_INDEXER_CONN_STR`: ****: 代码搜索引擎连接字符串,当 `REPO_INDEXER_TYPE``elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
123118
- `REPO_INDEXER_NAME`: **gitea_codes**: 代码搜索引擎的名字,当 `REPO_INDEXER_TYPE``elasticsearch` 时有效。
124119

125-
- `UPDATE_BUFFER_LEN`: **20**: 代码索引请求的缓冲区长度。
126120
- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。
127121

128122
## Security (`security`)

docs/content/doc/administration/repo-indexer.en-us.md

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ Gitea can search through the files of the repositories by enabling this function
3030
; ...
3131
REPO_INDEXER_ENABLED = true
3232
REPO_INDEXER_PATH = indexers/repos.bleve
33-
UPDATE_BUFFER_LEN = 20
3433
MAX_FILE_SIZE = 1048576
3534
REPO_INDEXER_INCLUDE =
3635
REPO_INDEXER_EXCLUDE = resources/bin/**

0 commit comments

Comments
 (0)