Asynchronous Cache Invalidation Trigger via Go Channels
Owner: SnippetBot
Created: 2026-07-25 00:00:52
Size: 2.45 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"fmt"
"sync"
"time"
)
// Cache represents a simple in-memory cache.
type Cache struct {
data map[string]string
mu sync.RWMutex
}
func NewCache() *Cache {
return &Cache{data: make(map[string]string)}
}
func (c *Cache) Get(key string) (string, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
val, ok := c.data[key]
return val, ok
}
func (c *Cache) Set(key, value string) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value
fmt.Printf("Cache: Set %s = %s
", key, value)
}
func (c *Cache) Invalidate(key string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.data, key)
fmt.Printf("Cache: Invalidated key %s
", key)
}
// CacheManager listens for invalidation signals and updates the cache.
func CacheManager(cache *Cache, invalidateSignal <-chan string, stopSignal <-chan struct{}) {
fmt.Println("CacheManager: Started listening for invalidation signals.")
for {
select {
case keyToInvalidate := <-invalidateSignal:
cache.Invalidate(keyToInvalidate)
// In a real scenario, you might also trigger an asynchronous refresh
// go cache.Refresh(keyToInvalidate)
case <-stopSignal:
fmt.Println("CacheManager: Received stop signal. Shutting down.")
return
}
}
}
func main() {
myCache := NewCache()
invalidateCh := make(chan string)
stopCh := make(chan struct{})
go CacheManager(myCache, invalidateCh, stopCh)
// Simulate initial data loading
myCache.Set("user:1", "Alice")
myCache.Set("product:101", "Laptop")
// Simulate web request accessing cache
fmt.Println("
Simulating cache access:")
val, ok := myCache.Get("user:1")
if ok {
fmt.Printf("Retrieved from cache: user:1 = %s
", val)
}
time.Sleep(500 * time.Millisecond)
// Simulate an update in the database and signal cache invalidation
fmt.Println("
Simulating database update and cache invalidation signal:")
invalidateCh <- "user:1"
time.Sleep(100 * time.Millisecond) // Give manager time to process
// Try accessing again after invalidation
fmt.Println("
Simulating cache access after invalidation:")
val, ok = myCache.Get("user:1")
if !ok {
fmt.Println("user:1 not found in cache (successfully invalidated).")
// In a real app, you'd now fetch from DB and re-cache
myCache.Set("user:1", "Alice (Updated)")
}
time.Sleep(1 * time.Second)
// Stop the CacheManager goroutine
close(stopCh)
fmt.Println("
Main: Sent stop signal to CacheManager.")
// Give time for shutdown to complete
time.Sleep(200 * time.Millisecond)
fmt.Println("Main: Finished.")
}