github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekatime/once_in.go (about) 1 // Copyright © 2020. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekatime 7 8 import ( 9 "sync/atomic" 10 ) 11 12 type ( 13 // OnceInCallback is an alias to the function that user must define. 14 // 15 // That function user could pass to the OnceIn<interval>.Call() call. 16 // Then it will be called each time when time has come. 17 // 18 // An arguments represents a moment when a callback is called. 19 OnceInCallback func(ts Timestamp) 20 21 // OnceInPanicCallback is an alias to the function that user may define. 22 // 23 // That function user could pass along with OnceInCallback 24 // to the OnceIn<interval>.Call() call. 25 // This function will be called only if original OnceInCallback panics. 26 // 27 // An argument represents a recovered panic object. 28 OnceInPanicCallback func(panicObj any) 29 ) 30 31 // noinspection GoUnusedGlobalVariable 32 var ( 33 // ----- 34 // OnceIn<period> are a special objects that allows you to get the current time 35 // that is not really actual but under updating each time when specified 36 // period has come. 37 // 38 // For example, the OnceInMinute provides a new time for you each minute, 39 // meaning that inside one minute you will get the same unix timestamp. 40 // 41 // It's useful when you do not need an exact time or time with highest precision 42 // because of NewTimestampNow() call more expensive than these calls (up to 8x times). 43 // ----- 44 45 // OnceInMinute allows you to get an actual time once in 60 seconds (1 minute). 46 OnceInMinute onceInUpdater 47 48 // OnceIn10Minutes allows you to get an actual time once in 10 minutes. 49 OnceIn10Minutes onceInUpdater 50 51 // OnceIn15Minutes allows you to get an actual time once in 15 minutes. 52 OnceIn15Minutes onceInUpdater 53 54 // OnceIn30Minutes allows you to get an actual time once in 30 minutes. 55 OnceIn30Minutes onceInUpdater 56 57 // OnceInHour allows you to get an actual time once in 60 minutes (1 hour). 58 OnceInHour onceInUpdater 59 60 // OnceIn2Hour allows you to get an actual time once in 120 minutes (2 hours). 61 OnceIn2Hour onceInUpdater 62 63 // OnceIn3Hour allows you to get an actual time once in 180 minutes (3 hours). 64 OnceIn3Hour onceInUpdater 65 66 // OnceIn6Hour allows you to get an actual time once in 1440 minutes (6 hours). 67 OnceIn6Hour onceInUpdater 68 69 // OnceIn12Hours allows you to get an actual time once in 12 hours. 70 OnceIn12Hours onceInUpdater 71 72 // OnceInDay allows you to get an actual time once in 24 hours (1 day). 73 OnceInDay onceInUpdater 74 ) 75 76 // Now returns the cached unix Timestamp from the current onceInUpdater that caches 77 // the current Timestamp once in the specified period. 78 func (oiu *onceInUpdater) Now() Timestamp { 79 return Timestamp(atomic.LoadInt64((*int64)(&oiu.ts))) 80 } 81 82 // Date returns the cached Date from the current onceInUpdater that caches 83 // the current Date once in the specified period. 84 func (oiu *onceInUpdater) Date() Date { 85 return Date(atomic.LoadUint32((*uint32)(&oiu.d))) 86 } 87 88 // Time returns the cached Time from the current onceInUpdater that caches 89 // the current Time once in the specified period. 90 func (oiu *onceInUpdater) Time() Time { 91 return Time(atomic.LoadUint32((*uint32)(&oiu.t))) 92 } 93 94 // Call calls cb every time when associated onceIn updater's time has come. 95 // So, it means that 96 // 97 // ekatime.OnceInHour.Call(func(ts Timestamp){ 98 // fmt.Println(ts) 99 // }) 100 // 101 // will call provided callback every hour, printing the UNIX timestamp of the time 102 // when that hour has come. 103 // 104 // Does nothing if you pass a nil cb. 105 // That callback will be rejected with no-op. 106 // 107 // WARNING! 108 // IMPOSSIBLE TO STOP! YOU CANNOT "CANCEL" A CALLBACK YOU ONCE ADDED TO PLANNER. 109 // It will be called every time until the end. If you need to stop, handle it manually! 110 // 111 // WARNING! 112 // ONE THREAD! ALL CALLBACKS SHARES THE SAME WORKER GOROUTINE. 113 // So, if there is some "big" work, wrap your callback manually to the closure with 114 // "go callback(ts, dd, t)" call (spawn a separate goroutine). 115 func (oiu *onceInUpdater) Call(invokeNow bool, cb OnceInCallback, panicCb ...OnceInPanicCallback) { 116 if cb != nil { 117 cbNum := atomic.AddUint32(&oiu.cbNum, 1) - 1 118 onceInRegister(cb, panicCb, oiu.repeatDelay, 1, invokeNow, true, cbNum) 119 } 120 } 121 122 // After is the same as Call() but calls cb after dur is passed. 123 // 124 // Does nothing if dur >= OnceIn's delayer time. 125 // It means, you cannot delay up to 1h function execution using OnceInHour. 126 func (oiu *onceInUpdater) After(delayInSec Timestamp, invokeNow bool, cb OnceInCallback, panicCb ...OnceInPanicCallback) { 127 128 if delayInSec < 1 { 129 delayInSec = 1 130 } 131 132 if cb != nil && delayInSec < oiu.repeatDelay { 133 cbNum := atomic.AddUint32(&oiu.cbNum, 1) - 1 134 onceInRegister(cb, panicCb, oiu.repeatDelay, delayInSec, invokeNow, true, cbNum) 135 } 136 }