-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ticker Package #1668
Ticker Package #1668
Conversation
3b9d6e0
to
f12d2fe
Compare
30decf4
to
eb5e221
Compare
eb5e221
to
6b90032
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Niiiiice, having a generic ticker interface should make testing much easier
ticker/ticker.go
Outdated
// NOTE: Part of the Ticker interface. | ||
func (t *ticker) Resume() { | ||
t.ticker = time.NewTicker(t.interval) | ||
t.ticks = t.ticker.C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like it would be simpler to just store t.ticker
, and return t.ticker.C
from Ticks()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe ticker.C
is buffered, so calling Stop()
might still produce an extra tick. See this example: https://play.golang.org/p/5I4Cm35wyao
Swapping out the channel for nil
ensures that this won't produce a tick when selected on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, in Tick
we can do
if t.ticker == nil {
return nil
}
return t.ticker.C
Should be equivalent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed!
htlcswitch/link.go
Outdated
@@ -1028,8 +986,8 @@ out: | |||
// If the downstream packet resulted in a non-empty | |||
// batch, reinstate the batch ticker so that it can be | |||
// cleared. | |||
if l.batchCounter > 0 && maybeBatchTick == nil { | |||
maybeBatchTick = l.cfg.BatchTicker.Start() | |||
if l.batchCounter > 0 && !l.cfg.BatchTicker.IsActive() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't need to check IsActive
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want to resume if we're already active, could cause us to reinitialize a ticker every time the batch is non-empty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could make Resume
a no-op if the ticker is already active.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh great idea!
ticker/ticker.go
Outdated
// false. | ||
// | ||
// NOTE: The behavior of a Ticker is undefined after calling Stop. | ||
Stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to distinguish pausing from stopping at this point? I think we should stick to Start/Stop
as that should be enough for our use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start
/Stop
is enough, but the mock ticker has a goroutine that needs to be cleaned up. In order to handle forced ticks while paused, i.e. keeping the goroutine alive, there needs to be a distinction between pausing, and actually tearing down the ticker
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still don't think a mock implementation detail should clutter up the interface, but I surrender to the overlords 🙇
2e5a269
to
bf5f7a3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I dig the new approach of the mock ticker where we can force ticks to trigger specific behaviors 😎
ticker/ticker.go
Outdated
|
||
// New returns a new ticker that signals with the given interval | ||
// when not paused. | ||
func New(interval time.Duration) *ticker { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should return the interface instead, otherwise we'd be returning an unexported identifier from an exported one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed in person, leaving as concrete type
ticker/mock.go
Outdated
"time" | ||
) | ||
|
||
// Mock implements the htlcswitch.Ticker interface, and provides a method of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/htlcswitch.Ticker/ticker.Ticker/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
ticker/mock.go
Outdated
} | ||
|
||
// NOTE: Part of the Ticker interface. | ||
func (m *Mock) Ticks() <-chan time.Time { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing godoc
, as well as all the others below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
peer.go
Outdated
@@ -416,6 +417,7 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) error { | |||
) | |||
if err != nil { | |||
lnChan.Stop() | |||
peerLog.Debugf("unable to add link %v: %v", chanPoint, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: capitalize first word for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed! also made peer disconnection logged to info, which seems useful as per discussion in #1630
9d50fea
to
e1acd1a
Compare
5494114
to
9381dee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🏒
The code reads well to me, and will definitely allow us to effectively test any scenario which depends on ticker behavior within the codebase. Before I merge this, will run it on the faucet for a bit to ensure that there hasn't been a regression in the improvements for idle CPU time.
bb43c81
to
c532718
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM ⏰
ticker/ticker.go
Outdated
Pause() | ||
|
||
// Stop suspends the underlying ticker, such that Ticks() stops | ||
// signaling at regular intervals, and permanently frees up any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra white space
ticker/ticker.go
Outdated
// false. | ||
// | ||
// NOTE: The behavior of a Ticker is undefined after calling Stop. | ||
Stop() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still don't think a mock implementation detail should clutter up the interface, but I surrender to the overlords 🙇
ticker/ticker.go
Outdated
} | ||
|
||
// ticker is the production implementation of the resumable Ticker interface. | ||
// This allows various components of the htlcswitch to toggle their need for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove htlcswitch reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
if l.batchCounter > 0 && maybeBatchTick == nil { | ||
maybeBatchTick = l.cfg.BatchTicker.Start() | ||
if l.batchCounter > 0 { | ||
l.cfg.BatchTicker.Resume() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so beautiful 😻
peer.go
Outdated
@@ -576,7 +578,7 @@ func (p *peer) Disconnect(reason error) { | |||
return | |||
} | |||
|
|||
peerLog.Tracef("Disconnecting %s, reason: %v", p, reason) | |||
peerLog.Infof("Disconnecting %s, reason: %v", p, reason) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debugf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
c532718
to
63149ed
Compare
comments addressed! re: interface clutter, it's not necessarily the mock ticker that's dictating this. In my mind, the aim is to generically encompass the possibility of tickers requiring cleanup that is different from |
This commit adds a Mock Ticker, implementing the Ticker interface. The ticker abides by the behavioral requirements of the production implementation, but also includes the ability to force feed ticks while the Ticker is paused. This commit also places the mock.go file behind the debug build flag. This allows us to import the MockTicker into our unit tests.
resumable ticker.Ticker interface
63149ed
to
8cc4681
Compare
This PR is an extension of #1659, and solidifies a generic
ticker.Ticker
interface for resumable tickers used within the switch. It replaces the existing tickers within the link and switch with the new resumable ticker, even though only the link's batch ticker actually utilizes the conditional aspect. However, this will allow for similar optimizations to made if others are found to be hotspots.This is required for #1551, as #1659 broke the previous method for testing link shutdowns. Previously, we used the batch ticker to test when the link becomes blocked during forwarding, so that we can test the ability for the link to be
Stop()
while synchronously forwarding Adds to the switch. The primary reason for this PR is thus to add theticker.Mock
, which satisfies the behavioral requirements of the production ticker, but also allows us to force feed ticks externally and arbitrarily.