github.com/wfusion/gofusion@v1.1.14/common/infra/asynq/janitor.go (about)

     1  // Copyright 2021 Kentaro Hibino. All rights reserved.
     2  // Use of this source code is governed by a MIT license
     3  // that can be found in the LICENSE file.
     4  
     5  package asynq
     6  
     7  import (
     8  	"sync"
     9  	"time"
    10  
    11  	"github.com/wfusion/gofusion/common/infra/asynq/pkg/base"
    12  	"github.com/wfusion/gofusion/common/infra/asynq/pkg/log"
    13  )
    14  
    15  // A janitor is responsible for deleting expired completed tasks from the specified
    16  // queues. It periodically checks for any expired tasks in the completed set, and
    17  // deletes them.
    18  type janitor struct {
    19  	logger *log.Logger
    20  	broker base.Broker
    21  
    22  	// channel to communicate back to the long running "janitor" goroutine.
    23  	done chan struct{}
    24  
    25  	// list of queue names to check.
    26  	queues []string
    27  
    28  	// average interval between checks.
    29  	avgInterval time.Duration
    30  }
    31  
    32  type janitorParams struct {
    33  	logger   *log.Logger
    34  	broker   base.Broker
    35  	queues   []string
    36  	interval time.Duration
    37  }
    38  
    39  func newJanitor(params janitorParams) *janitor {
    40  	return &janitor{
    41  		logger:      params.logger,
    42  		broker:      params.broker,
    43  		done:        make(chan struct{}),
    44  		queues:      params.queues,
    45  		avgInterval: params.interval,
    46  	}
    47  }
    48  
    49  func (j *janitor) shutdown() {
    50  	j.logger.Debug("[Common] asynq janitor shutting down...")
    51  	// Signal the janitor goroutine to stop.
    52  	j.done <- struct{}{}
    53  }
    54  
    55  // start starts the "janitor" goroutine.
    56  func (j *janitor) start(wg *sync.WaitGroup) {
    57  	wg.Add(1)
    58  	timer := time.NewTimer(j.avgInterval) // randomize this interval with margin of 1s
    59  	go func() {
    60  		defer wg.Done()
    61  		for {
    62  			select {
    63  			case <-j.done:
    64  				j.logger.Debug("[Common] asynq janitor done")
    65  				return
    66  			case <-timer.C:
    67  				j.exec()
    68  				timer.Reset(j.avgInterval)
    69  			}
    70  		}
    71  	}()
    72  }
    73  
    74  func (j *janitor) exec() {
    75  	for _, qname := range j.queues {
    76  		if err := j.broker.DeleteExpiredCompletedTasks(qname); err != nil {
    77  			j.logger.Errorf("[Common] asynq failed to delete expired completed tasks from queue %q: %v",
    78  				qname, err)
    79  		}
    80  	}
    81  }