Add cache mechanism to KorAP client
Change-Id: Ie3f3d48611f039904f22a19cf6299a3c43fe8bbe
diff --git a/service/client.go b/service/client.go
index 0ea0b94..a7c532c 100644
--- a/service/client.go
+++ b/service/client.go
@@ -19,6 +19,7 @@
baseURL string
httpClient *http.Client
oauthClient *auth.OAuthClient
+ cache *Cache
}
// ClientOptions configures the KorAP client
@@ -26,6 +27,7 @@
BaseURL string
Timeout time.Duration
OAuthConfig *config.OAuthConfig
+ CacheConfig *CacheConfig
}
// NewClient creates a new KorAP API client
@@ -59,6 +61,23 @@
client.oauthClient = oauthClient
}
+ // Initialize cache if configuration is provided
+ if opts.CacheConfig != nil {
+ cache, err := NewCache(*opts.CacheConfig)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create cache: %w", err)
+ }
+ client.cache = cache
+ } else {
+ // Use default cache configuration
+ defaultConfig := DefaultCacheConfig()
+ cache, err := NewCache(defaultConfig)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create default cache: %w", err)
+ }
+ client.cache = cache
+ }
+
return client, nil
}
@@ -152,8 +171,31 @@
return c.doRequest(ctx, http.MethodPost, endpoint, bodyReader)
}
-// GetJSON performs a GET request and unmarshals the JSON response
+// GetJSON performs a GET request and unmarshals the JSON response with caching
func (c *Client) GetJSON(ctx context.Context, endpoint string, target any) error {
+ // Generate cache key for GET requests
+ cacheKey := ""
+ if c.cache != nil {
+ // For GET requests, we can cache based on endpoint and query parameters
+ // Extract query parameters from endpoint if any
+ endpointURL, _ := url.Parse(endpoint)
+ params := make(map[string]any)
+ for key, values := range endpointURL.Query() {
+ if len(values) > 0 {
+ params[key] = values[0]
+ }
+ }
+ cacheKey = c.cache.generateCacheKey("GET", endpointURL.Path, params)
+
+ // Try to get from cache first
+ if cachedData, found := c.cache.Get(ctx, cacheKey); found {
+ if err := json.Unmarshal(cachedData, target); err == nil {
+ return nil
+ }
+ // If unmarshal fails, continue with API call
+ }
+ }
+
resp, err := c.Get(ctx, endpoint)
if err != nil {
return err
@@ -164,10 +206,23 @@
return c.handleErrorResponse(resp)
}
- if err := json.NewDecoder(resp.Body).Decode(target); err != nil {
+ // Read response body
+ body, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return fmt.Errorf("failed to read response body: %w", err)
+ }
+
+ // Unmarshal JSON
+ if err := json.Unmarshal(body, target); err != nil {
return fmt.Errorf("failed to decode JSON response: %w", err)
}
+ // Cache the response for GET requests
+ if c.cache != nil && cacheKey != "" {
+ ttl := c.cache.GetTTLForEndpoint(endpoint)
+ c.cache.Set(ctx, cacheKey, body, ttl)
+ }
+
return nil
}
@@ -236,3 +291,16 @@
return nil
}
+
+// GetCache returns the cache instance (for testing and monitoring)
+func (c *Client) GetCache() *Cache {
+ return c.cache
+}
+
+// Close closes the client and cleans up resources
+func (c *Client) Close() error {
+ if c.cache != nil {
+ return c.cache.Close()
+ }
+ return nil
+}