code.gitea.io/gitea@v1.19.3/modules/queue/setting.go (about)

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package queue
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"code.gitea.io/gitea/modules/json"
    11  	"code.gitea.io/gitea/modules/log"
    12  	"code.gitea.io/gitea/modules/setting"
    13  )
    14  
    15  func validType(t string) (Type, error) {
    16  	if len(t) == 0 {
    17  		return PersistableChannelQueueType, nil
    18  	}
    19  	for _, typ := range RegisteredTypes() {
    20  		if t == string(typ) {
    21  			return typ, nil
    22  		}
    23  	}
    24  	return PersistableChannelQueueType, fmt.Errorf("unknown queue type: %s defaulting to %s", t, string(PersistableChannelQueueType))
    25  }
    26  
    27  func getQueueSettings(name string) (setting.QueueSettings, []byte) {
    28  	q := setting.GetQueueSettings(name)
    29  	cfg, err := json.Marshal(q)
    30  	if err != nil {
    31  		log.Error("Unable to marshall generic options: %v Error: %v", q, err)
    32  		log.Error("Unable to create queue for %s", name, err)
    33  		return q, []byte{}
    34  	}
    35  	return q, cfg
    36  }
    37  
    38  // CreateQueue for name with provided handler and exemplar
    39  func CreateQueue(name string, handle HandlerFunc, exemplar interface{}) Queue {
    40  	q, cfg := getQueueSettings(name)
    41  	if len(cfg) == 0 {
    42  		return nil
    43  	}
    44  
    45  	typ, err := validType(q.Type)
    46  	if err != nil {
    47  		log.Error("Invalid type %s provided for queue named %s defaulting to %s", q.Type, name, string(typ))
    48  	}
    49  
    50  	returnable, err := NewQueue(typ, handle, cfg, exemplar)
    51  	if q.WrapIfNecessary && err != nil {
    52  		log.Warn("Unable to create queue for %s: %v", name, err)
    53  		log.Warn("Attempting to create wrapped queue")
    54  		returnable, err = NewQueue(WrappedQueueType, handle, WrappedQueueConfiguration{
    55  			Underlying:  typ,
    56  			Timeout:     q.Timeout,
    57  			MaxAttempts: q.MaxAttempts,
    58  			Config:      cfg,
    59  			QueueLength: q.QueueLength,
    60  			Name:        name,
    61  		}, exemplar)
    62  	}
    63  	if err != nil {
    64  		log.Error("Unable to create queue for %s: %v", name, err)
    65  		return nil
    66  	}
    67  
    68  	// Sanity check configuration
    69  	if q.Workers == 0 && (q.BoostTimeout == 0 || q.BoostWorkers == 0 || q.MaxWorkers == 0) {
    70  		log.Warn("Queue: %s is configured to be non-scaling and have no workers\n - this configuration is likely incorrect and could cause Gitea to block", q.Name)
    71  		if pausable, ok := returnable.(Pausable); ok {
    72  			log.Warn("Queue: %s is being paused to prevent data-loss, add workers manually and unpause.", q.Name)
    73  			pausable.Pause()
    74  		}
    75  	}
    76  
    77  	return returnable
    78  }
    79  
    80  // CreateUniqueQueue for name with provided handler and exemplar
    81  func CreateUniqueQueue(name string, handle HandlerFunc, exemplar interface{}) UniqueQueue {
    82  	q, cfg := getQueueSettings(name)
    83  	if len(cfg) == 0 {
    84  		return nil
    85  	}
    86  
    87  	if len(q.Type) > 0 && q.Type != "dummy" && q.Type != "immediate" && !strings.HasPrefix(q.Type, "unique-") {
    88  		q.Type = "unique-" + q.Type
    89  	}
    90  
    91  	typ, err := validType(q.Type)
    92  	if err != nil || typ == PersistableChannelQueueType {
    93  		typ = PersistableChannelUniqueQueueType
    94  		if err != nil {
    95  			log.Error("Invalid type %s provided for queue named %s defaulting to %s", q.Type, name, string(typ))
    96  		}
    97  	}
    98  
    99  	returnable, err := NewQueue(typ, handle, cfg, exemplar)
   100  	if q.WrapIfNecessary && err != nil {
   101  		log.Warn("Unable to create unique queue for %s: %v", name, err)
   102  		log.Warn("Attempting to create wrapped queue")
   103  		returnable, err = NewQueue(WrappedUniqueQueueType, handle, WrappedUniqueQueueConfiguration{
   104  			Underlying:  typ,
   105  			Timeout:     q.Timeout,
   106  			MaxAttempts: q.MaxAttempts,
   107  			Config:      cfg,
   108  			QueueLength: q.QueueLength,
   109  		}, exemplar)
   110  	}
   111  	if err != nil {
   112  		log.Error("Unable to create unique queue for %s: %v", name, err)
   113  		return nil
   114  	}
   115  
   116  	// Sanity check configuration
   117  	if q.Workers == 0 && (q.BoostTimeout == 0 || q.BoostWorkers == 0 || q.MaxWorkers == 0) {
   118  		log.Warn("Queue: %s is configured to be non-scaling and have no workers\n - this configuration is likely incorrect and could cause Gitea to block", q.Name)
   119  		if pausable, ok := returnable.(Pausable); ok {
   120  			log.Warn("Queue: %s is being paused to prevent data-loss, add workers manually and unpause.", q.Name)
   121  			pausable.Pause()
   122  		}
   123  	}
   124  
   125  	return returnable.(UniqueQueue)
   126  }