-
Notifications
You must be signed in to change notification settings - Fork 14
/
feature_flag_with_cache.go
107 lines (83 loc) · 3.01 KB
/
feature_flag_with_cache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package featureflag
import (
"sync"
"time"
redisearch "github.com/coretrix/beeorm-redisearch-plugin"
"github.com/coretrix/hitrix/datalayer"
"github.com/coretrix/hitrix/pkg/entity"
"github.com/coretrix/hitrix/service/component/app"
"github.com/coretrix/hitrix/service/component/clock"
errorlogger "github.com/coretrix/hitrix/service/component/error_logger"
)
type cacheEntity struct {
featureFlagEntity *entity.FeatureFlagEntity
time time.Time
}
type serviceFeatureFlagWithCache struct {
sync.Mutex
featureFlagService ServiceFeatureFlagInterface
clockService clock.IClock
cache map[string]*cacheEntity
}
func NewFeatureFlagWithCacheService(errorLoggerService errorlogger.ErrorLogger, clockService clock.IClock) ServiceFeatureFlagInterface {
featureFlagService := NewFeatureFlagService(errorLoggerService)
cachedService := &serviceFeatureFlagWithCache{
featureFlagService: featureFlagService,
clockService: clockService,
cache: make(map[string]*cacheEntity),
}
return cachedService
}
func (s *serviceFeatureFlagWithCache) IsActive(ormService *datalayer.ORM, name string) bool {
if name == "" {
panic("name cannot be empty")
}
s.Lock()
defer s.Unlock()
if cacheEntry, has := s.cache[name]; has {
if s.clockService.Now().Sub(cacheEntry.time) <= 5*time.Second {
return cacheEntry.featureFlagEntity.Enabled && cacheEntry.featureFlagEntity.Registered
}
}
query := redisearch.NewRedisSearchQuery()
query.FilterString("Name", name)
featureFlagEntity := &entity.FeatureFlagEntity{}
found := ormService.RedisSearchOne(featureFlagEntity, query)
if !found {
return false
}
s.cache[name] = &cacheEntity{
featureFlagEntity: featureFlagEntity,
time: s.clockService.Now(),
}
return featureFlagEntity.Enabled && featureFlagEntity.Registered
}
func (s *serviceFeatureFlagWithCache) FailIfIsNotActive(ormService *datalayer.ORM, name string) error {
return s.featureFlagService.FailIfIsNotActive(ormService, name)
}
func (s *serviceFeatureFlagWithCache) Enable(ormService *datalayer.ORM, name string) error {
err := s.featureFlagService.Enable(ormService, name)
s.Lock()
delete(s.cache, name)
s.Unlock()
return err
}
func (s *serviceFeatureFlagWithCache) Disable(ormService *datalayer.ORM, name string) error {
err := s.featureFlagService.Disable(ormService, name)
s.Lock()
delete(s.cache, name)
s.Unlock()
return err
}
func (s *serviceFeatureFlagWithCache) GetScriptsSingleInstance(ormService *datalayer.ORM) []app.IScript {
return s.featureFlagService.GetScriptsSingleInstance(ormService)
}
func (s *serviceFeatureFlagWithCache) GetScriptsMultiInstance(ormService *datalayer.ORM) []app.IScript {
return s.featureFlagService.GetScriptsMultiInstance(ormService)
}
func (s *serviceFeatureFlagWithCache) Register(featureFlags ...IFeatureFlag) {
s.featureFlagService.Register(featureFlags...)
}
func (s *serviceFeatureFlagWithCache) Sync(ormService *datalayer.ORM, clockService clock.IClock) {
s.featureFlagService.Sync(ormService, clockService)
}