@@ -17,6 +17,8 @@ import (
1717 "slices"
1818 "strconv"
1919 "strings"
20+ "sync"
21+ "sync/atomic"
2022 "time"
2123)
2224
@@ -100,6 +102,7 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
100102 }
101103
102104 // helper to process one athlete including starts, results, splits and disqualifications
105+ var processedItems64 int64
103106 processAthleteForTeam := func (teamName string , teamImported athleteModel.Team , athlete elements.Athlete ) error {
104107 dsvAthlete , err := strconv .Atoi (athlete .License )
105108 if err != nil {
@@ -171,6 +174,9 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
171174 }
172175 stats .Imported .Starts ++
173176
177+ // progress unit: entry processed
178+ atomic .AddInt64 (& processedItems64 , 1 )
179+
174180 if entry .EntryTime .Milliseconds () > 0 {
175181 resultModel := startModel.Result {
176182 Time : entry .EntryTime .Duration ,
@@ -183,6 +189,8 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
183189 }
184190 stats .Created .Results ++
185191 stats .Imported .Results ++
192+ // progress unit: result processed
193+ atomic .AddInt64 (& processedItems64 , 1 )
186194 }
187195 }
188196
@@ -242,6 +250,7 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
242250 }
243251 stats .Created .Results ++
244252 stats .Imported .Results ++
253+ atomic .AddInt64 (& processedItems64 , 1 )
245254 }
246255 }
247256
@@ -275,6 +284,7 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
275284 }
276285 stats .Created .Results ++
277286 stats .Imported .Results ++
287+ atomic .AddInt64 (& processedItems64 , 1 )
278288 }
279289 }
280290
@@ -339,6 +349,8 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
339349
340350 totalItems := totalEvents + totalAgeGroups + totalHeats + totalTeams + totalAthletes + totalEntries + totalResults
341351 processedItems := 0
352+ // initialize atomic counter with already processed units
353+ processedItems64 = int64 (processedItems )
342354
343355 progress (20 , fmt .Sprintf ("Starting import with %d total items to process" , totalItems ))
344356
@@ -556,15 +568,27 @@ func ImportLenexFile(file string, meeting string, exclude []int, include []int,
556568 stats .Imported .Teams ++
557569 fmt .Printf ("[ %c ] > id: %s, name: %s, part: %s\n " , cs , newTeam .Identifier .String (), newTeam .Name , newTeam .Participation )
558570
559- // ATHLETES
571+ // ATHLETES (bounded concurrency: N=5)
572+ const athleteWorkers = 5
573+ sem := make (chan struct {}, athleteWorkers )
574+ var wg sync.WaitGroup
560575 for _ , athlete := range team .Athletes {
561- processedItems ++
562- if err := processAthleteForTeam (team .Name , * newTeam , athlete ); err != nil {
563- return & stats , err
564- }
565- progressPct := 20 + (float64 (processedItems )/ float64 (totalItems ))* 80
566- progress (progressPct , fmt .Sprintf ("Processing athletes: %d / %d" , processedItems , totalItems ))
576+ sem <- struct {}{}
577+ wg .Add (1 )
578+ go func (a elements.Athlete ) {
579+ defer wg .Done ()
580+ defer func () { <- sem }()
581+ if err := processAthleteForTeam (team .Name , * newTeam , a ); err != nil {
582+ importError ("athlete processing failed" , err )
583+ return
584+ }
585+ // progress after athlete finished
586+ progressPct := 20 + (float64 (atomic .LoadInt64 (& processedItems64 ))/ float64 (totalItems ))* 80
587+ progress (progressPct , fmt .Sprintf ("Processing athletes: %d / %d" , atomic .LoadInt64 (& processedItems64 ), totalItems ))
588+ }(athlete )
567589 }
590+ // wait for team athletes to finish before moving to next team
591+ wg .Wait ()
568592 }
569593
570594 fmt .Printf (" +==============================+ \n " )
0 commit comments