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

     1  // Copyright 2019 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package queue
     5  
     6  import (
     7  	"context"
     8  
     9  	"code.gitea.io/gitea/modules/nosql"
    10  
    11  	"gitea.com/lunny/levelqueue"
    12  )
    13  
    14  // LevelUniqueQueueType is the type for level queue
    15  const LevelUniqueQueueType Type = "unique-level"
    16  
    17  // LevelUniqueQueueConfiguration is the configuration for a LevelUniqueQueue
    18  type LevelUniqueQueueConfiguration struct {
    19  	ByteFIFOQueueConfiguration
    20  	DataDir          string
    21  	ConnectionString string
    22  	QueueName        string
    23  }
    24  
    25  // LevelUniqueQueue implements a disk library queue
    26  type LevelUniqueQueue struct {
    27  	*ByteFIFOUniqueQueue
    28  }
    29  
    30  // NewLevelUniqueQueue creates a ledis local queue
    31  //
    32  // Please note that this Queue does not guarantee that a particular
    33  // task cannot be processed twice or more at the same time. Uniqueness is
    34  // only guaranteed whilst the task is waiting in the queue.
    35  func NewLevelUniqueQueue(handle HandlerFunc, cfg, exemplar interface{}) (Queue, error) {
    36  	configInterface, err := toConfig(LevelUniqueQueueConfiguration{}, cfg)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	config := configInterface.(LevelUniqueQueueConfiguration)
    41  
    42  	if len(config.ConnectionString) == 0 {
    43  		config.ConnectionString = config.DataDir
    44  	}
    45  	config.WaitOnEmpty = true
    46  
    47  	byteFIFO, err := NewLevelUniqueQueueByteFIFO(config.ConnectionString, config.QueueName)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	byteFIFOQueue, err := NewByteFIFOUniqueQueue(LevelUniqueQueueType, byteFIFO, handle, config.ByteFIFOQueueConfiguration, exemplar)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	queue := &LevelUniqueQueue{
    58  		ByteFIFOUniqueQueue: byteFIFOQueue,
    59  	}
    60  	queue.qid = GetManager().Add(queue, LevelUniqueQueueType, config, exemplar)
    61  	return queue, nil
    62  }
    63  
    64  var _ UniqueByteFIFO = &LevelUniqueQueueByteFIFO{}
    65  
    66  // LevelUniqueQueueByteFIFO represents a ByteFIFO formed from a LevelUniqueQueue
    67  type LevelUniqueQueueByteFIFO struct {
    68  	internal   *levelqueue.UniqueQueue
    69  	connection string
    70  }
    71  
    72  // NewLevelUniqueQueueByteFIFO creates a new ByteFIFO formed from a LevelUniqueQueue
    73  func NewLevelUniqueQueueByteFIFO(connection, prefix string) (*LevelUniqueQueueByteFIFO, error) {
    74  	db, err := nosql.GetManager().GetLevelDB(connection)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	internal, err := levelqueue.NewUniqueQueue(db, []byte(prefix), []byte(prefix+"-unique"), false)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	return &LevelUniqueQueueByteFIFO{
    85  		connection: connection,
    86  		internal:   internal,
    87  	}, nil
    88  }
    89  
    90  // PushFunc pushes data to the end of the fifo and calls the callback if it is added
    91  func (fifo *LevelUniqueQueueByteFIFO) PushFunc(ctx context.Context, data []byte, fn func() error) error {
    92  	return fifo.internal.LPushFunc(data, fn)
    93  }
    94  
    95  // PushBack pushes data to the top of the fifo
    96  func (fifo *LevelUniqueQueueByteFIFO) PushBack(ctx context.Context, data []byte) error {
    97  	return fifo.internal.RPush(data)
    98  }
    99  
   100  // Pop pops data from the start of the fifo
   101  func (fifo *LevelUniqueQueueByteFIFO) Pop(ctx context.Context) ([]byte, error) {
   102  	data, err := fifo.internal.RPop()
   103  	if err != nil && err != levelqueue.ErrNotFound {
   104  		return nil, err
   105  	}
   106  	return data, nil
   107  }
   108  
   109  // Len returns the length of the fifo
   110  func (fifo *LevelUniqueQueueByteFIFO) Len(ctx context.Context) int64 {
   111  	return fifo.internal.Len()
   112  }
   113  
   114  // Has returns whether the fifo contains this data
   115  func (fifo *LevelUniqueQueueByteFIFO) Has(ctx context.Context, data []byte) (bool, error) {
   116  	return fifo.internal.Has(data)
   117  }
   118  
   119  // Close this fifo
   120  func (fifo *LevelUniqueQueueByteFIFO) Close() error {
   121  	err := fifo.internal.Close()
   122  	_ = nosql.GetManager().CloseLevelDB(fifo.connection)
   123  	return err
   124  }
   125  
   126  func init() {
   127  	queuesMap[LevelUniqueQueueType] = NewLevelUniqueQueue
   128  }