Skip to content

Commit

Permalink
add reporter logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Freddy committed Nov 27, 2023
1 parent 33708d4 commit 03ac0fb
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 3 deletions.
12 changes: 9 additions & 3 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type CacheDriver[K any, T any] struct {
processor ProcessorI[K, T]
transformer TransformerI[T]
compressor CompressorI
reporter Reporter
}

func (cache *CacheDriver[T, K]) MissCount() int {
Expand Down Expand Up @@ -226,6 +227,7 @@ func New[K any, T any](
table: make(map[string]*CacheEntry[T], int(extendedCapacity)),
processor: processor,
compressor: lz4Compressor{},
reporter: &DefaultReporter{},
}
ret.head.prev = &ret.head
ret.head.next = &ret.head
Expand Down Expand Up @@ -305,6 +307,10 @@ func NewWithCompression[T any, K any](
return cache
}

func (cache *CacheDriver[T, K]) SetReporter(reporter Reporter) {
cache.reporter = reporter
}

// Insert entry as the first item of cache (mru)
func (cache *CacheDriver[T, K]) insertAsMru(entry *CacheEntry[K]) {
entry.prev = &cache.head
Expand Down Expand Up @@ -438,9 +444,9 @@ func (cache *CacheDriver[T, K]) RetrieveFromCacheOrCompute(request T,
entry, hit = cache.table[cacheKey]
if hit && currTime.Before(entry.expirationTime) {
cache.hitCount++
go cache.reporter.ReportHit()
cache.becomeMru(entry) //TODO: check if it is negative
cache.lock.Unlock()

entry.lock.Lock() // will block if it is computing
for entry.state == COMPUTING { // this guard is for protection; it should never be true
entry.cond.Wait() // it will wake up when result arrives
Expand Down Expand Up @@ -498,10 +504,10 @@ func (cache *CacheDriver[T, K]) RetrieveFromCacheOrCompute(request T,

entry.state = COMPUTING

go cache.reporter.ReportMiss()
cache.missCount++
cache.lock.Unlock() // release global lock before to take the entry lock

entry.lock.Lock() // other requests will wait for until postProcessedResponse is gotten
entry.lock.Lock() // other requests will wait for until postProcessedResponse is gotten
defer entry.lock.Unlock()

retVal, requestError := cache.processor.CacheMissSolver(request, other...)
Expand Down
57 changes: 57 additions & 0 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,8 +807,65 @@ func TestOtherInCache(t *testing.T) {
assert.NotNil(err)
assert.Equal(err.Code, Status5xx)
assert.Equal("", value)

}

type MockReporter struct {
missCount chan int
hitCount chan int
}

func (m *MockReporter) ReportMiss() {
m.missCount <- 1
}

func (m *MockReporter) ReportHit() {
m.hitCount <- 1
}

func TestReporter(t *testing.T) {

assert := assert.New(t)
processor := mocks.NewProcessorI[*RequestEntry, *RequestEntry](t)
reporter := &MockReporter{
missCount: make(chan int, 1),
hitCount: make(chan int, 1),
}
cache := New[*RequestEntry, *RequestEntry](
Capacity,
.4,
2*time.Second,
time.Second,
processor,
)

cache.SetReporter(reporter)

processor.EXPECT().ToMapKey(mock.Anything).Return("Keats", nil).Times(1)
processor.EXPECT().CacheMissSolver(mock.Anything).Return(nil, nil).Times(1)
_, err := cache.RetrieveFromCacheOrCompute(&RequestEntry{})
assert.Nil(err)
missCount := <-reporter.missCount
assert.Equal(1, missCount)

processor.EXPECT().ToMapKey(mock.Anything).Return("Keats", nil).Times(1)
_, err = cache.RetrieveFromCacheOrCompute(&RequestEntry{})
assert.Nil(err)
hitCount := <-reporter.hitCount
assert.Equal(1, hitCount)

}

// reporter.AssertNumberOfCalls(t, "ReportMiss", 1)
// reporter.AssertNumberOfCalls(t, "ReportHit", 0)

// processor.EXPECT().ToMapKey(mock.Anything).Return("Keats", nil).Times(1)
// processor.EXPECT().CacheMissSolver(mock.Anything).Return(nil, nil).Times(1)
// _, err = cache.RetrieveFromCacheOrCompute(&RequestEntry{})
// assert.Nil(err)
// reporter.AssertNumberOfCalls(t, "ReportMiss", 1)
// reporter.AssertNumberOfCalls(t, "ReportHit", 1)

// benchmark to test the performance of the cache
// when the processor should perform an addition task
type BenchProcessor struct{}
Expand Down
7 changes: 7 additions & 0 deletions default_reporter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package gw_cache

type DefaultReporter struct{}

func (d *DefaultReporter) ReportMiss() {}

func (d *DefaultReporter) ReportHit() {}
12 changes: 12 additions & 0 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ type TransformerI[T any] interface {
ValueToBytes(T) ([]byte, error)
}

// Reporter is the interface that wraps the basic ReportMiss and ReportHit methods
//
// # ReportMiss is used to report a cache miss
//
// # ReportHit is used to report a cache hit
//
//go:generate mockery --name Reporter --with-expecter=true --filename=reporter_mock.go
type Reporter interface {
ReportMiss()
ReportHit()
}

type DefaultTransformer[T any] struct{}

func (_ *DefaultTransformer[T]) BytesToValue(in []byte) (T, error) {
Expand Down

0 comments on commit 03ac0fb

Please sign in to comment.