@@ -30,8 +30,15 @@ import (
30
30
var (
31
31
ErrNotManagedByDocoCD = errors .New ("stack is not managed by doco-cd" )
32
32
ErrDeploymentConflict = errors .New ("another stack with the same name already exists and is not managed by this repository" )
33
+ repoLocks sync.Map // Map to hold locks for each repository
33
34
)
34
35
36
+ // getRepoLock retrieves a mutex lock for the given repository name.
37
+ func getRepoLock (repoName string ) * sync.Mutex {
38
+ lockIface , _ := repoLocks .LoadOrStore (repoName , & sync.Mutex {})
39
+ return lockIface .(* sync.Mutex )
40
+ }
41
+
35
42
// StartPoll initializes PollJob with the provided configuration and starts the PollHandler goroutine.
36
43
func StartPoll (h * handlerData , pollConfig config.PollConfig , wg * sync.WaitGroup ) error {
37
44
if pollConfig .Interval == 0 {
@@ -61,18 +68,28 @@ func StartPoll(h *handlerData, pollConfig config.PollConfig, wg *sync.WaitGroup)
61
68
62
69
// PollHandler is a function that handles polling for changes in a repository.
63
70
func (h * handlerData ) PollHandler (pollJob * config.PollJob ) {
64
- logger := h . log . With ( )
71
+ repoName := getRepoName ( string ( pollJob . Config . CloneUrl ) )
65
72
73
+ logger := h .log .With (slog .String ("repository" , repoName ))
66
74
logger .Debug ("Start poll handler" )
67
75
76
+ lock := getRepoLock (repoName )
77
+
68
78
for {
69
79
if pollJob .LastRun == 0 || time .Now ().Unix () >= pollJob .NextRun {
70
- repoName := getRepoName (string (pollJob .Config .CloneUrl ))
71
- logger .Debug ("Running poll for repository" , slog .String ("repoName" , repoName ))
80
+ locked := lock .TryLock ()
72
81
73
- err := RunPoll (context .Background (), pollJob .Config , h .appConfig , h .dataMountPoint , h .dockerCli , h .dockerClient , logger )
74
- if err != nil {
75
- prometheus .PollErrors .WithLabelValues (repoName ).Inc ()
82
+ if ! locked {
83
+ h .log .Info ("Another poll job is still in progress, skipping this run" )
84
+ } else {
85
+ logger .Debug ("Start poll job" )
86
+
87
+ err := RunPoll (context .Background (), pollJob .Config , h .appConfig , h .dataMountPoint , h .dockerCli , h .dockerClient , logger )
88
+ if err != nil {
89
+ prometheus .PollErrors .WithLabelValues (repoName ).Inc ()
90
+ }
91
+
92
+ lock .Unlock ()
76
93
}
77
94
78
95
pollJob .NextRun = time .Now ().Unix () + int64 (pollJob .Config .Interval )
@@ -91,9 +108,7 @@ func RunPoll(ctx context.Context, pollConfig config.PollConfig, appConfig *confi
91
108
cloneUrl := string (pollConfig .CloneUrl )
92
109
jobID := uuid .Must (uuid .NewRandom ()).String ()
93
110
repoName := getRepoName (cloneUrl )
94
- jobLog := logger .With (
95
- slog .String ("repository" , repoName ),
96
- slog .String ("job_id" , jobID ))
111
+ jobLog := logger .With (slog .String ("job_id" , jobID ))
97
112
98
113
if strings .Contains (repoName , ".." ) {
99
114
jobLog .Error ("invalid repository name, contains '..'" )
0 commit comments