Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
8a3e8830
Unverified
Commit
8a3e8830
authored
Jul 19, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-service: Support NewTimer in Clock
parent
d8db966b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
77 additions
and
0 deletions
+77
-0
clock.go
op-service/clock/clock.go
+17
-0
deterministic.go
op-service/clock/deterministic.go
+20
-0
deterministic_test.go
op-service/clock/deterministic_test.go
+40
-0
No files found.
op-service/clock/clock.go
View file @
8a3e8830
...
@@ -22,6 +22,10 @@ type Clock interface {
...
@@ -22,6 +22,10 @@ type Clock interface {
// The duration d must be greater than zero; if not, NewTicker will
// The duration d must be greater than zero; if not, NewTicker will
// panic. Stop the ticker to release associated resources.
// panic. Stop the ticker to release associated resources.
NewTicker
(
d
time
.
Duration
)
Ticker
NewTicker
(
d
time
.
Duration
)
Ticker
// NewTimer creates a new Timer that will send
// the current time on its channel after at least duration d.
NewTimer
(
d
time
.
Duration
)
Timer
}
}
// A Ticker holds a channel that delivers "ticks" of a clock at intervals
// A Ticker holds a channel that delivers "ticks" of a clock at intervals
...
@@ -42,9 +46,14 @@ type Ticker interface {
...
@@ -42,9 +46,14 @@ type Ticker interface {
// Timer represents a single event.
// Timer represents a single event.
type
Timer
interface
{
type
Timer
interface
{
// Ch returns the channel for the ticker. Equivalent to time.Timer.C
Ch
()
<-
chan
time
.
Time
// Stop prevents the Timer from firing.
// Stop prevents the Timer from firing.
// It returns true if the call stops the timer, false if the timer has already
// It returns true if the call stops the timer, false if the timer has already
// expired or been stopped.
// expired or been stopped.
// Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly.
//
//
// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
// has already expired and the function f has been started in its own goroutine;
// has already expired and the function f has been started in its own goroutine;
...
@@ -80,10 +89,18 @@ func (s systemClock) NewTicker(d time.Duration) Ticker {
...
@@ -80,10 +89,18 @@ func (s systemClock) NewTicker(d time.Duration) Ticker {
return
&
SystemTicker
{
time
.
NewTicker
(
d
)}
return
&
SystemTicker
{
time
.
NewTicker
(
d
)}
}
}
func
(
s
systemClock
)
NewTimer
(
d
time
.
Duration
)
Timer
{
return
&
SystemTimer
{
time
.
NewTimer
(
d
)}
}
type
SystemTimer
struct
{
type
SystemTimer
struct
{
*
time
.
Timer
*
time
.
Timer
}
}
func
(
t
*
SystemTimer
)
Ch
()
<-
chan
time
.
Time
{
return
t
.
C
}
func
(
s
systemClock
)
AfterFunc
(
d
time
.
Duration
,
f
func
())
Timer
{
func
(
s
systemClock
)
AfterFunc
(
d
time
.
Duration
,
f
func
())
Timer
{
return
&
SystemTimer
{
time
.
AfterFunc
(
d
,
f
)}
return
&
SystemTimer
{
time
.
AfterFunc
(
d
,
f
)}
}
}
op-service/clock/deterministic.go
View file @
8a3e8830
...
@@ -31,6 +31,7 @@ func (t task) fire(now time.Time) bool {
...
@@ -31,6 +31,7 @@ func (t task) fire(now time.Time) bool {
type
timer
struct
{
type
timer
struct
{
f
func
()
f
func
()
ch
chan
time
.
Time
due
time
.
Time
due
time
.
Time
stopped
bool
stopped
bool
run
bool
run
bool
...
@@ -53,6 +54,10 @@ func (t *timer) fire(now time.Time) bool {
...
@@ -53,6 +54,10 @@ func (t *timer) fire(now time.Time) bool {
return
false
return
false
}
}
func
(
t
*
timer
)
Ch
()
<-
chan
time
.
Time
{
return
t
.
ch
}
func
(
t
*
timer
)
Stop
()
bool
{
func
(
t
*
timer
)
Stop
()
bool
{
t
.
Lock
()
t
.
Lock
()
defer
t
.
Unlock
()
defer
t
.
Unlock
()
...
@@ -171,6 +176,21 @@ func (s *DeterministicClock) NewTicker(d time.Duration) Ticker {
...
@@ -171,6 +176,21 @@ func (s *DeterministicClock) NewTicker(d time.Duration) Ticker {
return
t
return
t
}
}
func
(
s
*
DeterministicClock
)
NewTimer
(
d
time
.
Duration
)
Timer
{
s
.
lock
.
Lock
()
defer
s
.
lock
.
Unlock
()
ch
:=
make
(
chan
time
.
Time
,
1
)
t
:=
&
timer
{
f
:
func
()
{
ch
<-
s
.
now
},
ch
:
ch
,
due
:
s
.
now
.
Add
(
d
),
}
s
.
addPending
(
t
)
return
t
}
func
(
s
*
DeterministicClock
)
addPending
(
t
action
)
{
func
(
s
*
DeterministicClock
)
addPending
(
t
action
)
{
s
.
pending
=
append
(
s
.
pending
,
t
)
s
.
pending
=
append
(
s
.
pending
,
t
)
select
{
select
{
...
...
op-service/clock/deterministic_test.go
View file @
8a3e8830
...
@@ -217,6 +217,46 @@ func TestNewTicker(t *testing.T) {
...
@@ -217,6 +217,46 @@ func TestNewTicker(t *testing.T) {
})
})
}
}
func
TestNewTimer
(
t
*
testing
.
T
)
{
t
.
Run
(
"FireOnceAfterDuration"
,
func
(
t
*
testing
.
T
)
{
clock
:=
NewDeterministicClock
(
time
.
UnixMilli
(
1000
))
timer
:=
clock
.
NewTimer
(
5
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
0
,
"should not fire immediately"
)
clock
.
AdvanceTime
(
4
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
0
,
"should not fire before due"
)
clock
.
AdvanceTime
(
1
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
1
,
"should fire when due"
)
require
.
Equal
(
t
,
clock
.
Now
(),
<-
timer
.
Ch
(),
"should post current time"
)
clock
.
AdvanceTime
(
6
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
0
,
"should not fire when due again"
)
})
t
.
Run
(
"StopBeforeExecuted"
,
func
(
t
*
testing
.
T
)
{
clock
:=
NewDeterministicClock
(
time
.
UnixMilli
(
1000
))
timer
:=
clock
.
NewTimer
(
5
*
time
.
Second
)
require
.
True
(
t
,
timer
.
Stop
())
clock
.
AdvanceTime
(
10
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
0
,
"should not fire after stop"
)
})
t
.
Run
(
"StopAfterExecuted"
,
func
(
t
*
testing
.
T
)
{
clock
:=
NewDeterministicClock
(
time
.
UnixMilli
(
1000
))
timer
:=
clock
.
NewTimer
(
5
*
time
.
Second
)
clock
.
AdvanceTime
(
10
*
time
.
Second
)
require
.
Len
(
t
,
timer
.
Ch
(),
1
,
"should fire when due"
)
require
.
Equal
(
t
,
clock
.
Now
(),
<-
timer
.
Ch
(),
"should post current time"
)
require
.
False
(
t
,
timer
.
Stop
())
})
}
func
TestWaitForPending
(
t
*
testing
.
T
)
{
func
TestWaitForPending
(
t
*
testing
.
T
)
{
t
.
Run
(
"DoNotBlockWhenAlreadyPending"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"DoNotBlockWhenAlreadyPending"
,
func
(
t
*
testing
.
T
)
{
clock
:=
NewDeterministicClock
(
time
.
UnixMilli
(
1000
))
clock
:=
NewDeterministicClock
(
time
.
UnixMilli
(
1000
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment