Skip to content

Commit e03b55a

Browse files
committed
test cache invalidation and add comments
1 parent 04e43c4 commit e03b55a

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

commit/plugin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,11 @@ func (p *Plugin) Outcome(
487487
if err != nil {
488488
lggr.Errorw("failed to get main outcome and cache invalidation", "err", err)
489489
}
490+
491+
// We invalidate the cache when we detect that inflight price updates appeared on-chain.
492+
// This is because at this moment we know that prices are updated
493+
// and want to instantly sync a potentially outdated cache.
494+
// Otherwise, oracles might re-observe the old prices in the next round.
490495
ctx = context.WithValue(ctx, consts.InvalidateCacheKey, invalidatePriceCache)
491496

492497
tokenPriceOutcome, err := p.tokenPriceProcessor.Outcome(
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package tokenprice
2+
3+
import (
4+
"context"
5+
"sync"
6+
"testing"
7+
"time"
8+
9+
"github.com/smartcontractkit/chainlink-common/pkg/logger"
10+
"github.com/smartcontractkit/chainlink-common/pkg/utils/tests"
11+
"github.com/stretchr/testify/require"
12+
13+
"github.com/smartcontractkit/chainlink-ccip/pkg/consts"
14+
cciptypes "github.com/smartcontractkit/chainlink-ccip/pkg/types/ccipocr3"
15+
)
16+
17+
func TestProcessor_Outcome_cacheInvalidation(t *testing.T) {
18+
lggr := logger.Test(t)
19+
ctx := tests.Context(t)
20+
21+
aobs := &asyncObserver{
22+
lggr: lggr,
23+
cancelFunc: nil,
24+
mu: sync.RWMutex{},
25+
triggerSyncChan: make(chan time.Time),
26+
}
27+
28+
p := &processor{
29+
lggr: lggr,
30+
obs: aobs,
31+
}
32+
33+
aobs.mu.Lock()
34+
aobs.tokenPriceMap = cciptypes.TokenPriceMap{"A": cciptypes.NewBigIntFromInt64(123)}
35+
aobs.mu.Unlock()
36+
37+
// cache is not invalidated with a normal context
38+
_, _ = p.Outcome(ctx, Outcome{}, Query{}, nil)
39+
aobs.mu.Lock()
40+
updates := aobs.tokenPriceMap
41+
aobs.mu.Unlock()
42+
require.Len(t, updates, 1)
43+
44+
// cache is not invalidated with invalidation context set to false
45+
ctx = context.WithValue(ctx, consts.InvalidateCacheKey, false)
46+
_, _ = p.Outcome(ctx, Outcome{}, Query{}, nil)
47+
aobs.mu.Lock()
48+
updates = aobs.tokenPriceMap
49+
aobs.mu.Unlock()
50+
require.Len(t, updates, 1)
51+
52+
// cache is invalidated with invalidation context set to true and a sync op is triggered
53+
wg := sync.WaitGroup{}
54+
go func() {
55+
<-aobs.triggerSyncChan
56+
}()
57+
ctx = context.WithValue(ctx, consts.InvalidateCacheKey, true)
58+
_, _ = p.Outcome(ctx, Outcome{}, Query{}, nil)
59+
aobs.mu.Lock()
60+
updates = aobs.tokenPriceMap
61+
aobs.mu.Unlock()
62+
require.Len(t, updates, 0)
63+
wg.Wait() // wait until receiving the sync operation signal
64+
}

0 commit comments

Comments
 (0)