github.com/zhongdalu/gf@v1.0.0/g/os/gcron/gcron_cron.go (about)

     1  // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  
     7  package gcron
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"github.com/zhongdalu/gf/g/container/garray"
    13  	"github.com/zhongdalu/gf/g/container/gmap"
    14  	"github.com/zhongdalu/gf/g/container/gtype"
    15  	"github.com/zhongdalu/gf/g/os/glog"
    16  	"github.com/zhongdalu/gf/g/os/gtimer"
    17  	"time"
    18  )
    19  
    20  type Cron struct {
    21  	idGen    *gtype.Int64    // Used for unique name generation.
    22  	status   *gtype.Int      // Timed task status(0: Not Start; 1: Running; 2: Stopped; -1: Closed)
    23  	entries  *gmap.StrAnyMap // All timed task entries.
    24  	logPath  *gtype.String   // Logging path(folder).
    25  	logLevel *gtype.Int      // Logging level.
    26  }
    27  
    28  // New returns a new Cron object with default settings.
    29  func New() *Cron {
    30  	return &Cron{
    31  		idGen:    gtype.NewInt64(),
    32  		status:   gtype.NewInt(STATUS_RUNNING),
    33  		entries:  gmap.NewStrAnyMap(),
    34  		logPath:  gtype.NewString(),
    35  		logLevel: gtype.NewInt(glog.LEVEL_PROD),
    36  	}
    37  }
    38  
    39  // SetLogPath sets the logging folder path.
    40  func (c *Cron) SetLogPath(path string) {
    41  	c.logPath.Set(path)
    42  }
    43  
    44  // GetLogPath return the logging folder path.
    45  func (c *Cron) GetLogPath() string {
    46  	return c.logPath.Val()
    47  }
    48  
    49  // SetLogLevel sets the logging level.
    50  func (c *Cron) SetLogLevel(level int) {
    51  	c.logLevel.Set(level)
    52  }
    53  
    54  // GetLogLevel returns the logging level.
    55  func (c *Cron) GetLogLevel() int {
    56  	return c.logLevel.Val()
    57  }
    58  
    59  // Add adds a timed task.
    60  // A unique <name> can be bound with the timed task.
    61  // It returns and error if the <name> is already used.
    62  func (c *Cron) Add(pattern string, job func(), name ...string) (*Entry, error) {
    63  	if len(name) > 0 {
    64  		if c.Search(name[0]) != nil {
    65  			return nil, errors.New(fmt.Sprintf(`cron job "%s" already exists`, name[0]))
    66  		}
    67  	}
    68  	return c.addEntry(pattern, job, false, name...)
    69  }
    70  
    71  // AddSingleton adds a singleton timed task.
    72  // A singleton timed task is that can only be running one single instance at the same time.
    73  // A unique <name> can be bound with the timed task.
    74  // It returns and error if the <name> is already used.
    75  func (c *Cron) AddSingleton(pattern string, job func(), name ...string) (*Entry, error) {
    76  	if entry, err := c.Add(pattern, job, name...); err != nil {
    77  		return nil, err
    78  	} else {
    79  		entry.SetSingleton(true)
    80  		return entry, nil
    81  	}
    82  }
    83  
    84  // AddOnce adds a timed task which can be run only once.
    85  // A unique <name> can be bound with the timed task.
    86  // It returns and error if the <name> is already used.
    87  func (c *Cron) AddOnce(pattern string, job func(), name ...string) (*Entry, error) {
    88  	if entry, err := c.Add(pattern, job, name...); err != nil {
    89  		return nil, err
    90  	} else {
    91  		entry.SetTimes(1)
    92  		return entry, nil
    93  	}
    94  }
    95  
    96  // AddTimes adds a timed task which can be run specified times.
    97  // A unique <name> can be bound with the timed task.
    98  // It returns and error if the <name> is already used.
    99  func (c *Cron) AddTimes(pattern string, times int, job func(), name ...string) (*Entry, error) {
   100  	if entry, err := c.Add(pattern, job, name...); err != nil {
   101  		return nil, err
   102  	} else {
   103  		entry.SetTimes(times)
   104  		return entry, nil
   105  	}
   106  }
   107  
   108  // DelayAdd adds a timed task after <delay> time.
   109  func (c *Cron) DelayAdd(delay time.Duration, pattern string, job func(), name ...string) {
   110  	gtimer.AddOnce(delay, func() {
   111  		if _, err := c.Add(pattern, job, name...); err != nil {
   112  			panic(err)
   113  		}
   114  	})
   115  }
   116  
   117  // DelayAddSingleton adds a singleton timed task after <delay> time.
   118  func (c *Cron) DelayAddSingleton(delay time.Duration, pattern string, job func(), name ...string) {
   119  	gtimer.AddOnce(delay, func() {
   120  		if _, err := c.AddSingleton(pattern, job, name...); err != nil {
   121  			panic(err)
   122  		}
   123  	})
   124  }
   125  
   126  // DelayAddOnce adds a timed task after <delay> time.
   127  // This timed task can be run only once.
   128  func (c *Cron) DelayAddOnce(delay time.Duration, pattern string, job func(), name ...string) {
   129  	gtimer.AddOnce(delay, func() {
   130  		if _, err := c.AddOnce(pattern, job, name...); err != nil {
   131  			panic(err)
   132  		}
   133  	})
   134  }
   135  
   136  // DelayAddTimes adds a timed task after <delay> time.
   137  // This timed task can be run specified times.
   138  func (c *Cron) DelayAddTimes(delay time.Duration, pattern string, times int, job func(), name ...string) {
   139  	gtimer.AddOnce(delay, func() {
   140  		if _, err := c.AddTimes(pattern, times, job, name...); err != nil {
   141  			panic(err)
   142  		}
   143  	})
   144  }
   145  
   146  // Search returns a scheduled task with the specified <name>.
   147  // It returns nil if no found.
   148  func (c *Cron) Search(name string) *Entry {
   149  	if v := c.entries.Get(name); v != nil {
   150  		return v.(*Entry)
   151  	}
   152  	return nil
   153  }
   154  
   155  // Start starts running the specified timed task named <name>.
   156  func (c *Cron) Start(name ...string) {
   157  	if len(name) > 0 {
   158  		for _, v := range name {
   159  			if entry := c.Search(v); entry != nil {
   160  				entry.Start()
   161  			}
   162  		}
   163  	} else {
   164  		c.status.Set(STATUS_READY)
   165  	}
   166  }
   167  
   168  // Stop stops running the specified timed task named <name>.
   169  func (c *Cron) Stop(name ...string) {
   170  	if len(name) > 0 {
   171  		for _, v := range name {
   172  			if entry := c.Search(v); entry != nil {
   173  				entry.Stop()
   174  			}
   175  		}
   176  	} else {
   177  		c.status.Set(STATUS_STOPPED)
   178  	}
   179  }
   180  
   181  // Remove deletes scheduled task which named <name>.
   182  func (c *Cron) Remove(name string) {
   183  	if v := c.entries.Get(name); v != nil {
   184  		v.(*Entry).Close()
   185  	}
   186  }
   187  
   188  // Close stops and closes current cron.
   189  func (c *Cron) Close() {
   190  	c.status.Set(STATUS_CLOSED)
   191  }
   192  
   193  // Size returns the size of the timed tasks.
   194  func (c *Cron) Size() int {
   195  	return c.entries.Size()
   196  }
   197  
   198  // Entries return all timed tasks as slice(order by registered time asc).
   199  func (c *Cron) Entries() []*Entry {
   200  	array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int {
   201  		entry1 := v1.(*Entry)
   202  		entry2 := v2.(*Entry)
   203  		if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() {
   204  			return 1
   205  		}
   206  		return -1
   207  	}, true)
   208  	c.entries.RLockFunc(func(m map[string]interface{}) {
   209  		for _, v := range m {
   210  			array.Add(v.(*Entry))
   211  		}
   212  	})
   213  	entries := make([]*Entry, array.Len())
   214  	array.RLockFunc(func(array []interface{}) {
   215  		for k, v := range array {
   216  			entries[k] = v.(*Entry)
   217  		}
   218  	})
   219  	return entries
   220  }