| 
									
										
										
										
											2025-04-21 11:07:53 -05:00
										 |  |  | package ezcache | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2025-04-21 12:01:32 -05:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2025-04-21 11:07:53 -05:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type ezc[K comparable, V any] struct { | 
					
						
							| 
									
										
										
										
											2025-04-21 12:01:32 -05:00
										 |  |  | 	fetch    Fetcher[K, V] | 
					
						
							|  |  |  | 	exp      time.Duration | 
					
						
							|  |  |  | 	cache    map[K]V | 
					
						
							|  |  |  | 	setTime  map[K]time.Time | 
					
						
							|  |  |  | 	lock     sync.RWMutex | 
					
						
							|  |  |  | 	timeLock sync.RWMutex | 
					
						
							| 
									
										
										
										
											2025-04-21 11:07:53 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func New[K comparable, V any](fetcher Fetcher[K, V], exp time.Duration) (Cache[K, V], error) { | 
					
						
							|  |  |  | 	c := &ezc[K, V]{} | 
					
						
							|  |  |  | 	err := c.SetFetcher(fetcher) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	err = c.SetExpiry(exp) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.cache = make(map[K]V) | 
					
						
							|  |  |  | 	c.setTime = make(map[K]time.Time) | 
					
						
							|  |  |  | 	return c, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ezc[K, V]) Get(key K) (V, error) { | 
					
						
							| 
									
										
										
										
											2025-04-21 12:01:32 -05:00
										 |  |  | 	c.timeLock.RLock() | 
					
						
							|  |  |  | 	setTime, ok := c.setTime[key] | 
					
						
							|  |  |  | 	c.timeLock.RUnlock() | 
					
						
							|  |  |  | 	if ok && time.Since(setTime) <= c.exp { | 
					
						
							|  |  |  | 		c.lock.RLock() | 
					
						
							|  |  |  | 		val, ok := c.cache[key] | 
					
						
							|  |  |  | 		c.lock.RUnlock() | 
					
						
							|  |  |  | 		if ok { | 
					
						
							|  |  |  | 			return val, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	val, err := c.fetch(key) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return val, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.lock.Lock() | 
					
						
							|  |  |  | 	defer c.lock.Unlock() | 
					
						
							|  |  |  | 	c.cache[key] = val | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.timeLock.Lock() | 
					
						
							|  |  |  | 	defer c.timeLock.Unlock() | 
					
						
							|  |  |  | 	c.setTime[key] = time.Now() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return val, nil | 
					
						
							| 
									
										
										
										
											2025-04-21 11:07:53 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ezc[K, V]) SetFetcher(f Fetcher[K, V]) error { | 
					
						
							|  |  |  | 	if f == nil { | 
					
						
							|  |  |  | 		return ErrInvalidFetcher | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.fetch = f | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *ezc[K, V]) SetExpiry(exp time.Duration) error { | 
					
						
							|  |  |  | 	if exp <= 0 { | 
					
						
							| 
									
										
										
										
											2025-04-21 11:24:51 -05:00
										 |  |  | 		return ErrInvalidExpiry | 
					
						
							| 
									
										
										
										
											2025-04-21 11:07:53 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	c.exp = exp | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |