Skip to content

Commit a5b0de2

Browse files
committed
Do not wake-up notifier if preference has been set to its previous one
Signed-off-by: Yacov Manevich <[email protected]>
1 parent 8d76a16 commit a5b0de2

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

snow/engine/snowman/block/notifier.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ type ChangeNotifier struct {
3131
// This is needed in case a block has been accepted that changes when a VM considers the need to build a block.
3232
// In order for the subscription to be correlated to the latest data, it needs to be retried.
3333
OnChange func()
34+
// lastPref is the last block ID that was set as preferred via SetPreference.
35+
lastPref ids.ID
36+
invoked bool
3437
}
3538

3639
func (cn *ChangeNotifier) GetAncestors(ctx context.Context, blkID ids.ID, maxBlocksNum int, maxBlocksSize int, maxBlocksRetrivalTime time.Duration) ([][]byte, error) {
@@ -83,7 +86,13 @@ func (cn *ChangeNotifier) GetStateSummary(ctx context.Context, summaryHeight uin
8386
}
8487

8588
func (cn *ChangeNotifier) SetPreference(ctx context.Context, blkID ids.ID) error {
86-
defer cn.OnChange()
89+
// Only call OnChange if the preference has changed.
90+
if !cn.invoked || cn.lastPref != blkID {
91+
cn.lastPref = blkID
92+
cn.invoked = true
93+
defer cn.OnChange()
94+
}
95+
8796
return cn.ChainVM.SetPreference(ctx, blkID)
8897
}
8998

snow/engine/snowman/block/notifier_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,38 @@ func TestChangeNotifierNormal(t *testing.T) {
224224
})
225225
}
226226
}
227+
228+
func TestChangeNotifierSetPreference(t *testing.T) {
229+
ctrl := gomock.NewController(t)
230+
231+
tvm := blockmock.NewFullVM(ctrl)
232+
tvm.EXPECT().SetPreference(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
233+
234+
var invoked bool
235+
nf := block.ChangeNotifier{
236+
OnChange: func() {
237+
invoked = true
238+
},
239+
ChainVM: tvm,
240+
}
241+
242+
// First time SetPreference is called, it should invoke OnChange
243+
require.NoError(t, nf.SetPreference(context.Background(), ids.Empty), "expected SetPreference to succeed")
244+
require.True(t, invoked, "expected to have been invoked on first SetPreference call")
245+
246+
invoked = false
247+
// Second time SetPreference is called with the same block ID, it should not invoke OnChange
248+
require.NoError(t, nf.SetPreference(context.Background(), ids.Empty), "expected SetPreference to succeed on second call with same block ID")
249+
require.False(t, invoked, "expected not to have been invoked on second SetPreference call with same block ID")
250+
251+
invoked = false
252+
// Third time SetPreference is called with a different block ID, it should invoke OnChange again
253+
testID := ids.GenerateTestID()
254+
require.NoError(t, nf.SetPreference(context.Background(), testID), "expected SetPreference to succeed on third call with different block ID")
255+
require.True(t, invoked, "expected to have been invoked on third SetPreference call with different block ID")
256+
257+
invoked = false
258+
// Fourth time SetPreference is called with the same block ID, it should not invoke OnChange
259+
require.NoError(t, nf.SetPreference(context.Background(), testID), "expected SetPreference to succeed on fourth call with same block ID")
260+
require.False(t, invoked, "expected not to have been invoked on fourth SetPreference call with same block ID")
261+
}

0 commit comments

Comments
 (0)