...

Source file src/github.com/letsencrypt/boulder/crl/updater/continuous.go

Documentation: github.com/letsencrypt/boulder/crl/updater

     1  package updater
     2  
     3  import (
     4  	"context"
     5  	"math/rand"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/letsencrypt/boulder/crl"
    10  	"github.com/letsencrypt/boulder/issuance"
    11  )
    12  
    13  // Run causes the crlUpdater to enter its processing loop. It starts one
    14  // goroutine for every shard it intends to update, each of which will wake at
    15  // the appropriate interval.
    16  func (cu *crlUpdater) Run(ctx context.Context) error {
    17  	var wg sync.WaitGroup
    18  
    19  	shardWorker := func(issuerNameID issuance.IssuerNameID, shardIdx int) {
    20  		defer wg.Done()
    21  
    22  		// Wait for a random number of nanoseconds less than the updatePeriod, so
    23  		// that process restarts do not skip or delay shards deterministically.
    24  		waitTimer := time.NewTimer(time.Duration(rand.Int63n(cu.updatePeriod.Nanoseconds())))
    25  		defer waitTimer.Stop()
    26  		select {
    27  		case <-waitTimer.C:
    28  			// Continue to ticker loop
    29  		case <-ctx.Done():
    30  			return
    31  		}
    32  
    33  		// Do work, then sleep for updatePeriod. Rinse, and repeat.
    34  		ticker := time.NewTicker(cu.updatePeriod)
    35  		defer ticker.Stop()
    36  		for {
    37  			// Check for context cancellation before we do any real work, in case we
    38  			// overran the last tick and both cases were selectable at the same time.
    39  			if ctx.Err() != nil {
    40  				return
    41  			}
    42  
    43  			atTime := cu.clk.Now()
    44  			err := cu.updateShardWithRetry(ctx, atTime, issuerNameID, shardIdx, nil)
    45  			if err != nil {
    46  				// We only log, rather than return, so that the long-lived process can
    47  				// continue and try again at the next tick.
    48  				cu.log.AuditErrf(
    49  					"Generating CRL failed: id=[%s] err=[%s]",
    50  					crl.Id(issuerNameID, shardIdx, crl.Number(atTime)), err)
    51  			}
    52  
    53  			select {
    54  			case <-ticker.C:
    55  				continue
    56  			case <-ctx.Done():
    57  				return
    58  			}
    59  		}
    60  	}
    61  
    62  	// Start one shard worker per shard this updater is responsible for.
    63  	for _, issuer := range cu.issuers {
    64  		for i := 1; i <= cu.numShards; i++ {
    65  			wg.Add(1)
    66  			go shardWorker(issuer.NameID(), i)
    67  		}
    68  	}
    69  
    70  	// Wait for all of the shard workers to exit, which will happen when their
    71  	// contexts are cancelled, probably by a SIGTERM.
    72  	wg.Wait()
    73  	return ctx.Err()
    74  }
    75  

View as plain text