producer.*ReProducer.buildReproducer   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 36
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nop 1
dl 0
loc 36
rs 7.9759
c 0
b 0
f 0
1
package producer
2
3
import (
4
	"context"
5
	"sync"
6
7
	"github.com/stefanoj3/dirstalk/pkg/common/urlpath"
8
	"github.com/stefanoj3/dirstalk/pkg/scan"
9
)
10
11
const defaultChannelBuffer = 25
12
13
func NewReProducer(
14
	producer scan.Producer,
15
) *ReProducer {
16
	return &ReProducer{producer: producer}
17
}
18
19
type ReProducer struct {
20
	producer scan.Producer
21
}
22
23
// Reproduce will check if it is possible to go deeper on the result provided, if so will.
24
func (r *ReProducer) Reproduce(ctx context.Context) func(r scan.Result) <-chan scan.Target {
25
	return r.buildReproducer(ctx)
26
}
27
28
func (r *ReProducer) buildReproducer(ctx context.Context) func(result scan.Result) <-chan scan.Target {
29
	resultRegistry := sync.Map{}
30
31
	return func(result scan.Result) <-chan scan.Target {
32
		resultChannel := make(chan scan.Target, defaultChannelBuffer)
33
34
		go func() {
35
			defer close(resultChannel)
36
37
			if result.Target.Depth <= 0 {
38
				return
39
			}
40
41
			// no point in appending to a filename
42
			if urlpath.HasExtension(result.Target.Path) {
43
				return
44
			}
45
46
			_, inRegistry := resultRegistry.Load(result.Target.Path)
47
			if inRegistry {
48
				return
49
			}
50
51
			resultRegistry.Store(result.Target.Path, nil)
52
53
			for target := range r.producer.Produce(ctx) {
54
				newTarget := result.Target
55
				newTarget.Depth--
56
				newTarget.Path = urlpath.Join(newTarget.Path, target.Path)
57
				newTarget.Method = target.Method
58
59
				resultChannel <- newTarget
60
			}
61
		}()
62
63
		return resultChannel
64
	}
65
}
66