github.com/letsencrypt/boulder@v0.20251208.0/crl/updater/batch.go (about) 1 package updater 2 3 import ( 4 "context" 5 "errors" 6 "sync" 7 8 "github.com/letsencrypt/boulder/crl" 9 "github.com/letsencrypt/boulder/issuance" 10 ) 11 12 // RunOnce causes the crlUpdater to update every shard immediately, then exit. 13 // It will run as many simultaneous goroutines as the configured maxParallelism. 14 func (cu *crlUpdater) RunOnce(ctx context.Context) error { 15 var wg sync.WaitGroup 16 atTime := cu.clk.Now() 17 18 type workItem struct { 19 issuerNameID issuance.NameID 20 shardIdx int 21 } 22 23 var anyErr bool 24 var once sync.Once 25 26 shardWorker := func(in <-chan workItem) { 27 defer wg.Done() 28 29 for { 30 select { 31 case <-ctx.Done(): 32 return 33 case work, ok := <-in: 34 if !ok { 35 return 36 } 37 err := cu.updateShardWithRetry(ctx, atTime, work.issuerNameID, work.shardIdx) 38 if err != nil { 39 cu.log.AuditErrf( 40 "Generating CRL failed: id=[%s] err=[%s]", 41 crl.Id(work.issuerNameID, work.shardIdx, crl.Number(atTime)), err) 42 once.Do(func() { anyErr = true }) 43 } 44 } 45 } 46 } 47 48 inputs := make(chan workItem) 49 50 for range cu.maxParallelism { 51 wg.Add(1) 52 go shardWorker(inputs) 53 } 54 55 for _, issuer := range cu.issuers { 56 for i := range cu.numShards { 57 select { 58 case <-ctx.Done(): 59 close(inputs) 60 wg.Wait() 61 return ctx.Err() 62 case inputs <- workItem{issuerNameID: issuer.NameID(), shardIdx: i + 1}: 63 } 64 } 65 } 66 close(inputs) 67 68 wg.Wait() 69 if anyErr { 70 return errors.New("one or more errors encountered, see logs") 71 } 72 return ctx.Err() 73 }