ctxcache(context caching middleware)

Thread-safe context caching for HTTP requests, enabling efficient data sharing within request lifecycles without repeated computations or database queries.

The ctxcache module provides thread-safe context caching for HTTP requests, enabling efficient data sharing within request lifecycles without repeated computations or database queries.

Features

  • Thread-safe caching using sync.Map for concurrent access
  • Generic type support with compile-time type safety
  • Context-based lifecycle - cache lives within request context
  • Key existence checking with HasKey function
  • Zero-value handling for missing keys
  • Any key type support - strings, structs, or custom types

Basic Usage

Initialize ctxcache as your first middleware (recommended for frameworks like Gin):

 1func InitRouter() {
 2    srv := gin.Default()
 3
 4    // Initialize context cache first
 5    srv.Use(func(c *gin.Context) {
 6        ctx := ctxcache.Init(c.Request.Context())
 7        c.Request = c.Request.WithContext(ctx)
 8        c.Next()
 9    })
10    
11    // Other middlewares follow
12    // srv.Use(CORS())
13    // srv.Use(Auth())
14}

Storing and Retrieving Data

 1// Store different types of data
 2ctxcache.Store(ctx, "user_id", int64(12345))
 3ctxcache.Store(ctx, "user_name", "john_doe")
 4ctxcache.Store(ctx, "is_admin", true)
 5
 6// Store complex structures
 7type User struct {
 8    ID   int64  `json:"id"`
 9    Name string `json:"name"`
10}
11user := User{ID: 123, Name: "John"}
12ctxcache.Store(ctx, "current_user", user)
13
14// Retrieve with type safety
15userID, ok := ctxcache.Get[int64](ctx, "user_id")
16if !ok {
17    // Handle missing key
18    return errors.New("user_id not found in cache")
19}
20
21userName, ok := ctxcache.Get[string](ctx, "user_name")
22if ok {
23    fmt.Printf("User: %s (ID: %d)\n", userName, userID)
24}
25
26// Retrieve complex structures
27cachedUser, ok := ctxcache.Get[User](ctx, "current_user")
28if ok {
29    fmt.Printf("Current user: %+v\n", cachedUser)
30}

Advanced Usage

 1// Using custom key types for better organization
 2type CacheKey struct {
 3    Module string
 4    ID     int64
 5}
 6
 7userKey := CacheKey{Module: "user", ID: 123}
 8ctxcache.Store(ctx, userKey, userData)
 9
10// Check if key exists before retrieval
11if ctxcache.HasKey(ctx, userKey) {
12    user, _ := ctxcache.Get[User](ctx, userKey)
13    // Process user data
14}
15
16// Cache expensive operations
17func GetUserPermissions(ctx context.Context, userID int64) ([]string, error) {
18    cacheKey := fmt.Sprintf("permissions_%d", userID)
19    
20    // Check cache first
21    if permissions, ok := ctxcache.Get[[]string](ctx, cacheKey); ok {
22        return permissions, nil
23    }
24    
25    // Expensive database query
26    permissions, err := database.GetUserPermissions(userID)
27    if err != nil {
28        return nil, err
29    }
30    
31    // Cache the result
32    ctxcache.Store(ctx, cacheKey, permissions)
33    return permissions, nil
34}