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 }