• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

optimizely / agent / 19177705593

07 Nov 2025 06:32PM UTC coverage: 86.321% (+0.1%) from 86.21%
19177705593

push

github

web-flow
[FSSDK-11990] Add Redis cache support for CMAB following ODP cache pattern (#447)

* Add Redis cache support for CMAB following ODP cache pattern

Implement Redis caching for CMAB (Contextual Multi-Armed Bandit)
decisions using the same plugin-based architecture as ODP cache.

Changes:
- Add cmabcache plugin with registry and service implementations
- Implement in-memory LRU cache (size: 10000, TTL: 30m)
- Implement Redis cache with JSON serialization
- Update CMABCacheConfig from struct to service-based map config
- Add comprehensive unit and integration tests (all passing)
- Update config.yaml with new service-based CMAB cache format
- Add cmabcache plugin import to main.go
- Fix cache.go to initialize CMAB cache via plugin system
- Add tests to improve CMAB config parsing coverage

Test coverage:
- In-memory cache tests: 8/8 passing
- Redis cache tests: 8/8 passing
- Integration tests: 8/8 passing
- Config parsing coverage improved for lines 149-167
- All package tests: passing

* Apply linter formatting fixes

* move redis cmab config into existing config

* expose cmab prediction endpoint in config

145 of 164 new or added lines in 6 files covered. (88.41%)

1 existing line in 1 file now uncovered.

2947 of 3414 relevant lines covered (86.32%)

3135.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.86
/plugins/cmabcache/services/in_memory_cache.go
1
/****************************************************************************
2
 * Copyright 2025, Optimizely, Inc. and contributors                        *
3
 *                                                                          *
4
 * Licensed under the Apache License, Version 2.0 (the "License");          *
5
 * you may not use this file except in compliance with the License.         *
6
 * You may obtain a copy of the License at                                  *
7
 *                                                                          *
8
 *    http://www.apache.org/licenses/LICENSE-2.0                            *
9
 *                                                                          *
10
 * Unless required by applicable law or agreed to in writing, software      *
11
 * distributed under the License is distributed on an "AS IS" BASIS,        *
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13
 * See the License for the specific language governing permissions and      *
14
 * limitations under the License.                                           *
15
 ***************************************************************************/
16

17
// Package services //
18
package services
19

20
import (
21
        "github.com/optimizely/agent/plugins/cmabcache"
22
        "github.com/optimizely/agent/plugins/utils"
23
        "github.com/optimizely/go-sdk/v2/pkg/cache"
24
)
25

26
// InMemoryCache represents the in-memory implementation of Cache interface
27
type InMemoryCache struct {
28
        Size    int            `json:"size"`
29
        Timeout utils.Duration `json:"timeout"`
30
        *cache.LRUCache
31
}
32

33
// Lookup is used to retrieve cached CMAB decisions
34
func (i *InMemoryCache) Lookup(key string) interface{} {
11✔
35
        if i.LRUCache == nil {
12✔
36
                i.initClient()
1✔
37
                return nil
1✔
38
        }
1✔
39
        return i.LRUCache.Lookup(key)
10✔
40
}
41

42
// Save is used to save CMAB decisions
43
func (i *InMemoryCache) Save(key string, value interface{}) {
7✔
44
        if i.LRUCache == nil {
12✔
45
                i.initClient()
5✔
46
        }
5✔
47
        i.LRUCache.Save(key, value)
7✔
48
}
49

50
// Remove is used to remove a specific CMAB decision from cache
51
func (i *InMemoryCache) Remove(key string) {
2✔
52
        if i.LRUCache == nil {
3✔
53
                return
1✔
54
        }
1✔
55
        i.LRUCache.Remove(key)
1✔
56
}
57

58
// Reset is used to reset all CMAB decisions
59
func (i *InMemoryCache) Reset() {
2✔
60
        if i.LRUCache != nil {
3✔
61
                i.LRUCache.Reset()
1✔
62
        }
1✔
63
}
64

65
func (i *InMemoryCache) initClient() {
6✔
66
        i.LRUCache = cache.NewLRUCache(i.Size, i.Timeout.Duration)
6✔
67
}
6✔
68

69
func init() {
1✔
70
        inMemoryCacheCreator := func() cache.Cache {
1✔
NEW
71
                return &InMemoryCache{}
×
NEW
72
        }
×
73
        cmabcache.Add("in-memory", inMemoryCacheCreator)
1✔
74
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc