Make common cache typed with generics (#2896)

Making typed common cache so that we don't use wrong types
across set/get methods and more higher-level methods can be
defined for cache.
Currently, we are not able to operate over all keys of the cache
due to generic types.
I also removed code comments around the cache.

Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
This commit is contained in:
Sanket Sudake
2024-01-04 10:46:32 +05:30
committed by GitHub
parent 12f8017d9b
commit 0c8573467b
8 changed files with 105 additions and 145 deletions
+36 -36
View File
@@ -34,33 +34,33 @@ const (
)
type (
Value struct {
Value[V any] struct {
ctime time.Time
atime time.Time
value interface{}
value V
}
Cache struct {
cache map[interface{}]*Value
Cache[K comparable, V any] struct {
cache map[K]*Value[V]
ctimeExpiry time.Duration
atimeExpiry time.Duration
requestChannel chan *request
requestChannel chan *request[K, V]
}
request struct {
request[K comparable, V any] struct {
requestType
key interface{}
value interface{}
responseChannel chan *response
key K
value V
responseChannel chan *response[K, V]
}
response struct {
response[K comparable, V any] struct {
error
existingValue interface{}
mapCopy map[interface{}]interface{}
value interface{}
existingValue V
mapCopy map[K]V
value V
}
)
func (c *Cache) IsOld(v *Value) bool {
func (c *Cache[K, V]) IsOld(v *Value[V]) bool {
if (c.ctimeExpiry != time.Duration(0)) && (time.Since(v.ctime) > c.ctimeExpiry) {
return true
}
@@ -72,12 +72,12 @@ func (c *Cache) IsOld(v *Value) bool {
return false
}
func MakeCache(ctimeExpiry, atimeExpiry time.Duration) *Cache {
c := &Cache{
cache: make(map[interface{}]*Value),
func MakeCache[K comparable, V any](ctimeExpiry, atimeExpiry time.Duration) *Cache[K, V] {
c := &Cache[K, V]{
cache: make(map[K]*Value[V]),
ctimeExpiry: ctimeExpiry,
atimeExpiry: atimeExpiry,
requestChannel: make(chan *request),
requestChannel: make(chan *request[K, V]),
}
go c.service()
if ctimeExpiry != time.Duration(0) || atimeExpiry != time.Duration(0) {
@@ -86,10 +86,10 @@ func MakeCache(ctimeExpiry, atimeExpiry time.Duration) *Cache {
return c
}
func (c *Cache) service() {
func (c *Cache[K, V]) service() {
for {
req := <-c.requestChannel
resp := &response{}
resp := &response[K, V]{}
switch req.requestType {
case GET:
val, ok := c.cache[req.key]
@@ -115,7 +115,7 @@ func (c *Cache) service() {
resp.existingValue = val.value
resp.error = ferror.MakeError(ferror.ErrorNameExists, "key already exists")
} else {
c.cache[req.key] = &Value{
c.cache[req.key] = &Value[V]{
value: req.value,
ctime: now,
atime: now,
@@ -133,7 +133,7 @@ func (c *Cache) service() {
}
// no response
case COPY:
resp.mapCopy = make(map[interface{}]interface{})
resp.mapCopy = make(map[K]V)
for k, v := range c.cache {
resp.mapCopy[k] = v.value
}
@@ -146,9 +146,9 @@ func (c *Cache) service() {
}
}
func (c *Cache) Get(key interface{}) (interface{}, error) {
respChannel := make(chan *response)
c.requestChannel <- &request{
func (c *Cache[K, V]) Get(key K) (V, error) {
respChannel := make(chan *response[K, V])
c.requestChannel <- &request[K, V]{
requestType: GET,
key: key,
responseChannel: respChannel,
@@ -159,9 +159,9 @@ func (c *Cache) Get(key interface{}) (interface{}, error) {
// if key exists in the cache, the new value is NOT set; instead an
// error and the old value are returned
func (c *Cache) Set(key interface{}, value interface{}) (interface{}, error) {
respChannel := make(chan *response)
c.requestChannel <- &request{
func (c *Cache[K, V]) Set(key K, value V) (V, error) {
respChannel := make(chan *response[K, V])
c.requestChannel <- &request[K, V]{
requestType: SET,
key: key,
value: value,
@@ -171,9 +171,9 @@ func (c *Cache) Set(key interface{}, value interface{}) (interface{}, error) {
return resp.existingValue, resp.error
}
func (c *Cache) Delete(key interface{}) error {
respChannel := make(chan *response)
c.requestChannel <- &request{
func (c *Cache[K, V]) Delete(key K) error {
respChannel := make(chan *response[K, V])
c.requestChannel <- &request[K, V]{
requestType: DELETE,
key: key,
responseChannel: respChannel,
@@ -182,9 +182,9 @@ func (c *Cache) Delete(key interface{}) error {
return resp.error
}
func (c *Cache) Copy() map[interface{}]interface{} {
respChannel := make(chan *response)
c.requestChannel <- &request{
func (c *Cache[K, V]) Copy() map[K]V {
respChannel := make(chan *response[K, V])
c.requestChannel <- &request[K, V]{
requestType: COPY,
responseChannel: respChannel,
}
@@ -192,10 +192,10 @@ func (c *Cache) Copy() map[interface{}]interface{} {
return resp.mapCopy
}
func (c *Cache) expiryService() {
func (c *Cache[K, V]) expiryService() {
for {
time.Sleep(time.Minute)
c.requestChannel <- &request{
c.requestChannel <- &request[K, V]{
requestType: EXPIRE,
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ func checkErr(err error) {
}
func TestCache(t *testing.T) {
c := MakeCache(100*time.Millisecond, 100*time.Millisecond)
c := MakeCache[string, string](100*time.Millisecond, 100*time.Millisecond)
_, err := c.Set("a", "b")
checkErr(err)