2020-01-07 16:53:09 +05:30
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 23:50:29 +05:30
// SPDX-License-Identifier: MIT
2020-01-07 16:53:09 +05:30
package setting
import (
2020-01-08 20:00:58 +05:30
"path/filepath"
2021-10-17 17:13:25 +05:30
"strconv"
2020-01-07 16:53:09 +05:30
"time"
2022-10-12 10:48:26 +05:30
"code.gitea.io/gitea/modules/container"
2020-01-07 16:53:09 +05:30
"code.gitea.io/gitea/modules/log"
2021-11-17 18:04:35 +05:30
2021-10-17 17:13:25 +05:30
ini "gopkg.in/ini.v1"
2020-01-07 16:53:09 +05:30
)
// QueueSettings represent the settings for a queue from the ini
type QueueSettings struct {
2020-10-16 03:10:03 +05:30
Name string
2020-01-07 16:53:09 +05:30
DataDir string
2020-10-16 03:10:03 +05:30
QueueLength int ` ini:"LENGTH" `
2020-01-07 16:53:09 +05:30
BatchLength int
ConnectionString string
Type string
QueueName string
2020-02-03 04:49:58 +05:30
SetName string
2020-01-07 16:53:09 +05:30
WrapIfNecessary bool
MaxAttempts int
Timeout time . Duration
Workers int
MaxWorkers int
BlockTimeout time . Duration
BoostTimeout time . Duration
BoostWorkers int
}
// Queue settings
var Queue = QueueSettings { }
// GetQueueSettings returns the queue settings for the appropriately named queue
func GetQueueSettings ( name string ) QueueSettings {
2023-02-19 21:42:01 +05:30
return getQueueSettings ( CfgProvider , name )
}
func getQueueSettings ( rootCfg ConfigProvider , name string ) QueueSettings {
2020-01-07 16:53:09 +05:30
q := QueueSettings { }
2023-02-19 21:42:01 +05:30
sec := rootCfg . Section ( "queue." + name )
2020-10-16 03:10:03 +05:30
q . Name = name
2020-01-07 16:53:09 +05:30
// DataDir is not directly inheritable
2021-05-26 08:20:35 +05:30
q . DataDir = filepath . ToSlash ( filepath . Join ( Queue . DataDir , "common" ) )
2020-01-07 16:53:09 +05:30
// QueueName is not directly inheritable either
q . QueueName = name + Queue . QueueName
for _ , key := range sec . Keys ( ) {
switch key . Name ( ) {
case "DATADIR" :
q . DataDir = key . MustString ( q . DataDir )
case "QUEUE_NAME" :
q . QueueName = key . MustString ( q . QueueName )
2020-02-03 04:49:58 +05:30
case "SET_NAME" :
q . SetName = key . MustString ( q . SetName )
2020-01-07 16:53:09 +05:30
}
}
2020-02-03 04:49:58 +05:30
if len ( q . SetName ) == 0 && len ( Queue . SetName ) > 0 {
q . SetName = q . QueueName + Queue . SetName
}
2020-01-08 20:00:58 +05:30
if ! filepath . IsAbs ( q . DataDir ) {
2021-06-17 03:49:20 +05:30
q . DataDir = filepath . ToSlash ( filepath . Join ( AppDataPath , q . DataDir ) )
2020-01-07 16:53:09 +05:30
}
2020-01-29 06:31:06 +05:30
_ , _ = sec . NewKey ( "DATADIR" , q . DataDir )
2020-10-16 03:10:03 +05:30
2020-01-07 16:53:09 +05:30
// The rest are...
2020-10-16 03:10:03 +05:30
q . QueueLength = sec . Key ( "LENGTH" ) . MustInt ( Queue . QueueLength )
2020-01-07 16:53:09 +05:30
q . BatchLength = sec . Key ( "BATCH_LENGTH" ) . MustInt ( Queue . BatchLength )
q . ConnectionString = sec . Key ( "CONN_STR" ) . MustString ( Queue . ConnectionString )
q . Type = sec . Key ( "TYPE" ) . MustString ( Queue . Type )
q . WrapIfNecessary = sec . Key ( "WRAP_IF_NECESSARY" ) . MustBool ( Queue . WrapIfNecessary )
q . MaxAttempts = sec . Key ( "MAX_ATTEMPTS" ) . MustInt ( Queue . MaxAttempts )
q . Timeout = sec . Key ( "TIMEOUT" ) . MustDuration ( Queue . Timeout )
q . Workers = sec . Key ( "WORKERS" ) . MustInt ( Queue . Workers )
q . MaxWorkers = sec . Key ( "MAX_WORKERS" ) . MustInt ( Queue . MaxWorkers )
q . BlockTimeout = sec . Key ( "BLOCK_TIMEOUT" ) . MustDuration ( Queue . BlockTimeout )
q . BoostTimeout = sec . Key ( "BOOST_TIMEOUT" ) . MustDuration ( Queue . BoostTimeout )
q . BoostWorkers = sec . Key ( "BOOST_WORKERS" ) . MustInt ( Queue . BoostWorkers )
return q
}
2023-02-19 21:42:01 +05:30
// LoadQueueSettings sets up the default settings for Queues
2020-01-07 16:53:09 +05:30
// This is exported for tests to be able to use the queue
2023-02-19 21:42:01 +05:30
func LoadQueueSettings ( ) {
loadQueueFrom ( CfgProvider )
}
func loadQueueFrom ( rootCfg ConfigProvider ) {
sec := rootCfg . Section ( "queue" )
2021-05-26 08:20:35 +05:30
Queue . DataDir = filepath . ToSlash ( sec . Key ( "DATADIR" ) . MustString ( "queues/" ) )
2020-01-08 20:00:58 +05:30
if ! filepath . IsAbs ( Queue . DataDir ) {
2021-05-26 08:20:35 +05:30
Queue . DataDir = filepath . ToSlash ( filepath . Join ( AppDataPath , Queue . DataDir ) )
2020-01-07 16:53:09 +05:30
}
2020-10-16 03:10:03 +05:30
Queue . QueueLength = sec . Key ( "LENGTH" ) . MustInt ( 20 )
2020-01-07 16:53:09 +05:30
Queue . BatchLength = sec . Key ( "BATCH_LENGTH" ) . MustInt ( 20 )
2020-10-04 22:42:26 +05:30
Queue . ConnectionString = sec . Key ( "CONN_STR" ) . MustString ( "" )
2021-06-17 03:49:20 +05:30
defaultType := sec . Key ( "TYPE" ) . String ( )
2020-01-29 06:31:06 +05:30
Queue . Type = sec . Key ( "TYPE" ) . MustString ( "persistable-channel" )
2020-01-07 16:53:09 +05:30
Queue . WrapIfNecessary = sec . Key ( "WRAP_IF_NECESSARY" ) . MustBool ( true )
Queue . MaxAttempts = sec . Key ( "MAX_ATTEMPTS" ) . MustInt ( 10 )
Queue . Timeout = sec . Key ( "TIMEOUT" ) . MustDuration ( GracefulHammerTime + 30 * time . Second )
2021-05-24 04:53:55 +05:30
Queue . Workers = sec . Key ( "WORKERS" ) . MustInt ( 0 )
2020-01-07 16:53:09 +05:30
Queue . MaxWorkers = sec . Key ( "MAX_WORKERS" ) . MustInt ( 10 )
Queue . BlockTimeout = sec . Key ( "BLOCK_TIMEOUT" ) . MustDuration ( 1 * time . Second )
Queue . BoostTimeout = sec . Key ( "BOOST_TIMEOUT" ) . MustDuration ( 5 * time . Minute )
2021-05-24 04:53:55 +05:30
Queue . BoostWorkers = sec . Key ( "BOOST_WORKERS" ) . MustInt ( 1 )
2020-01-07 16:53:09 +05:30
Queue . QueueName = sec . Key ( "QUEUE_NAME" ) . MustString ( "_queue" )
2020-02-03 04:49:58 +05:30
Queue . SetName = sec . Key ( "SET_NAME" ) . MustString ( "" )
2020-01-07 16:53:09 +05:30
// Now handle the old issue_indexer configuration
2022-01-20 22:30:38 +05:30
// FIXME: DEPRECATED to be removed in v1.18.0
2023-02-19 21:42:01 +05:30
section := rootCfg . Section ( "queue.issue_indexer" )
2022-10-12 10:48:26 +05:30
directlySet := toDirectlySetKeysSet ( section )
if ! directlySet . Contains ( "TYPE" ) && defaultType == "" {
2023-02-19 21:42:01 +05:30
switch typ := rootCfg . Section ( "indexer" ) . Key ( "ISSUE_INDEXER_QUEUE_TYPE" ) . MustString ( "" ) ; typ {
2022-01-20 22:30:38 +05:30
case "levelqueue" :
2020-01-29 06:31:06 +05:30
_ , _ = section . NewKey ( "TYPE" , "level" )
2022-01-20 22:30:38 +05:30
case "channel" :
2020-01-29 06:31:06 +05:30
_ , _ = section . NewKey ( "TYPE" , "persistable-channel" )
2022-01-20 22:30:38 +05:30
case "redis" :
2020-01-29 06:31:06 +05:30
_ , _ = section . NewKey ( "TYPE" , "redis" )
2021-06-17 03:49:20 +05:30
case "" :
_ , _ = section . NewKey ( "TYPE" , "level" )
2020-01-07 16:53:09 +05:30
default :
2022-01-20 22:30:38 +05:30
log . Fatal ( "Unsupported indexer queue type: %v" , typ )
2020-01-07 16:53:09 +05:30
}
}
2022-10-12 10:48:26 +05:30
if ! directlySet . Contains ( "LENGTH" ) {
2023-02-19 21:42:01 +05:30
length := rootCfg . Section ( "indexer" ) . Key ( "UPDATE_BUFFER_LEN" ) . MustInt ( 0 )
2022-01-20 22:30:38 +05:30
if length != 0 {
_ , _ = section . NewKey ( "LENGTH" , strconv . Itoa ( length ) )
}
2020-01-07 16:53:09 +05:30
}
2022-10-12 10:48:26 +05:30
if ! directlySet . Contains ( "BATCH_LENGTH" ) {
2023-02-19 21:42:01 +05:30
fallback := rootCfg . Section ( "indexer" ) . Key ( "ISSUE_INDEXER_QUEUE_BATCH_NUMBER" ) . MustInt ( 0 )
2022-01-20 22:30:38 +05:30
if fallback != 0 {
_ , _ = section . NewKey ( "BATCH_LENGTH" , strconv . Itoa ( fallback ) )
}
2020-01-07 16:53:09 +05:30
}
2022-10-12 10:48:26 +05:30
if ! directlySet . Contains ( "DATADIR" ) {
2023-02-19 21:42:01 +05:30
queueDir := filepath . ToSlash ( rootCfg . Section ( "indexer" ) . Key ( "ISSUE_INDEXER_QUEUE_DIR" ) . MustString ( "" ) )
2022-01-20 22:30:38 +05:30
if queueDir != "" {
_ , _ = section . NewKey ( "DATADIR" , queueDir )
}
2020-01-07 16:53:09 +05:30
}
2022-10-12 10:48:26 +05:30
if ! directlySet . Contains ( "CONN_STR" ) {
2023-02-19 21:42:01 +05:30
connStr := rootCfg . Section ( "indexer" ) . Key ( "ISSUE_INDEXER_QUEUE_CONN_STR" ) . MustString ( "" )
2022-01-20 22:30:38 +05:30
if connStr != "" {
_ , _ = section . NewKey ( "CONN_STR" , connStr )
}
2020-01-07 16:53:09 +05:30
}
2020-01-16 23:25:36 +05:30
2022-01-20 22:30:38 +05:30
// FIXME: DEPRECATED to be removed in v1.18.0
// - will need to set default for [queue.*)] LENGTH appropriately though though
2020-01-16 23:25:36 +05:30
// Handle the old mailer configuration
2023-02-19 21:42:01 +05:30
handleOldLengthConfiguration ( rootCfg , "mailer" , "mailer" , "SEND_BUFFER_LEN" , 100 )
2020-02-03 04:49:58 +05:30
// Handle the old test pull requests configuration
// Please note this will be a unique queue
2023-02-19 21:42:01 +05:30
handleOldLengthConfiguration ( rootCfg , "pr_patch_checker" , "repository" , "PULL_REQUEST_QUEUE_LENGTH" , 1000 )
2021-10-17 17:13:25 +05:30
// Handle the old mirror queue configuration
// Please note this will be a unique queue
2023-02-19 21:42:01 +05:30
handleOldLengthConfiguration ( rootCfg , "mirror" , "repository" , "MIRROR_QUEUE_LENGTH" , 1000 )
2021-10-17 17:13:25 +05:30
}
// handleOldLengthConfiguration allows fallback to older configuration. `[queue.name]` `LENGTH` will override this configuration, but
// if that is left unset then we should fallback to the older configuration. (Except where the new length woul be <=0)
2023-02-19 21:42:01 +05:30
func handleOldLengthConfiguration ( rootCfg ConfigProvider , queueName , oldSection , oldKey string , defaultValue int ) {
if rootCfg . Section ( oldSection ) . HasKey ( oldKey ) {
2022-01-20 22:30:38 +05:30
log . Error ( "Deprecated fallback for %s queue length `[%s]` `%s` present. Use `[queue.%s]` `LENGTH`. This will be removed in v1.18.0" , queueName , queueName , oldSection , oldKey )
}
2023-02-19 21:42:01 +05:30
value := rootCfg . Section ( oldSection ) . Key ( oldKey ) . MustInt ( defaultValue )
2022-01-20 22:30:38 +05:30
2021-10-17 17:13:25 +05:30
// Don't override with 0
if value <= 0 {
return
}
2023-02-19 21:42:01 +05:30
section := rootCfg . Section ( "queue." + queueName )
2022-10-12 10:48:26 +05:30
directlySet := toDirectlySetKeysSet ( section )
if ! directlySet . Contains ( "LENGTH" ) {
2021-10-17 17:13:25 +05:30
_ , _ = section . NewKey ( "LENGTH" , strconv . Itoa ( value ) )
}
}
2022-10-12 10:48:26 +05:30
// toDirectlySetKeysSet returns a set of keys directly set by this section
2021-10-17 17:13:25 +05:30
// Note: we cannot use section.HasKey(...) as that will immediately set the Key if a parent section has the Key
// but this section does not.
2022-10-12 10:48:26 +05:30
func toDirectlySetKeysSet ( section * ini . Section ) container . Set [ string ] {
sections := make ( container . Set [ string ] )
2020-02-03 04:49:58 +05:30
for _ , key := range section . Keys ( ) {
2022-10-12 10:48:26 +05:30
sections . Add ( key . Name ( ) )
2020-02-03 04:49:58 +05:30
}
2022-10-12 10:48:26 +05:30
return sections
2020-01-07 16:53:09 +05:30
}