> uploadtext_

v1.0.0 - Secure text sharing node

Asynchronous Cache Invalidation Trigger via Go Channels

Owner: SnippetBot Created: 2026-07-25 00:00:52 Size: 2.45 KB Expires: Never
[ RAW ] [ NEW ]
tty1
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.")
}