From 98b2e8ab18a210e7503a34a5101815a5cd12b780 Mon Sep 17 00:00:00 2001 From: John Guo Date: Wed, 13 Jul 2022 20:20:38 +0800 Subject: [PATCH] improve panic...recover of exit feature for package ghttp/gtimer/gfsnotify (#2000) --- .github/workflows/gf.yml | 2 + net/ghttp/ghttp.go | 12 ++- os/gcache/gcache_adapter_memory_lru.go | 18 +--- os/gcron/gcron_entry.go | 2 +- os/gcron/gcron_schedule.go | 131 ++++++++++--------------- os/gcron/gcron_schedule_fix.go | 53 ++++++++++ os/gcron/gcron_z_unit_schedule_test.go | 2 +- os/gfsnotify/gfsnotify.go | 7 +- os/gtimer/gtimer.go | 25 ++--- os/gtimer/gtimer_exit.go | 15 +++ os/gtimer/gtimer_z_unit_entry_test.go | 8 +- os/gtimer/gtimer_z_unit_timer_test.go | 33 +++---- 12 files changed, 168 insertions(+), 140 deletions(-) create mode 100644 os/gcron/gcron_schedule_fix.go create mode 100644 os/gtimer/gtimer_exit.go diff --git a/.github/workflows/gf.yml b/.github/workflows/gf.yml index 5d629703c..b0f7ed284 100644 --- a/.github/workflows/gf.yml +++ b/.github/workflows/gf.yml @@ -8,6 +8,7 @@ on: - develop - personal/** - feature/** + - enhance/** - fix/** pull_request: @@ -16,6 +17,7 @@ on: - develop - personal/** - feature/** + - enhance/** - fix/** env: diff --git a/net/ghttp/ghttp.go b/net/ghttp/ghttp.go index c48367245..0de8a833c 100644 --- a/net/ghttp/ghttp.go +++ b/net/ghttp/ghttp.go @@ -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. diff --git a/os/gcache/gcache_adapter_memory_lru.go b/os/gcache/gcache_adapter_memory_lru.go index cf478996c..819954825 100644 --- a/os/gcache/gcache_adapter_memory_lru.go +++ b/os/gcache/gcache_adapter_memory_lru.go @@ -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) } } } diff --git a/os/gcron/gcron_entry.go b/os/gcron/gcron_entry.go index e878c902c..2fa2344ca 100644 --- a/os/gcron/gcron_entry.go +++ b/os/gcron/gcron_entry.go @@ -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"`, diff --git a/os/gcron/gcron_schedule.go b/os/gcron/gcron_schedule.go index 231472920..14c595a84 100644 --- a/os/gcron/gcron_schedule.go +++ b/os/gcron/gcron_schedule.go @@ -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 } diff --git a/os/gcron/gcron_schedule_fix.go b/os/gcron/gcron_schedule_fix.go new file mode 100644 index 000000000..d3dcb00c7 --- /dev/null +++ b/os/gcron/gcron_schedule_fix.go @@ -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 +} diff --git a/os/gcron/gcron_z_unit_schedule_test.go b/os/gcron/gcron_z_unit_schedule_test.go index 3a105bf8d..0714532e7 100644 --- a/os/gcron/gcron_z_unit_schedule_test.go +++ b/os/gcron/gcron_z_unit_schedule_test.go @@ -29,7 +29,7 @@ func TestSlash(t *testing.T) { t.Fatal(err) } - t.AssertEQ(sched.week, c.expected) + t.AssertEQ(sched.weekMap, c.expected) } }) diff --git a/os/gfsnotify/gfsnotify.go b/os/gfsnotify/gfsnotify.go index b6de60e0e..be58e2c37 100644 --- a/os/gfsnotify/gfsnotify.go +++ b/os/gfsnotify/gfsnotify.go @@ -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 ( diff --git a/os/gtimer/gtimer.go b/os/gtimer/gtimer.go index 3f6d801b4..5a00ca264 100644 --- a/os/gtimer/gtimer.go +++ b/os/gtimer/gtimer.go @@ -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) -} diff --git a/os/gtimer/gtimer_exit.go b/os/gtimer/gtimer_exit.go new file mode 100644 index 000000000..2ff3e698e --- /dev/null +++ b/os/gtimer/gtimer_exit.go @@ -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) +} diff --git a/os/gtimer/gtimer_z_unit_entry_test.go b/os/gtimer/gtimer_z_unit_entry_test.go index 77192568f..3aa4a8e0f 100644 --- a/os/gtimer/gtimer_z_unit_entry_test.go +++ b/os/gtimer/gtimer_z_unit_entry_test.go @@ -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) diff --git a/os/gtimer/gtimer_z_unit_timer_test.go b/os/gtimer/gtimer_z_unit_timer_test.go index a2df98054..5a564e90e 100644 --- a/os/gtimer/gtimer_z_unit_timer_test.go +++ b/os/gtimer/gtimer_z_unit_timer_test.go @@ -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)