mirror of
https://gitee.com/johng/gf.git
synced 2024-12-02 04:07:47 +08:00
improve panic...recover of exit feature for package ghttp/gtimer/gfsnotify (#2000)
This commit is contained in:
parent
675ae9bade
commit
98b2e8ab18
2
.github/workflows/gf.yml
vendored
2
.github/workflows/gf.yml
vendored
@ -8,6 +8,7 @@ on:
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
|
||||
pull_request:
|
||||
@ -16,6 +17,7 @@ on:
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
|
||||
env:
|
||||
|
@ -98,6 +98,9 @@ type (
|
||||
// Listening file descriptor mapping.
|
||||
// The key is either "http" or "https" and the value is its FD.
|
||||
listenerFdMap = map[string]string
|
||||
|
||||
// internalPanic is the custom panic for internal usage.
|
||||
internalPanic string
|
||||
)
|
||||
|
||||
const (
|
||||
@ -119,9 +122,6 @@ const (
|
||||
const (
|
||||
supportedHttpMethods = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
|
||||
defaultMethod = "ALL"
|
||||
exceptionExit = "exit"
|
||||
exceptionExitAll = "exit_all"
|
||||
exceptionExitHook = "exit_hook"
|
||||
routeCacheDuration = time.Hour
|
||||
ctxKeyForRequest = "gHttpRequestObject"
|
||||
contentTypeXml = "text/xml"
|
||||
@ -135,6 +135,12 @@ const (
|
||||
gracefulShutdownTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
const (
|
||||
exceptionExit internalPanic = "exit"
|
||||
exceptionExitAll internalPanic = "exit_all"
|
||||
exceptionExitHook internalPanic = "exit_hook"
|
||||
)
|
||||
|
||||
var (
|
||||
// methodsMap stores all supported HTTP method.
|
||||
// It is used for quick HTTP method searching using map.
|
||||
|
@ -71,14 +71,6 @@ func (lru *adapterMemoryLru) Pop() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Print is used for test only.
|
||||
// func (lru *adapterMemoryLru) Print() {
|
||||
// for _, v := range lru.list.FrontAll() {
|
||||
// fmt.Printf("%v ", v)
|
||||
// }
|
||||
// fmt.Println()
|
||||
// }
|
||||
|
||||
// SyncAndClear synchronizes the keys from `rawList` to `list` and `data`
|
||||
// using Least Recently Used algorithm.
|
||||
func (lru *adapterMemoryLru) SyncAndClear(ctx context.Context) {
|
||||
@ -87,9 +79,7 @@ func (lru *adapterMemoryLru) SyncAndClear(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
// Data synchronization.
|
||||
var (
|
||||
alreadyExistItem interface{}
|
||||
)
|
||||
var alreadyExistItem interface{}
|
||||
for {
|
||||
if rawListItem := lru.rawList.PopFront(); rawListItem != nil {
|
||||
// Deleting the key from list.
|
||||
@ -104,9 +94,9 @@ func (lru *adapterMemoryLru) SyncAndClear(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
// Data cleaning up.
|
||||
for i := lru.Size() - lru.cache.cap; i > 0; i-- {
|
||||
if s := lru.Pop(); s != nil {
|
||||
lru.cache.clearByKey(s, true)
|
||||
for clearLength := lru.Size() - lru.cache.cap; clearLength > 0; clearLength-- {
|
||||
if topKey := lru.Pop(); topKey != nil {
|
||||
lru.cache.clearByKey(topKey, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ func (entry *Entry) Close() {
|
||||
// gcron.Entry relies on gtimer to implement a scheduled task check for gcron.Entry per second.
|
||||
func (entry *Entry) checkAndRun(ctx context.Context) {
|
||||
currentTime := time.Now()
|
||||
if !entry.schedule.checkMeetAndUpdateLastSeconds(currentTime) {
|
||||
if !entry.schedule.checkMeetAndUpdateLastSeconds(ctx, currentTime) {
|
||||
intlog.Printf(
|
||||
ctx,
|
||||
`timely check, current time does not meet cron job "%s"`,
|
||||
|
@ -15,23 +15,22 @@ import (
|
||||
"github.com/gogf/gf/v2/container/gtype"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/internal/intlog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
)
|
||||
|
||||
// cronSchedule is the schedule for cron job.
|
||||
type cronSchedule struct {
|
||||
create int64 // Created timestamp.
|
||||
every int64 // Running interval in seconds.
|
||||
pattern string // The raw cron pattern string.
|
||||
second map[int]struct{} // Job can run in these second numbers.
|
||||
minute map[int]struct{} // Job can run in these minute numbers.
|
||||
hour map[int]struct{} // Job can run in these hour numbers.
|
||||
day map[int]struct{} // Job can run in these day numbers.
|
||||
week map[int]struct{} // Job can run in these week numbers.
|
||||
month map[int]struct{} // Job can run in these moth numbers.
|
||||
lastTimestamp *gtype.Int64 // Last timestamp number, for seconds fix.
|
||||
createTimestamp int64 // Created timestamp in seconds.
|
||||
everySeconds int64 // Running interval in seconds.
|
||||
pattern string // The raw cron pattern string.
|
||||
secondMap map[int]struct{} // Job can run in these second numbers.
|
||||
minuteMap map[int]struct{} // Job can run in these minute numbers.
|
||||
hourMap map[int]struct{} // Job can run in these hour numbers.
|
||||
dayMap map[int]struct{} // Job can run in these day numbers.
|
||||
weekMap map[int]struct{} // Job can run in these week numbers.
|
||||
monthMap map[int]struct{} // Job can run in these moth numbers.
|
||||
lastTimestamp *gtype.Int64 // Last timestamp number, for timestamp fix in some delay.
|
||||
}
|
||||
|
||||
const (
|
||||
@ -107,6 +106,7 @@ var (
|
||||
|
||||
// newSchedule creates and returns a schedule object for given cron pattern.
|
||||
func newSchedule(pattern string) (*cronSchedule, error) {
|
||||
var currentTimestamp = time.Now().Unix()
|
||||
// Check if the predefined patterns.
|
||||
if match, _ := gregex.MatchString(`(@\w+)\s*(\w*)\s*`, pattern); len(match) > 0 {
|
||||
key := strings.ToLower(match[1])
|
||||
@ -118,10 +118,10 @@ func newSchedule(pattern string) (*cronSchedule, error) {
|
||||
return nil, err
|
||||
}
|
||||
return &cronSchedule{
|
||||
create: time.Now().Unix(),
|
||||
every: int64(d.Seconds()),
|
||||
pattern: pattern,
|
||||
lastTimestamp: gtype.NewInt64(),
|
||||
createTimestamp: currentTimestamp,
|
||||
everySeconds: int64(d.Seconds()),
|
||||
pattern: pattern,
|
||||
lastTimestamp: gtype.NewInt64(currentTimestamp),
|
||||
}, nil
|
||||
}
|
||||
return nil, gerror.NewCodef(gcode.CodeInvalidParameter, `invalid pattern: "%s"`, pattern)
|
||||
@ -130,46 +130,46 @@ func newSchedule(pattern string) (*cronSchedule, error) {
|
||||
// 0 0 0 1 1 2
|
||||
if match, _ := gregex.MatchString(regexForCron, pattern); len(match) == 7 {
|
||||
schedule := &cronSchedule{
|
||||
create: time.Now().Unix(),
|
||||
every: 0,
|
||||
pattern: pattern,
|
||||
lastTimestamp: gtype.NewInt64(),
|
||||
createTimestamp: currentTimestamp,
|
||||
everySeconds: 0,
|
||||
pattern: pattern,
|
||||
lastTimestamp: gtype.NewInt64(currentTimestamp),
|
||||
}
|
||||
// Second.
|
||||
if m, err := parsePatternItem(match[1], 0, 59, false); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.second = m
|
||||
schedule.secondMap = m
|
||||
}
|
||||
// Minute.
|
||||
if m, err := parsePatternItem(match[2], 0, 59, false); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.minute = m
|
||||
schedule.minuteMap = m
|
||||
}
|
||||
// Hour.
|
||||
if m, err := parsePatternItem(match[3], 0, 23, false); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.hour = m
|
||||
schedule.hourMap = m
|
||||
}
|
||||
// Day.
|
||||
if m, err := parsePatternItem(match[4], 1, 31, true); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.day = m
|
||||
schedule.dayMap = m
|
||||
}
|
||||
// Month.
|
||||
if m, err := parsePatternItem(match[5], 1, 12, false); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.month = m
|
||||
schedule.monthMap = m
|
||||
}
|
||||
// Week.
|
||||
if m, err := parsePatternItem(match[6], 0, 6, true); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
schedule.week = m
|
||||
schedule.weekMap = m
|
||||
}
|
||||
return schedule, nil
|
||||
}
|
||||
@ -208,6 +208,7 @@ func parsePatternItem(item string, min int, max int, allowQuestionMark bool) (ma
|
||||
case 6:
|
||||
// It's checking week field.
|
||||
itemType = patternItemTypeWeek
|
||||
|
||||
case 12:
|
||||
// It's checking month field.
|
||||
itemType = patternItemTypeMonth
|
||||
@ -268,78 +269,48 @@ func parsePatternItemValue(value string, itemType int) (int, error) {
|
||||
}
|
||||
|
||||
// checkMeetAndUpdateLastSeconds checks if the given time `t` meets the runnable point for the job.
|
||||
func (s *cronSchedule) checkMeetAndUpdateLastSeconds(t time.Time) bool {
|
||||
if s.every != 0 {
|
||||
func (s *cronSchedule) checkMeetAndUpdateLastSeconds(ctx context.Context, t time.Time) bool {
|
||||
if s.everySeconds != 0 {
|
||||
// It checks using interval.
|
||||
if diff := t.Unix() - s.create; diff > 0 {
|
||||
return diff%s.every == 0
|
||||
secondsAfterCreated := t.Unix() - s.createTimestamp
|
||||
secondsAfterCreated += int64(s.getFixedTimestampDelta(ctx, t))
|
||||
if secondsAfterCreated > 0 {
|
||||
return secondsAfterCreated%s.everySeconds == 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// It checks using normal cron pattern.
|
||||
if _, ok := s.second[s.getFixedSecond(t)]; !ok {
|
||||
if _, ok := s.secondMap[s.getFixedSecond(ctx, t)]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := s.minute[t.Minute()]; !ok {
|
||||
if _, ok := s.minuteMap[t.Minute()]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := s.hour[t.Hour()]; !ok {
|
||||
if _, ok := s.hourMap[t.Hour()]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := s.day[t.Day()]; !ok {
|
||||
if _, ok := s.dayMap[t.Day()]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := s.month[int(t.Month())]; !ok {
|
||||
if _, ok := s.monthMap[int(t.Month())]; !ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := s.week[int(t.Weekday())]; !ok {
|
||||
if _, ok := s.weekMap[int(t.Weekday())]; !ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// getFixedSecond checks, fixes and returns the seconds that have delay in some seconds.
|
||||
// Reference: https://github.com/golang/go/issues/14410
|
||||
func (s *cronSchedule) getFixedSecond(t time.Time) int {
|
||||
var (
|
||||
second = t.Second()
|
||||
currentTimestamp = t.Unix()
|
||||
lastTimestamp = s.lastTimestamp.Val()
|
||||
)
|
||||
switch {
|
||||
case
|
||||
lastTimestamp == 0,
|
||||
lastTimestamp == currentTimestamp-1:
|
||||
lastTimestamp = currentTimestamp
|
||||
|
||||
case
|
||||
lastTimestamp == currentTimestamp-2,
|
||||
lastTimestamp == currentTimestamp-3,
|
||||
lastTimestamp == currentTimestamp:
|
||||
lastTimestamp += 1
|
||||
second += 1
|
||||
|
||||
default:
|
||||
// Too much delay, let's update the last timestamp to current one.
|
||||
lastTimestamp = currentTimestamp
|
||||
intlog.Printf(
|
||||
context.Background(),
|
||||
`too much delay, last "%d", current "%d"`,
|
||||
lastTimestamp, currentTimestamp,
|
||||
)
|
||||
}
|
||||
second %= 60
|
||||
s.lastTimestamp.Set(lastTimestamp)
|
||||
return second
|
||||
}
|
||||
|
||||
// Next returns the next time this schedule is activated, greater than the given
|
||||
// time. If no time can be found to satisfy the schedule, return the zero time.
|
||||
func (s *cronSchedule) Next(t time.Time) time.Time {
|
||||
if s.every != 0 {
|
||||
diff := t.Unix() - s.create
|
||||
cnt := diff/s.every + 1
|
||||
return t.Add(time.Duration(cnt*s.every) * time.Second)
|
||||
if s.everySeconds != 0 {
|
||||
var (
|
||||
diff = t.Unix() - s.createTimestamp
|
||||
count = diff/s.everySeconds + 1
|
||||
)
|
||||
return t.Add(time.Duration(count*s.everySeconds) * time.Second)
|
||||
}
|
||||
|
||||
// Start at the earliest possible time (the upcoming second).
|
||||
@ -355,7 +326,7 @@ WRAP:
|
||||
return t // who will care the job that run in five years later
|
||||
}
|
||||
|
||||
for !s.match(s.month, int(t.Month())) {
|
||||
for !s.match(s.monthMap, int(t.Month())) {
|
||||
if !added {
|
||||
added = true
|
||||
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc)
|
||||
@ -387,7 +358,7 @@ WRAP:
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
for !s.match(s.hour, t.Hour()) {
|
||||
for !s.match(s.hourMap, t.Hour()) {
|
||||
if !added {
|
||||
added = true
|
||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, loc)
|
||||
@ -398,7 +369,7 @@ WRAP:
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
for !s.match(s.minute, t.Minute()) {
|
||||
for !s.match(s.minuteMap, t.Minute()) {
|
||||
if !added {
|
||||
added = true
|
||||
t = t.Truncate(time.Minute)
|
||||
@ -409,7 +380,7 @@ WRAP:
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
for !s.match(s.second, t.Second()) {
|
||||
for !s.match(s.secondMap, t.Second()) {
|
||||
if !added {
|
||||
added = true
|
||||
t = t.Truncate(time.Second)
|
||||
@ -425,8 +396,8 @@ WRAP:
|
||||
// dayMatches returns true if the schedule's day-of-week and day-of-month
|
||||
// restrictions are satisfied by the given time.
|
||||
func (s *cronSchedule) dayMatches(t time.Time) bool {
|
||||
_, ok1 := s.day[t.Day()]
|
||||
_, ok2 := s.week[int(t.Weekday())]
|
||||
_, ok1 := s.dayMap[t.Day()]
|
||||
_, ok2 := s.weekMap[int(t.Weekday())]
|
||||
return ok1 && ok2
|
||||
}
|
||||
|
||||
|
53
os/gcron/gcron_schedule_fix.go
Normal file
53
os/gcron/gcron_schedule_fix.go
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gcron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/internal/intlog"
|
||||
)
|
||||
|
||||
// getFixedSecond checks, fixes and returns the seconds that have delay fix in some seconds.
|
||||
// Reference: https://github.com/golang/go/issues/14410
|
||||
func (s *cronSchedule) getFixedSecond(ctx context.Context, t time.Time) int {
|
||||
return (t.Second() + s.getFixedTimestampDelta(ctx, t)) % 60
|
||||
}
|
||||
|
||||
// getFixedTimestampDelta checks, fixes and returns the timestamp delta that have delay fix in some seconds.
|
||||
// The tolerated timestamp delay is `3` seconds in default.
|
||||
func (s *cronSchedule) getFixedTimestampDelta(ctx context.Context, t time.Time) int {
|
||||
var (
|
||||
currentTimestamp = t.Unix()
|
||||
lastTimestamp = s.lastTimestamp.Val()
|
||||
delta int
|
||||
)
|
||||
switch {
|
||||
case
|
||||
lastTimestamp == currentTimestamp-1:
|
||||
lastTimestamp = currentTimestamp
|
||||
|
||||
case
|
||||
lastTimestamp == currentTimestamp-2,
|
||||
lastTimestamp == currentTimestamp-3,
|
||||
lastTimestamp == currentTimestamp:
|
||||
lastTimestamp += 1
|
||||
delta = 1
|
||||
|
||||
default:
|
||||
// Too much delay, let's update the last timestamp to current one.
|
||||
intlog.Printf(
|
||||
ctx,
|
||||
`too much delay, last timestamp "%d", current "%d"`,
|
||||
lastTimestamp, currentTimestamp,
|
||||
)
|
||||
lastTimestamp = currentTimestamp
|
||||
}
|
||||
s.lastTimestamp.Set(lastTimestamp)
|
||||
return delta
|
||||
}
|
@ -29,7 +29,7 @@ func TestSlash(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
|
||||
}
|
||||
t.AssertEQ(sched.week, c.expected)
|
||||
t.AssertEQ(sched.weekMap, c.expected)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -56,6 +56,9 @@ type Event struct {
|
||||
// Op is the bits union for file operations.
|
||||
type Op uint32
|
||||
|
||||
// internalPanic is the custom panic for internal usage.
|
||||
type internalPanic string
|
||||
|
||||
const (
|
||||
CREATE Op = 1 << iota
|
||||
WRITE
|
||||
@ -65,8 +68,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
repeatEventFilterDuration = time.Millisecond // Duration for repeated event filter.
|
||||
callbackExitEventPanicStr = "exit" // Custom exit event for internal usage.
|
||||
repeatEventFilterDuration = time.Millisecond // Duration for repeated event filter.
|
||||
callbackExitEventPanicStr internalPanic = "exit" // Custom exit event for internal usage.
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -44,14 +44,17 @@ type TimerOptions struct {
|
||||
Interval time.Duration // Interval is the interval escaped of the timer.
|
||||
}
|
||||
|
||||
// internalPanic is the custom panic for internal usage.
|
||||
type internalPanic string
|
||||
|
||||
const (
|
||||
StatusReady = 0 // Job or Timer is ready for running.
|
||||
StatusRunning = 1 // Job or Timer is already running.
|
||||
StatusStopped = 2 // Job or Timer is stopped.
|
||||
StatusClosed = -1 // Job or Timer is closed and waiting to be deleted.
|
||||
panicExit = "exit" // panicExit is used for custom job exit with panic.
|
||||
defaultTimerInterval = "100" // defaultTimerInterval is the default timer interval in milliseconds.
|
||||
commandEnvKeyForInterval = "gf.gtimer.interval" // commandEnvKeyForInterval is the key for command argument or environment configuring default interval duration for timer.
|
||||
StatusReady = 0 // Job or Timer is ready for running.
|
||||
StatusRunning = 1 // Job or Timer is already running.
|
||||
StatusStopped = 2 // Job or Timer is stopped.
|
||||
StatusClosed = -1 // Job or Timer is closed and waiting to be deleted.
|
||||
panicExit internalPanic = "exit" // panicExit is used for custom job exit with panic.
|
||||
defaultTimerInterval = "100" // defaultTimerInterval is the default timer interval in milliseconds.
|
||||
commandEnvKeyForInterval = "gf.gtimer.interval" // commandEnvKeyForInterval is the key for command argument or environment configuring default interval duration for timer.
|
||||
)
|
||||
|
||||
var (
|
||||
@ -154,11 +157,3 @@ func DelayAddOnce(ctx context.Context, delay time.Duration, interval time.Durati
|
||||
func DelayAddTimes(ctx context.Context, delay time.Duration, interval time.Duration, times int, job JobFunc) {
|
||||
defaultTimer.DelayAddTimes(ctx, delay, interval, times, job)
|
||||
}
|
||||
|
||||
// Exit is used in timing job internally, which exits and marks it closed from timer.
|
||||
// The timing job will be automatically removed from timer later. It uses "panic-recover"
|
||||
// mechanism internally implementing this feature, which is designed for simplification
|
||||
// and convenience.
|
||||
func Exit() {
|
||||
panic(panicExit)
|
||||
}
|
||||
|
15
os/gtimer/gtimer_exit.go
Normal file
15
os/gtimer/gtimer_exit.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gtimer
|
||||
|
||||
// Exit is used in timing job internally, which exits and marks it closed from timer.
|
||||
// The timing job will be automatically removed from timer later. It uses "panic-recover"
|
||||
// mechanism internally implementing this feature, which is designed for simplification
|
||||
// and convenience.
|
||||
func Exit() {
|
||||
panic(panicExit)
|
||||
}
|
@ -20,7 +20,7 @@ import (
|
||||
|
||||
func TestJob_Start_Stop_Close(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
job := timer.Add(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -43,7 +43,7 @@ func TestJob_Start_Stop_Close(t *testing.T) {
|
||||
|
||||
func TestJob_Singleton(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
job := timer.Add(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -62,7 +62,7 @@ func TestJob_Singleton(t *testing.T) {
|
||||
|
||||
func TestJob_SetTimes(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
job := timer.Add(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -76,7 +76,7 @@ func TestJob_SetTimes(t *testing.T) {
|
||||
|
||||
func TestJob_Run(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
job := timer.Add(ctx, 1000*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
|
@ -18,13 +18,9 @@ import (
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
func New() *gtimer.Timer {
|
||||
return gtimer.New()
|
||||
}
|
||||
|
||||
func TestTimer_Add_Close(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
//fmt.Println("start", time.Now())
|
||||
timer.Add(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
@ -53,7 +49,7 @@ func TestTimer_Add_Close(t *testing.T) {
|
||||
|
||||
func TestTimer_Start_Stop_Close(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.Add(ctx, 1000*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -75,7 +71,7 @@ func TestTimer_Start_Stop_Close(t *testing.T) {
|
||||
|
||||
func TestJob_Reset(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
job := timer.AddSingleton(ctx, 500*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -93,7 +89,7 @@ func TestJob_Reset(t *testing.T) {
|
||||
|
||||
func TestTimer_AddSingleton(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.AddSingleton(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -109,7 +105,7 @@ func TestTimer_AddSingleton(t *testing.T) {
|
||||
|
||||
func TestTimer_AddOnce(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.AddOnce(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -131,7 +127,7 @@ func TestTimer_AddOnce(t *testing.T) {
|
||||
|
||||
func TestTimer_AddTimes(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.AddTimes(ctx, 200*time.Millisecond, 2, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -143,7 +139,7 @@ func TestTimer_AddTimes(t *testing.T) {
|
||||
|
||||
func TestTimer_DelayAdd(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.DelayAdd(ctx, 200*time.Millisecond, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -157,7 +153,7 @@ func TestTimer_DelayAdd(t *testing.T) {
|
||||
|
||||
func TestTimer_DelayAddJob(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.DelayAddEntry(ctx, 200*time.Millisecond, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -171,7 +167,7 @@ func TestTimer_DelayAddJob(t *testing.T) {
|
||||
|
||||
func TestTimer_DelayAddSingleton(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.DelayAddSingleton(ctx, 200*time.Millisecond, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -187,7 +183,7 @@ func TestTimer_DelayAddSingleton(t *testing.T) {
|
||||
|
||||
func TestTimer_DelayAddOnce(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.DelayAddOnce(ctx, 200*time.Millisecond, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -205,7 +201,7 @@ func TestTimer_DelayAddOnce(t *testing.T) {
|
||||
|
||||
func TestTimer_DelayAddTimes(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.DelayAddTimes(ctx, 200*time.Millisecond, 500*time.Millisecond, 2, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
@ -246,24 +242,21 @@ func TestTimer_AddLessThanInterval(t *testing.T) {
|
||||
|
||||
func TestTimer_AddLeveledJob1(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
//glog.Print("start")
|
||||
timer.DelayAdd(ctx, 1000*time.Millisecond, 1000*time.Millisecond, func(ctx context.Context) {
|
||||
//glog.Print("add")
|
||||
array.Append(1)
|
||||
})
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
t.Assert(array.Len(), 0)
|
||||
time.Sleep(1300 * time.Millisecond)
|
||||
//glog.Print("check")
|
||||
t.Assert(array.Len(), 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTimer_Exit(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
timer := New()
|
||||
timer := gtimer.New()
|
||||
array := garray.New(true)
|
||||
timer.Add(ctx, 200*time.Millisecond, func(ctx context.Context) {
|
||||
array.Append(1)
|
||||
|
Loading…
Reference in New Issue
Block a user