Add cache mechanism to KorAP client
Change-Id: Ie3f3d48611f039904f22a19cf6299a3c43fe8bbe
diff --git a/service/client_test.go b/service/client_test.go
index 0009d71..6ebb61e 100644
--- a/service/client_test.go
+++ b/service/client_test.go
@@ -318,3 +318,154 @@
assert.Equal(t, "https://example.com/", client.GetBaseURL())
}
+
+// TestClientCaching tests client caching functionality
+func TestClientCaching(t *testing.T) {
+ requestCount := 0
+
+ // Create a mock server that counts requests
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ requestCount++
+ // Use URL.Path to get clean path without query parameters
+ path := r.URL.Path
+ switch path {
+ case "/cached":
+ w.Header().Set("Content-Type", "application/json")
+ json.NewEncoder(w).Encode(map[string]interface{}{
+ "data": "cached response",
+ "request_count": requestCount,
+ })
+ case "/search":
+ w.Header().Set("Content-Type", "application/json")
+ query := r.URL.Query().Get("q")
+ json.NewEncoder(w).Encode(map[string]interface{}{
+ "query": query,
+ "results": []string{"result1", "result2"},
+ "request_count": requestCount,
+ })
+ default:
+ w.WriteHeader(http.StatusNotFound)
+ json.NewEncoder(w).Encode(map[string]string{
+ "error": fmt.Sprintf("Not found: %s", path),
+ })
+ }
+ }))
+ defer server.Close()
+
+ t.Run("cache enabled", func(t *testing.T) {
+ cacheConfig := DefaultCacheConfig()
+ cacheConfig.DefaultTTL = 1 * time.Minute
+
+ client, err := NewClient(ClientOptions{
+ BaseURL: server.URL,
+ CacheConfig: &cacheConfig,
+ })
+ assert.NoError(t, err)
+ defer client.Close()
+
+ ctx := context.Background()
+ requestCount = 0
+
+ // First request - should hit the server
+ var result1 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result1)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(1), result1["request_count"])
+
+ // Second request - should hit the cache
+ var result2 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result2)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(1), result2["request_count"]) // Same as first request
+
+ // Verify cache statistics
+ cache := client.GetCache()
+ assert.NotNil(t, cache)
+ stats := cache.Stats()
+ assert.True(t, stats["enabled"].(bool))
+ assert.Equal(t, 1, stats["size"].(int))
+ assert.True(t, stats["hits"].(int64) > 0)
+ })
+
+ t.Run("cache disabled", func(t *testing.T) {
+ cacheConfig := CacheConfig{Enabled: false}
+
+ client, err := NewClient(ClientOptions{
+ BaseURL: server.URL,
+ CacheConfig: &cacheConfig,
+ })
+ assert.NoError(t, err)
+ defer client.Close()
+
+ ctx := context.Background()
+ requestCount = 0
+
+ // Both requests should hit the server
+ var result1 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result1)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(1), result1["request_count"])
+
+ var result2 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result2)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(2), result2["request_count"]) // Different from first request
+
+ // Verify cache is disabled
+ cache := client.GetCache()
+ assert.NotNil(t, cache)
+ stats := cache.Stats()
+ assert.False(t, stats["enabled"].(bool))
+ })
+
+ t.Run("cache expiry", func(t *testing.T) {
+ cacheConfig := CacheConfig{
+ Enabled: true,
+ DefaultTTL: 50 * time.Millisecond,
+ SearchTTL: 50 * time.Millisecond,
+ MetadataTTL: 50 * time.Millisecond,
+ MaxSize: 100,
+ }
+
+ client, err := NewClient(ClientOptions{
+ BaseURL: server.URL,
+ CacheConfig: &cacheConfig,
+ })
+ assert.NoError(t, err)
+ defer client.Close()
+
+ ctx := context.Background()
+ requestCount = 0
+
+ // First request
+ var result1 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result1)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(1), result1["request_count"])
+
+ // Wait for cache to expire
+ time.Sleep(100 * time.Millisecond)
+
+ // Second request should hit server again
+ var result2 map[string]interface{}
+ err = client.GetJSON(ctx, "/cached", &result2)
+ assert.NoError(t, err)
+ assert.Equal(t, float64(2), result2["request_count"])
+ })
+}
+
+// TestClientDefaultCache tests that clients get default cache when no config is provided
+func TestClientDefaultCache(t *testing.T) {
+ client, err := NewClient(ClientOptions{
+ BaseURL: "https://example.com",
+ })
+ assert.NoError(t, err)
+ defer client.Close()
+
+ cache := client.GetCache()
+ assert.NotNil(t, cache)
+
+ stats := cache.Stats()
+ assert.True(t, stats["enabled"].(bool))
+ assert.Equal(t, 1000, stats["max_size"].(int))
+}