mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 20:36:07 +01:00 
			
		
		
		
	Fix intermittent CI failure in EmptyQueue (#23753)
The ordering of the final token causing a close of the queue in this test may be out of sync due to concurrency. Instead just use ensure that the queue is closed when everything expected is done. Fixes: https://github.com/go-gitea/gitea/issues/23608 Fixes: https://github.com/go-gitea/gitea/issues/23977 --------- Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
This commit is contained in:
		@@ -4,9 +4,9 @@
 | 
				
			|||||||
package queue
 | 
					package queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
						"sync/atomic"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,10 +16,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
					func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
				
			||||||
	if os.Getenv("CI") != "" {
 | 
						// Create a temporary directory for the queue
 | 
				
			||||||
		t.Skip("Skipping because test is flaky on CI")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	tmpDir := t.TempDir()
 | 
						tmpDir := t.TempDir()
 | 
				
			||||||
	_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
 | 
						_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -100,7 +97,7 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
				
			|||||||
	executedInitial := map[string][]string{}
 | 
						executedInitial := map[string][]string{}
 | 
				
			||||||
	hasInitial := map[string][]string{}
 | 
						hasInitial := map[string][]string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fillQueue := func(name string, done chan struct{}) {
 | 
						fillQueue := func(name string, done chan int64) {
 | 
				
			||||||
		t.Run("Initial Filling: "+name, func(t *testing.T) {
 | 
							t.Run("Initial Filling: "+name, func(t *testing.T) {
 | 
				
			||||||
			lock := sync.Mutex{}
 | 
								lock := sync.Mutex{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -157,33 +154,39 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
				
			|||||||
			assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name]))
 | 
								assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name]))
 | 
				
			||||||
			mapLock.Unlock()
 | 
								mapLock.Unlock()
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
							mapLock.Lock()
 | 
				
			||||||
 | 
							count := int64(len(hasInitial[name]))
 | 
				
			||||||
 | 
							mapLock.Unlock()
 | 
				
			||||||
 | 
							done <- count
 | 
				
			||||||
		close(done)
 | 
							close(done)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	doneA := make(chan struct{})
 | 
						hasQueueAChan := make(chan int64)
 | 
				
			||||||
	doneB := make(chan struct{})
 | 
						hasQueueBChan := make(chan int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go fillQueue("QueueA", doneA)
 | 
						go fillQueue("QueueA", hasQueueAChan)
 | 
				
			||||||
	go fillQueue("QueueB", doneB)
 | 
						go fillQueue("QueueB", hasQueueBChan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<-doneA
 | 
						hasA := <-hasQueueAChan
 | 
				
			||||||
	<-doneB
 | 
						hasB := <-hasQueueBChan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	executedEmpty := map[string][]string{}
 | 
						executedEmpty := map[string][]string{}
 | 
				
			||||||
	hasEmpty := map[string][]string{}
 | 
						hasEmpty := map[string][]string{}
 | 
				
			||||||
	emptyQueue := func(name string, done chan struct{}) {
 | 
						emptyQueue := func(name string, numInQueue int64, done chan struct{}) {
 | 
				
			||||||
		t.Run("Empty Queue: "+name, func(t *testing.T) {
 | 
							t.Run("Empty Queue: "+name, func(t *testing.T) {
 | 
				
			||||||
			lock := sync.Mutex{}
 | 
								lock := sync.Mutex{}
 | 
				
			||||||
			stop := make(chan struct{})
 | 
								stop := make(chan struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// collect the tasks that have been executed
 | 
								// collect the tasks that have been executed
 | 
				
			||||||
 | 
								atomicCount := int64(0)
 | 
				
			||||||
			handle := func(data ...Data) []Data {
 | 
								handle := func(data ...Data) []Data {
 | 
				
			||||||
				lock.Lock()
 | 
									lock.Lock()
 | 
				
			||||||
				for _, datum := range data {
 | 
									for _, datum := range data {
 | 
				
			||||||
					mapLock.Lock()
 | 
										mapLock.Lock()
 | 
				
			||||||
					executedEmpty[name] = append(executedEmpty[name], datum.(string))
 | 
										executedEmpty[name] = append(executedEmpty[name], datum.(string))
 | 
				
			||||||
					mapLock.Unlock()
 | 
										mapLock.Unlock()
 | 
				
			||||||
					if datum.(string) == "final" {
 | 
										count := atomic.AddInt64(&atomicCount, 1)
 | 
				
			||||||
 | 
										if count >= numInQueue {
 | 
				
			||||||
						close(stop)
 | 
											close(stop)
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -217,11 +220,11 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
				
			|||||||
		close(done)
 | 
							close(done)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	doneA = make(chan struct{})
 | 
						doneA := make(chan struct{})
 | 
				
			||||||
	doneB = make(chan struct{})
 | 
						doneB := make(chan struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go emptyQueue("QueueA", doneA)
 | 
						go emptyQueue("QueueA", hasA, doneA)
 | 
				
			||||||
	go emptyQueue("QueueB", doneB)
 | 
						go emptyQueue("QueueB", hasB, doneB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<-doneA
 | 
						<-doneA
 | 
				
			||||||
	<-doneB
 | 
						<-doneB
 | 
				
			||||||
@@ -237,20 +240,20 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
 | 
				
			|||||||
	hasEmpty = map[string][]string{}
 | 
						hasEmpty = map[string][]string{}
 | 
				
			||||||
	mapLock.Unlock()
 | 
						mapLock.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	doneA = make(chan struct{})
 | 
						hasQueueAChan = make(chan int64)
 | 
				
			||||||
	doneB = make(chan struct{})
 | 
						hasQueueBChan = make(chan int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go fillQueue("QueueA", doneA)
 | 
						go fillQueue("QueueA", hasQueueAChan)
 | 
				
			||||||
	go fillQueue("QueueB", doneB)
 | 
						go fillQueue("QueueB", hasQueueBChan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<-doneA
 | 
						hasA = <-hasQueueAChan
 | 
				
			||||||
	<-doneB
 | 
						hasB = <-hasQueueBChan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	doneA = make(chan struct{})
 | 
						doneA = make(chan struct{})
 | 
				
			||||||
	doneB = make(chan struct{})
 | 
						doneB = make(chan struct{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go emptyQueue("QueueA", doneA)
 | 
						go emptyQueue("QueueA", hasA, doneA)
 | 
				
			||||||
	go emptyQueue("QueueB", doneB)
 | 
						go emptyQueue("QueueB", hasB, doneB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<-doneA
 | 
						<-doneA
 | 
				
			||||||
	<-doneB
 | 
						<-doneB
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user