gcron_cron.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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/gogf/gf.
  6. package gcron
  7. import (
  8. "context"
  9. "time"
  10. "github.com/gogf/gf/v2/container/garray"
  11. "github.com/gogf/gf/v2/container/gmap"
  12. "github.com/gogf/gf/v2/container/gtype"
  13. "github.com/gogf/gf/v2/os/glog"
  14. "github.com/gogf/gf/v2/os/gtimer"
  15. )
  16. type Cron struct {
  17. idGen *gtype.Int64 // Used for unique name generation.
  18. status *gtype.Int // Timed task status(0: Not Start; 1: Running; 2: Stopped; -1: Closed)
  19. entries *gmap.StrAnyMap // All timed task entries.
  20. logger glog.ILogger // Logger, it is nil in default.
  21. }
  22. // New returns a new Cron object with default settings.
  23. func New() *Cron {
  24. return &Cron{
  25. idGen: gtype.NewInt64(),
  26. status: gtype.NewInt(StatusRunning),
  27. entries: gmap.NewStrAnyMap(true),
  28. }
  29. }
  30. // SetLogger sets the logger for cron.
  31. func (c *Cron) SetLogger(logger glog.ILogger) {
  32. c.logger = logger
  33. }
  34. // GetLogger returns the logger in the cron.
  35. func (c *Cron) GetLogger() glog.ILogger {
  36. return c.logger
  37. }
  38. // AddEntry creates and returns a new Entry object.
  39. func (c *Cron) AddEntry(ctx context.Context, pattern string, job JobFunc, times int, isSingleton bool, name ...string) (*Entry, error) {
  40. var (
  41. entryName = ""
  42. infinite = false
  43. )
  44. if len(name) > 0 {
  45. entryName = name[0]
  46. }
  47. if times <= 0 {
  48. infinite = true
  49. }
  50. return c.doAddEntry(doAddEntryInput{
  51. Name: entryName,
  52. Job: job,
  53. Ctx: ctx,
  54. Times: times,
  55. Pattern: pattern,
  56. IsSingleton: isSingleton,
  57. Infinite: infinite,
  58. })
  59. }
  60. // Add adds a timed task.
  61. // A unique `name` can be bound with the timed task.
  62. // It returns and error if the `name` is already used.
  63. func (c *Cron) Add(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
  64. return c.AddEntry(ctx, pattern, job, -1, false, name...)
  65. }
  66. // AddSingleton adds a singleton timed task.
  67. // A singleton timed task is that can only be running one single instance at the same time.
  68. // A unique `name` can be bound with the timed task.
  69. // It returns and error if the `name` is already used.
  70. func (c *Cron) AddSingleton(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
  71. return c.AddEntry(ctx, pattern, job, -1, true, name...)
  72. }
  73. // AddTimes adds a timed task which can be run specified times.
  74. // A unique `name` can be bound with the timed task.
  75. // It returns and error if the `name` is already used.
  76. func (c *Cron) AddTimes(ctx context.Context, pattern string, times int, job JobFunc, name ...string) (*Entry, error) {
  77. return c.AddEntry(ctx, pattern, job, times, false, name...)
  78. }
  79. // AddOnce adds a timed task which can be run only once.
  80. // A unique `name` can be bound with the timed task.
  81. // It returns and error if the `name` is already used.
  82. func (c *Cron) AddOnce(ctx context.Context, pattern string, job JobFunc, name ...string) (*Entry, error) {
  83. return c.AddEntry(ctx, pattern, job, 1, false, name...)
  84. }
  85. // DelayAddEntry adds a timed task after `delay` time.
  86. func (c *Cron) DelayAddEntry(ctx context.Context, delay time.Duration, pattern string, job JobFunc, times int, isSingleton bool, name ...string) {
  87. gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
  88. if _, err := c.AddEntry(ctx, pattern, job, times, isSingleton, name...); err != nil {
  89. panic(err)
  90. }
  91. })
  92. }
  93. // DelayAdd adds a timed task after `delay` time.
  94. func (c *Cron) DelayAdd(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
  95. gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
  96. if _, err := c.Add(ctx, pattern, job, name...); err != nil {
  97. panic(err)
  98. }
  99. })
  100. }
  101. // DelayAddSingleton adds a singleton timed task after `delay` time.
  102. func (c *Cron) DelayAddSingleton(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
  103. gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
  104. if _, err := c.AddSingleton(ctx, pattern, job, name...); err != nil {
  105. panic(err)
  106. }
  107. })
  108. }
  109. // DelayAddOnce adds a timed task after `delay` time.
  110. // This timed task can be run only once.
  111. func (c *Cron) DelayAddOnce(ctx context.Context, delay time.Duration, pattern string, job JobFunc, name ...string) {
  112. gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
  113. if _, err := c.AddOnce(ctx, pattern, job, name...); err != nil {
  114. panic(err)
  115. }
  116. })
  117. }
  118. // DelayAddTimes adds a timed task after `delay` time.
  119. // This timed task can be run specified times.
  120. func (c *Cron) DelayAddTimes(ctx context.Context, delay time.Duration, pattern string, times int, job JobFunc, name ...string) {
  121. gtimer.AddOnce(ctx, delay, func(ctx context.Context) {
  122. if _, err := c.AddTimes(ctx, pattern, times, job, name...); err != nil {
  123. panic(err)
  124. }
  125. })
  126. }
  127. // Search returns a scheduled task with the specified `name`.
  128. // It returns nil if not found.
  129. func (c *Cron) Search(name string) *Entry {
  130. if v := c.entries.Get(name); v != nil {
  131. return v.(*Entry)
  132. }
  133. return nil
  134. }
  135. // Start starts running the specified timed task named `name`.
  136. // If no`name` specified, it starts the entire cron.
  137. func (c *Cron) Start(name ...string) {
  138. if len(name) > 0 {
  139. for _, v := range name {
  140. if entry := c.Search(v); entry != nil {
  141. entry.Start()
  142. }
  143. }
  144. } else {
  145. c.status.Set(StatusReady)
  146. }
  147. }
  148. // Stop stops running the specified timed task named `name`.
  149. // If no`name` specified, it stops the entire cron.
  150. func (c *Cron) Stop(name ...string) {
  151. if len(name) > 0 {
  152. for _, v := range name {
  153. if entry := c.Search(v); entry != nil {
  154. entry.Stop()
  155. }
  156. }
  157. } else {
  158. c.status.Set(StatusStopped)
  159. }
  160. }
  161. // Remove deletes scheduled task which named `name`.
  162. func (c *Cron) Remove(name string) {
  163. if v := c.entries.Get(name); v != nil {
  164. v.(*Entry).Close()
  165. }
  166. }
  167. // Close stops and closes current cron.
  168. func (c *Cron) Close() {
  169. c.status.Set(StatusClosed)
  170. }
  171. // Size returns the size of the timed tasks.
  172. func (c *Cron) Size() int {
  173. return c.entries.Size()
  174. }
  175. // Entries return all timed tasks as slice(order by registered time asc).
  176. func (c *Cron) Entries() []*Entry {
  177. array := garray.NewSortedArraySize(c.entries.Size(), func(v1, v2 interface{}) int {
  178. entry1 := v1.(*Entry)
  179. entry2 := v2.(*Entry)
  180. if entry1.Time.Nanosecond() > entry2.Time.Nanosecond() {
  181. return 1
  182. }
  183. return -1
  184. }, true)
  185. c.entries.RLockFunc(func(m map[string]interface{}) {
  186. for _, v := range m {
  187. array.Add(v.(*Entry))
  188. }
  189. })
  190. entries := make([]*Entry, array.Len())
  191. array.RLockFunc(func(array []interface{}) {
  192. for k, v := range array {
  193. entries[k] = v.(*Entry)
  194. }
  195. })
  196. return entries
  197. }