code.gitea.io/gitea@v1.22.3/modules/queue/base_levelqueue_test.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package queue
     5  
     6  import (
     7  	"testing"
     8  
     9  	"code.gitea.io/gitea/modules/queue/lqinternal"
    10  	"code.gitea.io/gitea/modules/setting"
    11  
    12  	"gitea.com/lunny/levelqueue"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/syndtr/goleveldb/leveldb"
    15  )
    16  
    17  func TestBaseLevelDB(t *testing.T) {
    18  	_, err := newBaseLevelQueueGeneric(&BaseConfig{ConnStr: "redis://"}, false)
    19  	assert.ErrorContains(t, err, "invalid leveldb connection string")
    20  
    21  	_, err = newBaseLevelQueueGeneric(&BaseConfig{DataFullDir: "relative"}, false)
    22  	assert.ErrorContains(t, err, "invalid leveldb data dir")
    23  
    24  	testQueueBasic(t, newBaseLevelQueueSimple, toBaseConfig("baseLevelQueue", setting.QueueSettings{Datadir: t.TempDir() + "/queue-test", Length: 10}), false)
    25  	testQueueBasic(t, newBaseLevelQueueUnique, toBaseConfig("baseLevelQueueUnique", setting.QueueSettings{ConnStr: "leveldb://" + t.TempDir() + "/queue-test", Length: 10}), true)
    26  }
    27  
    28  func TestCorruptedLevelQueue(t *testing.T) {
    29  	// sometimes the levelqueue could be in a corrupted state, this test is to make sure it can recover from it
    30  	dbDir := t.TempDir() + "/levelqueue-test"
    31  	db, err := leveldb.OpenFile(dbDir, nil)
    32  	if !assert.NoError(t, err) {
    33  		return
    34  	}
    35  	defer db.Close()
    36  
    37  	assert.NoError(t, db.Put([]byte("other-key"), []byte("other-value"), nil))
    38  
    39  	nameQueuePrefix := []byte("queue_name")
    40  	nameSetPrefix := []byte("set_name")
    41  	lq, err := levelqueue.NewUniqueQueue(db, nameQueuePrefix, nameSetPrefix, false)
    42  	assert.NoError(t, err)
    43  	assert.NoError(t, lq.RPush([]byte("item-1")))
    44  
    45  	itemKey := lqinternal.QueueItemKeyBytes(nameQueuePrefix, 1)
    46  	itemValue, err := db.Get(itemKey, nil)
    47  	assert.NoError(t, err)
    48  	assert.Equal(t, []byte("item-1"), itemValue)
    49  
    50  	// there should be 5 keys in db: queue low, queue high, 1 queue item, 1 set item, and "other-key"
    51  	keys := lqinternal.ListLevelQueueKeys(db)
    52  	assert.Len(t, keys, 5)
    53  
    54  	// delete the queue item key, to corrupt the queue
    55  	assert.NoError(t, db.Delete(itemKey, nil))
    56  	// now the queue is corrupted, it never works again
    57  	_, err = lq.LPop()
    58  	assert.ErrorIs(t, err, levelqueue.ErrNotFound)
    59  	assert.NoError(t, lq.Close())
    60  
    61  	// remove all the queue related keys to reset the queue
    62  	lqinternal.RemoveLevelQueueKeys(db, nameQueuePrefix)
    63  	lqinternal.RemoveLevelQueueKeys(db, nameSetPrefix)
    64  	// now there should be only 1 key in db: "other-key"
    65  	keys = lqinternal.ListLevelQueueKeys(db)
    66  	assert.Len(t, keys, 1)
    67  	assert.Equal(t, []byte("other-key"), keys[0])
    68  
    69  	// re-create a queue from db
    70  	lq, err = levelqueue.NewUniqueQueue(db, nameQueuePrefix, nameSetPrefix, false)
    71  	assert.NoError(t, err)
    72  	assert.NoError(t, lq.RPush([]byte("item-new-1")))
    73  	// now the queue works again
    74  	itemValue, err = lq.LPop()
    75  	assert.NoError(t, err)
    76  	assert.Equal(t, []byte("item-new-1"), itemValue)
    77  	assert.NoError(t, lq.Close())
    78  }