...
1 package internal
2
3 import (
4 "context"
5 "sort"
6 "strings"
7 "sync"
8
9 "github.com/onsi/ginkgo/v2/types"
10 )
11
12 type ProgressReporterManager struct {
13 lock *sync.Mutex
14 progressReporters map[int]func() string
15 prCounter int
16 }
17
18 func NewProgressReporterManager() *ProgressReporterManager {
19 return &ProgressReporterManager{
20 progressReporters: map[int]func() string{},
21 lock: &sync.Mutex{},
22 }
23 }
24
25 func (prm *ProgressReporterManager) AttachProgressReporter(reporter func() string) func() {
26 prm.lock.Lock()
27 defer prm.lock.Unlock()
28 prm.prCounter += 1
29 prCounter := prm.prCounter
30 prm.progressReporters[prCounter] = reporter
31
32 return func() {
33 prm.lock.Lock()
34 defer prm.lock.Unlock()
35 delete(prm.progressReporters, prCounter)
36 }
37 }
38
39 func (prm *ProgressReporterManager) QueryProgressReporters(ctx context.Context, failer *Failer) []string {
40 prm.lock.Lock()
41 keys := []int{}
42 for key := range prm.progressReporters {
43 keys = append(keys, key)
44 }
45 sort.Ints(keys)
46 reporters := []func() string{}
47 for _, key := range keys {
48 reporters = append(reporters, prm.progressReporters[key])
49 }
50 prm.lock.Unlock()
51
52 if len(reporters) == 0 {
53 return nil
54 }
55 out := []string{}
56 for _, reporter := range reporters {
57 reportC := make(chan string, 1)
58 go func() {
59 defer func() {
60 e := recover()
61 if e != nil {
62 failer.Panic(types.NewCodeLocationWithStackTrace(1), e)
63 reportC <- "failed to query attached progress reporter"
64 }
65 }()
66 reportC <- reporter()
67 }()
68 var report string
69 select {
70 case report = <-reportC:
71 case <-ctx.Done():
72 return out
73 }
74 if strings.TrimSpace(report) != "" {
75 out = append(out, report)
76 }
77 }
78 return out
79 }
80
View as plain text