@@ -68,6 +68,49 @@ func (vm *VisitedMap) Get(path string) bool {
6868 return vm .visited [path ]
6969}
7070
71+ // WorkerPool manages a pool of workers for processing files
72+ type WorkerPool struct {
73+ workers int
74+ tasks chan func ()
75+ wg sync.WaitGroup
76+ }
77+
78+ func NewWorkerPool (workers int ) * WorkerPool {
79+ pool := & WorkerPool {
80+ workers : workers ,
81+ tasks : make (chan func (), workers ), // Buffer size matches worker count
82+ }
83+ pool .start ()
84+ return pool
85+ }
86+
87+ func (p * WorkerPool ) start () {
88+ for i := 0 ; i < p .workers ; i ++ {
89+ p .wg .Add (1 )
90+ go func () {
91+ defer p .wg .Done ()
92+ for task := range p .tasks {
93+ task ()
94+ }
95+ }()
96+ }
97+ }
98+
99+ func (p * WorkerPool ) Submit (task func ()) {
100+ p .tasks <- task
101+ }
102+
103+ func (p * WorkerPool ) Wait () {
104+ close (p .tasks )
105+ p .wg .Wait ()
106+ }
107+
108+ // BatchProcessor handles batched file operations
109+ type BatchProcessor struct {
110+ files []os.DirEntry
111+ path string
112+ }
113+
71114// Walk walks a directory tree looking for Argo applications and renders them
72115func (w * Walker ) Walk (inputPath , outputPath string , maxDepth int , hashes HashStore ) error {
73116 visited := NewVisitedMap ()
@@ -112,7 +155,6 @@ func pruneUnvisited(visited *VisitedMap, outputPath string) error {
112155
113156func (w * Walker ) walk (inputPath , outputPath string , depth , maxDepth int , visited * VisitedMap , hashes HashStore ) error {
114157 if maxDepth != InfiniteDepth {
115- // If we've reached the max depth, stop walking
116158 if depth > maxDepth {
117159 return nil
118160 }
@@ -125,22 +167,17 @@ func (w *Walker) walk(inputPath, outputPath string, depth, maxDepth int, visited
125167 return err
126168 }
127169
128- var wg sync.WaitGroup
170+ // Create a worker pool with optimal size
171+ pool := NewWorkerPool (4 )
129172 errChan := make (chan error , len (fi ))
130- semaphore := make (chan struct {}, 10 ) // Limit concurrent goroutines
131173
132174 for _ , file := range fi {
133175 if ! strings .Contains (file .Name (), ".yaml" ) {
134176 continue
135177 }
136178
137- wg .Add (1 )
138- semaphore <- struct {}{} // Acquire semaphore
139-
140- go func (file os.DirEntry ) {
141- defer wg .Done ()
142- defer func () { <- semaphore }() // Release semaphore
143-
179+ file := file // Create a new variable for the closure
180+ pool .Submit (func () {
144181 crds , err := helm .Read (filepath .Join (inputPath , file .Name ()))
145182 if err != nil {
146183 errChan <- err
@@ -157,55 +194,67 @@ func (w *Walker) walk(inputPath, outputPath string, depth, maxDepth int, visited
157194 }
158195
159196 path := filepath .Join (outputPath , crd .ObjectMeta .Name )
160- visited .Set (path )
161197
162- hash , err := hashes . Get ( crd . ObjectMeta . Name )
163- if err != nil {
198+ // Create the output directory if it doesn't exist
199+ if err := os . MkdirAll ( path , 0755 ); err != nil {
164200 errChan <- err
165201 return
166202 }
167203
168- hashGenerated , err := w .GenerateHash (crd )
169- if err != nil {
170- if errors .Is (err , kustomize .ErrNotSupported ) {
171- continue
172- }
173- errChan <- err
174- return
175- }
204+ visited .Set (path )
176205
177- emptyManifest , err := helm .EmptyManifest (filepath .Join (path , "manifest.yaml" ))
206+ // Check hash first to avoid unnecessary operations
207+ hash , err := hashes .Get (crd .ObjectMeta .Name )
178208 if err != nil {
179209 errChan <- err
180210 return
181211 }
182212
183- if hashGenerated != hash || emptyManifest {
184- log .Printf ("No match detected. Render: %s\n " , crd .ObjectMeta .Name )
185- if err := w .Render (crd , path ); err != nil {
213+ // Only proceed with hash generation if needed
214+ if hash == "" {
215+ hashGenerated , err := w .GenerateHash (crd )
216+ if err != nil {
186217 if errors .Is (err , kustomize .ErrNotSupported ) {
187218 continue
188219 }
189220 errChan <- err
190221 return
191222 }
192223
193- if err := hashes .Add (crd .ObjectMeta .Name , hashGenerated ); err != nil {
224+ emptyManifest , err := helm .EmptyManifest (filepath .Join (path , "manifest.yaml" ))
225+ if err != nil {
194226 errChan <- err
195227 return
196228 }
229+
230+ if emptyManifest {
231+ log .Printf ("No match detected. Render: %s\n " , crd .ObjectMeta .Name )
232+ if err := w .Render (crd , path ); err != nil {
233+ if errors .Is (err , kustomize .ErrNotSupported ) {
234+ continue
235+ }
236+ errChan <- err
237+ return
238+ }
239+
240+ if err := hashes .Add (crd .ObjectMeta .Name , hashGenerated ); err != nil {
241+ errChan <- err
242+ return
243+ }
244+ }
197245 }
198246
247+ // Process subdirectories sequentially
199248 if err := w .walk (path , outputPath , depth + 1 , maxDepth , visited , hashes ); err != nil {
200249 errChan <- err
201250 return
202251 }
203252 }
204- }( file )
253+ })
205254 }
206255
207- // Wait for all goroutines to complete
208- wg .Wait ()
256+ // Wait for all workers to complete
257+ pool .Wait ()
209258 close (errChan )
210259
211260 // Check for any errors
0 commit comments