Tenant-aware caching with automatic key prefixing.
This module provides tenant-scoped cache operations to prevent cache collisions between tenants in multi-tenant applications.
Key Features:
Usage: ;; Wrap existing cache with tenant context (def tenant-cache (create-tenant-cache cache tenant-id))
;; Use normally - keys automatically prefixed (ports/set-value! tenant-cache :user-123 user-data) ;; Actual key: "tenant:abc123:user-123"
;; Bulk operations work too (ports/set-many! tenant-cache {:user-1 data1 :user-2 data2}) ;; Keys: "tenant:abc123:user-1", "tenant:abc123:user-2"
Pattern: All cache keys are prefixed with: tenant:<tenant-id>:<original-key> Example: tenant:acme_corp:user:456
Tenant-aware caching with automatic key prefixing.
This module provides tenant-scoped cache operations to prevent cache
collisions between tenants in multi-tenant applications.
Key Features:
- Automatic tenant-id prefixing for all cache keys
- Transparent tenant context extraction from middleware
- Compatible with all ICache implementations (Redis, in-memory)
- No changes required to existing cache calls
- Complete cache isolation between tenants
Usage:
;; Wrap existing cache with tenant context
(def tenant-cache (create-tenant-cache cache tenant-id))
;; Use normally - keys automatically prefixed
(ports/set-value! tenant-cache :user-123 user-data)
;; Actual key: "tenant:abc123:user-123"
;; Bulk operations work too
(ports/set-many! tenant-cache {:user-1 data1 :user-2 data2})
;; Keys: "tenant:abc123:user-1", "tenant:abc123:user-2"
Pattern:
All cache keys are prefixed with: tenant:<tenant-id>:<original-key>
Example: tenant:acme_corp:user:456(create-tenant-cache cache tenant-id)Create a tenant-scoped cache wrapper.
Wraps an existing cache implementation with automatic tenant key prefixing. All cache operations will be scoped to the specified tenant.
Args: cache - Base cache implementation (ICache) tenant-id - Tenant identifier (string)
Returns: Tenant-scoped cache instance implementing all cache protocols
Example: (def base-cache (redis-cache/create-redis-cache pool)) (def tenant-cache (create-tenant-cache base-cache "acme-corp"))
;; Keys automatically prefixed (ports/set-value! tenant-cache :user-123 user-data) ;; Stored as: "tenant:acme-corp:user-123"
;; Complete cache isolation (def other-tenant (create-tenant-cache base-cache "globex")) (ports/get-value other-tenant :user-123) ;; => nil (different tenant namespace)
Notes:
Create a tenant-scoped cache wrapper. Wraps an existing cache implementation with automatic tenant key prefixing. All cache operations will be scoped to the specified tenant. Args: cache - Base cache implementation (ICache) tenant-id - Tenant identifier (string) Returns: Tenant-scoped cache instance implementing all cache protocols Example: (def base-cache (redis-cache/create-redis-cache pool)) (def tenant-cache (create-tenant-cache base-cache "acme-corp")) ;; Keys automatically prefixed (ports/set-value! tenant-cache :user-123 user-data) ;; Stored as: "tenant:acme-corp:user-123" ;; Complete cache isolation (def other-tenant (create-tenant-cache base-cache "globex")) (ports/get-value other-tenant :user-123) ;; => nil (different tenant namespace) Notes: - Thread-safe (delegates to underlying cache) - Supports all cache protocols (ICache, IBatchCache, etc.) - flush-all! only deletes tenant's keys, not entire cache - close! does NOT close underlying cache (shared resource)
(extract-tenant-cache cache request)Extract tenant-scoped cache from request context.
Convenience function to create tenant cache from middleware context.
Args: cache - Base cache implementation request - HTTP request with tenant context (from middleware)
Returns: Tenant-scoped cache or base cache if no tenant context
Example: (defn my-handler [request] (let [tenant-cache (extract-tenant-cache cache request) user-data (ports/get-value tenant-cache :user-123)] {:status 200 :body user-data}))
Middleware contract: Request must contain either: {:tenant {:id "tenant-123" ...}} OR {:tenant-id "tenant-123"}
If no tenant context found, returns base cache (public namespace).
Extract tenant-scoped cache from request context.
Convenience function to create tenant cache from middleware context.
Args:
cache - Base cache implementation
request - HTTP request with tenant context (from middleware)
Returns:
Tenant-scoped cache or base cache if no tenant context
Example:
(defn my-handler [request]
(let [tenant-cache (extract-tenant-cache cache request)
user-data (ports/get-value tenant-cache :user-123)]
{:status 200 :body user-data}))
Middleware contract:
Request must contain either:
{:tenant {:id "tenant-123" ...}} OR
{:tenant-id "tenant-123"}
If no tenant context found, returns base cache (public namespace).(tenant-cache-key tenant-id key)Prefix cache key with tenant ID for isolation.
Format: tenant:<tenant-id>:<original-key>
Args: tenant-id - Tenant identifier (string) key - Original cache key (string or keyword)
Returns: Prefixed key string
Examples: (tenant-cache-key "acme" :user-123) => "tenant:acme:user-123"
(tenant-cache-key "globex" "session:abc") => "tenant:globex:session:abc"
Prefix cache key with tenant ID for isolation. Format: tenant:<tenant-id>:<original-key> Args: tenant-id - Tenant identifier (string) key - Original cache key (string or keyword) Returns: Prefixed key string Examples: (tenant-cache-key "acme" :user-123) => "tenant:acme:user-123" (tenant-cache-key "globex" "session:abc") => "tenant:globex:session:abc"
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |