@@ -104,102 +104,181 @@ func NewInMemoryWithDefaults(capacity int) (*HyperCache[backend.InMemory], error
104104// - The eviction algorithm is set to LRU.
105105// - The expiration interval is set to 30 minutes.
106106// - The stats collector is set to the HistogramStatsCollector stats collector.
107- //
108- //nolint:cyclop
109107func New [T backend.IBackendConstrain ](bm * BackendManager , config * Config [T ]) (* HyperCache [T ], error ) {
110- // Get the backend constructor from the registry
111- constructor , exists := bm .backendRegistry [config .BackendType ]
112- if ! exists {
113- return nil , ewrap .Newf ("unknown backend type: %s" , config .BackendType )
108+ // Resolve typed backend from registry
109+ backendTyped , err := resolveBackend [T ](bm , config )
110+ if err != nil {
111+ return nil , err
112+ }
113+
114+ // Initialize base cache struct
115+ hyperCache := newHyperCacheBase [T ](backendTyped )
116+
117+ // Initialize the cache backend type checker
118+ hyperCache .cacheBackendChecker = introspect.CacheBackendChecker [T ]{
119+ Backend : hyperCache .backend ,
120+ BackendType : config .BackendType ,
121+ }
122+
123+ // Apply options and configure eviction-related settings
124+ ApplyHyperCacheOptions (hyperCache , config .HyperCacheOptions ... )
125+ configureEvictionSettings (hyperCache )
126+
127+ // Initialize eviction algorithm
128+ err = initEvictionAlgorithm (hyperCache )
129+ if err != nil {
130+ return hyperCache , err
131+ }
132+
133+ // Stats collector
134+ err = configureStats (hyperCache )
135+ if err != nil {
136+ return hyperCache , err
114137 }
115138
116- // Create the backend
117- backendInstance , err := constructor . Create ( config )
139+ // Capacity check (fatal)
140+ err = checkCapacity ( hyperCache )
118141 if err != nil {
119142 return nil , err
120143 }
121144
122- // Check if the backend implements the IBackend interface
123- backend , ok := backendInstance .(backend.IBackend [T ])
124- if ! ok {
145+ // Initialize expiration trigger channel and start background jobs
146+ initExpirationTrigger (hyperCache )
147+ hyperCache .startBackgroundJobs ()
148+
149+ return hyperCache , nil
150+ }
151+
152+ // resolveBackend constructs a typed backend instance based on the config.BackendType.
153+ func resolveBackend [T backend.IBackendConstrain ](bm * BackendManager , config * Config [T ]) (backend.IBackend [T ], error ) {
154+ constructor , exists := bm .backendRegistry [config .BackendType ]
155+ if ! exists {
156+ return nil , ewrap .Newf ("unknown backend type: %s" , config .BackendType )
157+ }
158+
159+ switch config .BackendType {
160+ case constants .InMemoryBackend :
161+ inMemoryConstructor , ok := constructor .(InMemoryBackendConstructor )
162+ if ! ok {
163+ return nil , sentinel .ErrInvalidBackendType
164+ }
165+
166+ cfg , ok := any (config ).(* Config [backend.InMemory ])
167+ if ! ok {
168+ return nil , sentinel .ErrInvalidBackendType
169+ }
170+
171+ bi , err := inMemoryConstructor .Create (cfg )
172+ if err != nil {
173+ return nil , err
174+ }
175+
176+ if b , ok := any (bi ).(backend.IBackend [T ]); ok {
177+ return b , nil
178+ }
179+
180+ return nil , sentinel .ErrInvalidBackendType
181+
182+ case constants .RedisBackend :
183+ redisConstructor , ok := constructor .(RedisBackendConstructor )
184+ if ! ok {
185+ return nil , sentinel .ErrInvalidBackendType
186+ }
187+
188+ cfg , ok := any (config ).(* Config [backend.Redis ])
189+ if ! ok {
190+ return nil , sentinel .ErrInvalidBackendType
191+ }
192+
193+ bi , err := redisConstructor .Create (cfg )
194+ if err != nil {
195+ return nil , err
196+ }
197+
198+ if b , ok := any (bi ).(backend.IBackend [T ]); ok {
199+ return b , nil
200+ }
201+
125202 return nil , sentinel .ErrInvalidBackendType
126203 }
127204
128- // Initialize the cache
129- hyperCache := & HyperCache [T ]{
130- backend : backend ,
205+ return nil , ewrap .Newf ("unknown backend type: %s" , config .BackendType )
206+ }
207+
208+ // newHyperCacheBase builds the base HyperCache instance with default timings and internals.
209+ func newHyperCacheBase [T backend.IBackendConstrain ](b backend.IBackend [T ]) * HyperCache [T ] {
210+ return & HyperCache [T ]{
211+ backend : b ,
131212 itemPoolManager : cache .NewItemPoolManager (),
132213 workerPool : NewWorkerPool (runtime .NumCPU ()),
133214 stop : make (chan bool , 2 ),
134215 expirationInterval : constants .DefaultExpirationInterval ,
135216 evictionInterval : constants .DefaultEvictionInterval ,
136217 }
218+ }
137219
138- // Initialize the cache backend type checker
139- hyperCache .cacheBackendChecker = introspect.CacheBackendChecker [T ]{
140- Backend : hyperCache .backend ,
141- BackendType : config .BackendType ,
142- }
143-
144- // Apply options
145- ApplyHyperCacheOptions (hyperCache , config .HyperCacheOptions ... )
146-
147- // evaluate if the cache should evict items proactively
148- hyperCache .shouldEvict .Store (hyperCache .evictionInterval == 0 && hyperCache .backend .Capacity () > 0 )
220+ // configureEvictionSettings computes derived eviction settings like shouldEvict and default maxEvictionCount.
221+ func configureEvictionSettings [T backend.IBackendConstrain ](hc * HyperCache [T ]) {
222+ hc .shouldEvict .Store (hc .evictionInterval == 0 && hc .backend .Capacity () > 0 )
149223
150- // Set the max eviction count to the capacity if it is not set or is zero
151- if hyperCache .maxEvictionCount == 0 {
224+ if hc .maxEvictionCount == 0 {
152225 //nolint:gosec
153- hyperCache .maxEvictionCount = uint (hyperCache .backend .Capacity ())
226+ hc .maxEvictionCount = uint (hc .backend .Capacity ())
154227 }
228+ }
155229
156- // Initialize the eviction algorithm
157- if hyperCache .evictionAlgorithmName == "" {
230+ // initEvictionAlgorithm initializes the eviction algorithm for the cache.
231+ func initEvictionAlgorithm [T backend.IBackendConstrain ](hc * HyperCache [T ]) error {
232+ var err error
233+ if hc .evictionAlgorithmName == "" {
158234 // Use the default eviction algorithm if none is specified
159235 //nolint:gosec
160- hyperCache .evictionAlgorithm , err = eviction .NewLRUAlgorithm (int (hyperCache .maxEvictionCount ))
236+ hc .evictionAlgorithm , err = eviction .NewLRUAlgorithm (int (hc .maxEvictionCount ))
161237 } else {
162238 // Use the specified eviction algorithm
163239 //nolint:gosec
164- hyperCache .evictionAlgorithm , err = eviction .NewEvictionAlgorithm (hyperCache .evictionAlgorithmName , int (hyperCache .maxEvictionCount ))
240+ hc .evictionAlgorithm , err = eviction .NewEvictionAlgorithm (hc .evictionAlgorithmName , int (hc .maxEvictionCount ))
165241 }
166242
167- if err != nil {
168- return hyperCache , err
169- }
243+ return err
244+ }
170245
171- // Initialize the stats collector
172- if hyperCache .statsCollectorName == "" {
173- // Use the default stats collector if none is specified
174- hyperCache .StatsCollector = stats .NewHistogramStatsCollector ()
175- } else {
176- // Use the specified stats collector
177- hyperCache .StatsCollector , err = stats .NewCollector (hyperCache .statsCollectorName )
178- if err != nil {
179- return hyperCache , err
180- }
246+ // configureStats sets the stats collector, using default if none specified.
247+ func configureStats [T backend.IBackendConstrain ](hc * HyperCache [T ]) error {
248+ if hc .statsCollectorName == "" {
249+ hc .StatsCollector = stats .NewHistogramStatsCollector ()
250+
251+ return nil
181252 }
182253
183- // If the capacity is less than zero, we return
184- if hyperCache .backend .Capacity () < 0 {
185- return nil , sentinel .ErrInvalidCapacity
254+ var err error
255+
256+ hc .StatsCollector , err = stats .NewCollector (hc .statsCollectorName )
257+
258+ return err
259+ }
260+
261+ // checkCapacity validates the backend capacity and returns an error if invalid.
262+ func checkCapacity [T backend.IBackendConstrain ](hc * HyperCache [T ]) error {
263+ if hc .backend .Capacity () < 0 {
264+ return sentinel .ErrInvalidCapacity
186265 }
187266
188- // Initialize the expiration trigger channel with configurable buffer size (default: half capacity)
189- buf := hyperCache .backend .Capacity () / 2
190- if hyperCache .expirationTriggerBufSize > 0 {
191- buf = hyperCache .expirationTriggerBufSize
267+ return nil
268+ }
269+
270+ // initExpirationTrigger initializes the expiration trigger channel with optional buffer override.
271+ func initExpirationTrigger [T backend.IBackendConstrain ](hc * HyperCache [T ]) {
272+ buf := hc .backend .Capacity () / 2
273+ if hc .expirationTriggerBufSize > 0 {
274+ buf = hc .expirationTriggerBufSize
192275 }
193276
194277 if buf < 1 {
195278 buf = 1
196279 }
197280
198- hyperCache .expirationTriggerCh = make (chan bool , buf )
199-
200- hyperCache .startBackgroundJobs ()
201-
202- return hyperCache , err
281+ hc .expirationTriggerCh = make (chan bool , buf )
203282}
204283
205284// startBackgroundJobs starts the background jobs for the hyper cache.
0 commit comments