Skip to content

Commit

Permalink
Fixed an timing issue with near cache clear (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
tmiddlet2666 committed Mar 11, 2024
1 parent 26284bb commit 2178d2d
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 7 deletions.
3 changes: 3 additions & 0 deletions coherence/cache.go
Expand Up @@ -198,6 +198,9 @@ type NamedMap[K comparable, V any] interface {
// GetNearCacheStats returns the [CacheStats] for a near cache for a [NamedMap] or [NamedCache].
// If no near cache is defined, nil is returned.
GetNearCacheStats() CacheStats

// GetCacheName returns the cache name of the [NamedMap] or [NamedCache].
GetCacheName() string
}

// NamedCache is syntactically identical in behaviour to a NamedMap, but additionally implements
Expand Down
4 changes: 2 additions & 2 deletions coherence/common.go
Expand Up @@ -132,7 +132,7 @@ func executeClear[K comparable, V any](ctx context.Context, bc *baseClient[K, V]
_, err = bc.client.Clear(newCtx, &clearRequest)

// clear the near cache
if err != nil && nearCache != nil {
if nearCache != nil {
nearCache.Clear()
}

Expand Down Expand Up @@ -238,7 +238,7 @@ func executeTruncate[K comparable, V any](ctx context.Context, bc *baseClient[K,
_, err = bc.client.Truncate(newCtx, &request)

// clear the near cache
if err != nil && nearCache != nil {
if nearCache != nil {
nearCache.Clear()
}

Expand Down
6 changes: 3 additions & 3 deletions coherence/event.go
Expand Up @@ -186,7 +186,7 @@ func (l *mapLifecycleEvent[K, V]) Source() NamedMap[K, V] {

// String returns a string representation of a MapLifecycleEvent.
func (l *mapLifecycleEvent[K, V]) String() string {
return fmt.Sprintf("MapLifecycleEvent{source=%v, type=%s}", l.Source(), l.Type())
return fmt.Sprintf("MapLifecycleEvent{source=%v, type=%s}", l.Source().GetCacheName(), l.Type())
}

// MapEvent an event which indicates that the content of the NamedMap or
Expand Down Expand Up @@ -321,8 +321,8 @@ func (e *mapEvent[K, V]) String() string {
}
return *val
}
return fmt.Sprintf("MapEvent{source=%v, name=%s, type=%s, key=%s, oldValue=%s, newValue=%s}",
source, source.Name(), e.eventType, keyEval(key, keyErr), valueEval(oldValue, oldErr), valueEval(newValue, newErr))
return fmt.Sprintf("MapEvent{source=%v, name=%s, type=%s, key=%v, oldValue=%v, newValue=%v}",
source.GetCacheName(), source.Name(), e.eventType, keyEval(key, keyErr), valueEval(oldValue, oldErr), valueEval(newValue, newErr))
}

type SessionLifecycleListener interface {
Expand Down
5 changes: 5 additions & 0 deletions coherence/named_cache_client.go
Expand Up @@ -28,6 +28,11 @@ func (nc *NamedCacheClient[K, V]) getBaseClient() *baseClient[K, V] { // nolint
return &nc.baseClient
}

// GetCacheName returns the cache name of the [NamedCache].
func (nc *NamedCacheClient[K, V]) GetCacheName() string {
return nc.name
}

// AddLifecycleListener Adds a [MapLifecycleListener] that will receive events (truncated or released) that occur
// against the [NamedCache].
func (nc *NamedCacheClient[K, V]) AddLifecycleListener(listener MapLifecycleListener[K, V]) {
Expand Down
5 changes: 5 additions & 0 deletions coherence/named_map_client.go
Expand Up @@ -248,6 +248,11 @@ func RemoveIndex[K comparable, V, T, E any](ctx context.Context, nm NamedMap[K,
return executeRemoveIndex(ctx, nm.getBaseClient(), extractor)
}

// GetCacheName returns the cache name of the [NamedMap].
func (nm *NamedMapClient[K, V]) GetCacheName() string {
return nm.name
}

// AddLifecycleListener adds a [MapLifecycleListener] that will receive events (truncated or released) that occur
// against the [NamedMap].
func (nm *NamedMapClient[K, V]) AddLifecycleListener(listener MapLifecycleListener[K, V]) {
Expand Down
51 changes: 49 additions & 2 deletions test/e2e/standalone/near_cache_test.go
Expand Up @@ -39,8 +39,10 @@ func TestNearCacheOperationsAgainstMapAndCache(t *testing.T) {
nameMap coherence.NamedMap[int, Person]
test func(t *testing.T, namedCache coherence.NamedMap[int, Person])
}{
{"TestNearCacheBasicNamedMap", GetNearCacheNamedMap[int, Person](g, session, "near-cache-basic-map", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearCacheBasic},
{"TestNearCacheBasicNamedCache", GetNearCacheNamedCache[int, Person](g, session, "near-cache-basic-cache", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearCacheBasic},
{"RunTestNearCacheBasicNamedMap", GetNearCacheNamedMap[int, Person](g, session, "near-cache-basic-map", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearCacheBasic},
{"RunTestNearCacheBasicNamedCache", GetNearCacheNamedCache[int, Person](g, session, "near-cache-basic-cache", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearCacheBasic},
{"RunTestNearWithClearNamedCache", GetNearCacheNamedCache[int, Person](g, session, "near-cache-clear-cache", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearWithClear},
{"RunTestNearWithClearNamedMap", GetNearCacheNamedCache[int, Person](g, session, "near-cache-clear-map", coherence.WithNearCache(&nearCacheOptions10Seconds)), RunTestNearWithClear},
{"RunTestNearCacheRemovesNamedMap", GetNearCacheNamedMap[int, Person](g, session, "near-cache-removes-map", coherence.WithNearCache(&nearCacheOptions120Seconds)), RunTestNearCacheRemoves},
{"RunTestNearCacheRemovesNamedCache", GetNearCacheNamedCache[int, Person](g, session, "near-cache-removes-cache", coherence.WithNearCache(&nearCacheOptions120Seconds)), RunTestNearCacheRemoves},
{"RunTestNearCacheContainsKeyNamedMap", GetNearCacheNamedMap[int, Person](g, session, "near-cache-removes-map", coherence.WithNearCache(&nearCacheOptions120Seconds)), RunTestNearCacheContainsKey},
Expand Down Expand Up @@ -347,6 +349,51 @@ func RunTestNearCacheWithHighUnits(t *testing.T, namedMap coherence.NamedMap[int
g.Expect(namedMap.GetNearCacheStats().GetCachePrunes()).To(gomega.Equal(int64(1)))
}

// RunTestNearWithClear tests a near cache that issues puts, get then clears..
func RunTestNearWithClear(t *testing.T, namedMap coherence.NamedMap[int, Person]) {
var (
g = gomega.NewWithT(t)
err error
p1Get *Person
p2Get *Person
)

err = namedMap.Clear(ctx)
g.Expect(err).ShouldNot(gomega.HaveOccurred())

p1 := Person{ID: 1, Name: "p1"}
p2 := Person{ID: 2, Name: "p2"}

for i := 1; i < 100; i++ {
_, err = namedMap.Put(ctx, p1.ID, p1)
g.Expect(err).ShouldNot(gomega.HaveOccurred())

_, err = namedMap.Put(ctx, p2.ID, p2)
g.Expect(err).ShouldNot(gomega.HaveOccurred())

AssertSize[int, Person](g, namedMap, 2)

p1Get, err = namedMap.Get(ctx, p1.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(*p1Get).Should(gomega.Equal(p1))

p2Get, err = namedMap.Get(ctx, p2.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(*p2Get).Should(gomega.Equal(p2))

err = namedMap.Clear(ctx)
g.Expect(err).ShouldNot(gomega.HaveOccurred())

p1Get, err = namedMap.Get(ctx, p1.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(p1Get).Should(gomega.BeNil())

p2Get, err = namedMap.Get(ctx, p2.ID)
g.Expect(err).ShouldNot(gomega.HaveOccurred())
g.Expect(p2Get).Should(gomega.BeNil())
}
}

// RunTestNearCacheWithHighUnits tests near cache with high units of 100 and accessing entries to ensure they are not removed.
func RunTestNearCacheWithHighUnitsAccess(t *testing.T, namedMap coherence.NamedMap[int, Person]) {
var (
Expand Down

0 comments on commit 2178d2d

Please sign in to comment.