Skip to content

Commit 77a9007

Browse files
committed
feat: improve coverage of TempTableCache
1 parent 924ebe3 commit 77a9007

File tree

2 files changed

+84
-20
lines changed

2 files changed

+84
-20
lines changed

tests/utils_tests/utils_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,71 @@ func TestCheckAndGetLastCustomConceptVariableDef(t *testing.T) {
422422
}
423423

424424
}
425+
426+
func TestTempTableCache(t *testing.T) {
427+
setUp(t)
428+
var tempTableCache = &utils.CacheSimple{
429+
Data: make(map[string]interface{}),
430+
MaxSize: 3,
431+
}
432+
tempTableCache.Set("abc_key", "abc_value")
433+
value, exists := tempTableCache.Get("abc_key")
434+
if value == nil || !exists || value != "abc_value" {
435+
t.Errorf("Expected abc_value but got: exists=%v, value=%s", exists, value)
436+
}
437+
438+
// The cache has maxsize 3.
439+
// Scenario 1: After adding 3 new items, the .Get("abc_key") should result in empty,
440+
// as it will have been removed.
441+
// Scenario 2: The cache will keep items that were re-set (.Set) or recently retrieved (with .Get) "warm",
442+
// meaning that they get moved to the end of the queue of who gets dropped next from cache. So, in
443+
// this scenario, we want to add 2 new items, then .Get("abc_key"), then add one more item, and
444+
// assert that "abc_key" is still in, while the older of the 2 new items got dropped.
445+
446+
// (Scenario 1) Add 3 new items; "abc_key" should be removed
447+
tempTableCache.Set("key1", "value1")
448+
tempTableCache.Set("key2", "value2")
449+
tempTableCache.Set("key3", "value3")
450+
value, exists = tempTableCache.Get("abc_key")
451+
if exists {
452+
t.Errorf("Expected abc_key to be evicted, but it still exists with value: %v", value)
453+
}
454+
455+
// (Scenario 2) Keep "abc_key" warm and verify eviction order
456+
tempTableCache.Set("abc_key", "abc_value")
457+
tempTableCache.Set("key4", "value4")
458+
tempTableCache.Set("key5", "value5")
459+
_, _ = tempTableCache.Get("abc_key") // Access abc_key to keep it warm
460+
tempTableCache.Set("key6", "value6") // Since abc_key is warm, key4 should be evicted at this point
461+
value, exists = tempTableCache.Get("abc_key")
462+
if !exists || value != "abc_value" {
463+
t.Errorf("Expected abc_key to be retained, but it was evicted")
464+
}
465+
value, exists = tempTableCache.Get("key4")
466+
if exists {
467+
t.Errorf("Expected key4 to be evicted, but it still exists with value: %v", value)
468+
}
469+
470+
// Scenario 3: like scenario 2, but with Set. The .Set method
471+
// should be repeatable and also keeps the entry "warm"
472+
// (Scenario 2) Keep "abc_key" warm and verify eviction order
473+
tempTableCache.Set("abc_key", "abc_value")
474+
tempTableCache.Set("key4", "value4")
475+
tempTableCache.Set("key5", "value5")
476+
tempTableCache.Set("abc_key", "new_value1") // Reset abc_key to keep it warm, updating its value at the same time
477+
tempTableCache.Set("abc_key", "new_value2") // Reset abc_key to keep it warm, updating its value at the same time
478+
tempTableCache.Set("abc_key", "new_value3") // Reset abc_key to keep it warm, updating its value at the same time
479+
tempTableCache.Set("key6", "value6") // Since abc_key is warm, key4 should be evicted at this point
480+
value, exists = tempTableCache.Get("abc_key")
481+
if !exists || value != "new_value3" {
482+
t.Errorf("Expected abc_key to be retained, but it was evicted, or expected value does not match. Value: %s", value)
483+
}
484+
value, exists = tempTableCache.Get("key4")
485+
if exists {
486+
t.Errorf("Expected key4 to be evicted, but it still exists with value: %v", value)
487+
}
488+
value, exists = tempTableCache.Get("key5")
489+
if !exists || value != "value5" {
490+
t.Errorf("Expected abc_key to be retained, but it was evicted, or expected value does not match. Value: %s", value)
491+
}
492+
}

utils/temptablecache.go

+16-20
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import (
66

77
// TempTableCache is a thread-safe cache for storing temporary table mappings
88
var TempTableCache = &CacheSimple{
9-
data: make(map[string]interface{}),
10-
maxSize: 10,
9+
Data: make(map[string]interface{}),
10+
MaxSize: 100, // Note: this might need some tweaking if in a highly concurrent space...which is not the case now. Setting it too high risks too many temp tables..filling db.
1111
accessOrder: make([]string, 0),
1212
}
1313

1414
// Defines a thread-safe in-memory cache
1515
type CacheSimple struct {
16-
data map[string]interface{}
16+
Data map[string]interface{}
17+
MaxSize int
1718
mu sync.RWMutex
18-
maxSize int
1919
accessOrder []string // Keeps track of insertion order for cleanup
2020
}
2121

@@ -24,7 +24,7 @@ func (c *CacheSimple) Get(key string) (interface{}, bool) {
2424
c.mu.RLock()
2525
defer c.mu.RUnlock()
2626

27-
value, exists := c.data[key]
27+
value, exists := c.Data[key]
2828
// If the key already exists, update its position in the queue, so it is kept a bit longer:
2929
if exists {
3030
c.moveToEnd(key)
@@ -38,24 +38,24 @@ func (c *CacheSimple) Set(key string, value interface{}) {
3838
defer c.mu.Unlock()
3939

4040
// If the key already exists, update its value and move it to the end of the access order
41-
if _, exists := c.data[key]; exists {
42-
c.data[key] = value
41+
if _, exists := c.Data[key]; exists {
42+
c.Data[key] = value
4343
c.moveToEnd(key)
4444
return
4545
}
4646

4747
// Add the new key-value pair
48-
c.data[key] = value
48+
c.Data[key] = value
4949
c.accessOrder = append(c.accessOrder, key)
5050

5151
// If the cache exceeds its maximum size, remove the oldest / least recently accessed entry
52-
if len(c.accessOrder) > c.maxSize {
52+
if len(c.accessOrder) > c.MaxSize {
5353
oldestKey := c.accessOrder[0]
5454
c.accessOrder = c.accessOrder[1:]
55-
delete(c.data, oldestKey)
56-
55+
delete(c.Data, oldestKey)
56+
c.removeFromOrder(oldestKey)
5757
// Optionally drop the corresponding table
58-
dropTable(oldestKey)
58+
// dropTable(key) - probably not necessary if DB cleans up tmp tables automatically when session closes
5959
}
6060
}
6161

@@ -64,9 +64,11 @@ func (c *CacheSimple) Delete(key string) {
6464
c.mu.Lock()
6565
defer c.mu.Unlock()
6666

67-
if _, exists := c.data[key]; exists {
68-
delete(c.data, key)
67+
if _, exists := c.Data[key]; exists {
68+
delete(c.Data, key)
6969
c.removeFromOrder(key)
70+
// Optionally drop the corresponding table
71+
// dropTable(key) - probably not necessary if DB cleans up tmp tables automatically when session closes
7072
}
7173
}
7274

@@ -90,9 +92,3 @@ func (c *CacheSimple) removeFromOrder(key string) {
9092
}
9193
}
9294
}
93-
94-
// Drops a temporary table (to be implemented based on your database logic)
95-
func dropTable(key string) {
96-
// Add logic to drop the temporary table associated with the key
97-
// Example: db.Exec(fmt.Sprintf("DROP TABLE %s", key))
98-
}

0 commit comments

Comments
 (0)