github.com/wangyougui/gf/v2@v2.6.5/os/gtimer/gtimer.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/wangyougui/gf.
     6  
     7  // Package gtimer implements timer for interval/delayed jobs running and management.
     8  //
     9  // This package is designed for management for millions of timing jobs. The differences
    10  // between gtimer and gcron are as follows:
    11  //  1. package gcron is implemented based on package gtimer.
    12  //  2. gtimer is designed for high performance and for millions of timing jobs.
    13  //  3. gcron supports configuration pattern grammar like linux crontab, which is more manually
    14  //     readable.
    15  //  4. gtimer's benchmark OP is measured in nanoseconds, and gcron's benchmark OP is measured
    16  //     in microseconds.
    17  //
    18  // ALSO VERY NOTE the common delay of the timer: https://github.com/golang/go/issues/14410
    19  package gtimer
    20  
    21  import (
    22  	"context"
    23  	"strconv"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/wangyougui/gf/v2/container/gtype"
    28  	"github.com/wangyougui/gf/v2/errors/gcode"
    29  	"github.com/wangyougui/gf/v2/errors/gerror"
    30  	"github.com/wangyougui/gf/v2/internal/command"
    31  )
    32  
    33  // Timer is the timer manager, which uses ticks to calculate the timing interval.
    34  type Timer struct {
    35  	mu      sync.RWMutex
    36  	queue   *priorityQueue // queue is a priority queue based on heap structure.
    37  	status  *gtype.Int     // status is the current timer status.
    38  	ticks   *gtype.Int64   // ticks is the proceeded interval number by the timer.
    39  	options TimerOptions   // timer options is used for timer configuration.
    40  }
    41  
    42  // TimerOptions is the configuration object for Timer.
    43  type TimerOptions struct {
    44  	Interval time.Duration // (optional) Interval is the underlying rolling interval tick of the timer.
    45  	Quick    bool          // Quick is used for quick timer, which means the timer will not wait for the first interval to be elapsed.
    46  }
    47  
    48  // internalPanic is the custom panic for internal usage.
    49  type internalPanic string
    50  
    51  const (
    52  	StatusReady                        = 0      // Job or Timer is ready for running.
    53  	StatusRunning                      = 1      // Job or Timer is already running.
    54  	StatusStopped                      = 2      // Job or Timer is stopped.
    55  	StatusClosed                       = -1     // Job or Timer is closed and waiting to be deleted.
    56  	panicExit            internalPanic = "exit" // panicExit is used for custom job exit with panic.
    57  	defaultTimerInterval               = "100"  // defaultTimerInterval is the default timer interval in milliseconds.
    58  	// commandEnvKeyForInterval is the key for command argument or environment configuring default interval duration for timer.
    59  	commandEnvKeyForInterval = "gf.gtimer.interval"
    60  )
    61  
    62  var (
    63  	defaultInterval = getDefaultInterval()
    64  	defaultTimer    = New()
    65  )
    66  
    67  func getDefaultInterval() time.Duration {
    68  	interval := command.GetOptWithEnv(commandEnvKeyForInterval, defaultTimerInterval)
    69  	n, err := strconv.Atoi(interval)
    70  	if err != nil {
    71  		panic(gerror.WrapCodef(
    72  			gcode.CodeInvalidConfiguration, err, `error converting string "%s" to int number`,
    73  			interval,
    74  		))
    75  	}
    76  	return time.Duration(n) * time.Millisecond
    77  }
    78  
    79  // DefaultOptions creates and returns a default options object for Timer creation.
    80  func DefaultOptions() TimerOptions {
    81  	return TimerOptions{
    82  		Interval: defaultInterval,
    83  	}
    84  }
    85  
    86  // SetTimeout runs the job once after duration of `delay`.
    87  // It is like the one in javascript.
    88  func SetTimeout(ctx context.Context, delay time.Duration, job JobFunc) {
    89  	AddOnce(ctx, delay, job)
    90  }
    91  
    92  // SetInterval runs the job every duration of `delay`.
    93  // It is like the one in javascript.
    94  func SetInterval(ctx context.Context, interval time.Duration, job JobFunc) {
    95  	Add(ctx, interval, job)
    96  }
    97  
    98  // Add adds a timing job to the default timer, which runs in interval of `interval`.
    99  func Add(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
   100  	return defaultTimer.Add(ctx, interval, job)
   101  }
   102  
   103  // AddEntry adds a timing job to the default timer with detailed parameters.
   104  //
   105  // The parameter `interval` specifies the running interval of the job.
   106  //
   107  // The parameter `singleton` specifies whether the job running in singleton mode.
   108  // There's only one of the same job is allowed running when its a singleton mode job.
   109  //
   110  // The parameter `times` specifies limit for the job running times, which means the job
   111  // exits if its run times exceeds the `times`.
   112  //
   113  // The parameter `status` specifies the job status when it's firstly added to the timer.
   114  func AddEntry(ctx context.Context, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) *Entry {
   115  	return defaultTimer.AddEntry(ctx, interval, job, isSingleton, times, status)
   116  }
   117  
   118  // AddSingleton is a convenience function for add singleton mode job.
   119  func AddSingleton(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
   120  	return defaultTimer.AddSingleton(ctx, interval, job)
   121  }
   122  
   123  // AddOnce is a convenience function for adding a job which only runs once and then exits.
   124  func AddOnce(ctx context.Context, interval time.Duration, job JobFunc) *Entry {
   125  	return defaultTimer.AddOnce(ctx, interval, job)
   126  }
   127  
   128  // AddTimes is a convenience function for adding a job which is limited running times.
   129  func AddTimes(ctx context.Context, interval time.Duration, times int, job JobFunc) *Entry {
   130  	return defaultTimer.AddTimes(ctx, interval, times, job)
   131  }
   132  
   133  // DelayAdd adds a timing job after delay of `interval` duration.
   134  // Also see Add.
   135  func DelayAdd(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
   136  	defaultTimer.DelayAdd(ctx, delay, interval, job)
   137  }
   138  
   139  // DelayAddEntry adds a timing job after delay of `interval` duration.
   140  // Also see AddEntry.
   141  func DelayAddEntry(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc, isSingleton bool, times int, status int) {
   142  	defaultTimer.DelayAddEntry(ctx, delay, interval, job, isSingleton, times, status)
   143  }
   144  
   145  // DelayAddSingleton adds a timing job after delay of `interval` duration.
   146  // Also see AddSingleton.
   147  func DelayAddSingleton(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
   148  	defaultTimer.DelayAddSingleton(ctx, delay, interval, job)
   149  }
   150  
   151  // DelayAddOnce adds a timing job after delay of `interval` duration.
   152  // Also see AddOnce.
   153  func DelayAddOnce(ctx context.Context, delay time.Duration, interval time.Duration, job JobFunc) {
   154  	defaultTimer.DelayAddOnce(ctx, delay, interval, job)
   155  }
   156  
   157  // DelayAddTimes adds a timing job after delay of `interval` duration.
   158  // Also see AddTimes.
   159  func DelayAddTimes(ctx context.Context, delay time.Duration, interval time.Duration, times int, job JobFunc) {
   160  	defaultTimer.DelayAddTimes(ctx, delay, interval, times, job)
   161  }