@@ -13,21 +13,46 @@ import (
1313
1414// CacheClientS3 is a small cache that is backed by an S3-compatible store
1515type CacheClientS3 struct {
16- MC * minio.Client
17- Bucket string
18- CTX context.Context
16+ mc * minio.Client
17+ bucket string
18+ ctx context.Context
19+ defaultExpiration time.Duration
1920}
2021
21- func (c * CacheClientS3 ) Set (key string , value interface {}, exp time.Duration ) error {
22- data , err := json .Marshal (value )
23- if err != nil {
22+ // NewCacheClientS3 creates a new S3 cache client with default settings
23+ func NewCacheClientS3 (ctx context.Context , mc * minio.Client , bucket string ) * CacheClientS3 {
24+ return & CacheClientS3 {
25+ mc : mc ,
26+ bucket : bucket ,
27+ ctx : ctx ,
28+ defaultExpiration : 24 * time .Hour ,
29+ }
30+ }
31+
32+ func (c * CacheClientS3 ) Set (key string , value any , exp time.Duration ) error {
33+ var data bytes.Buffer
34+ if err := json .NewEncoder (& data ).Encode (value ); err != nil {
2435 return err
2536 }
2637
27- r := bytes .NewReader (data )
38+ r := bytes .NewReader (data .Bytes ())
39+
40+ // Use the provided expiration time or fall back to default
41+ expiration := exp
42+ if expiration == 0 {
43+ expiration = c .defaultExpiration
44+ }
45+
46+ // Calculate the expiration time
47+ expiresAt := time .Now ().Add (expiration )
2848
29- _ , err = c .MC .PutObject (c .CTX , c .Bucket , key , r , int64 (r .Len ()), minio.PutObjectOptions {
30- Expires : time .Now ().Add (exp ),
49+ // Set metadata to track expiration
50+ metadata := map [string ]string {
51+ "expires-at" : expiresAt .Format (time .RFC3339 ),
52+ }
53+
54+ _ , err := c .mc .PutObject (c .ctx , c .bucket , key , r , int64 (r .Len ()), minio.PutObjectOptions {
55+ UserMetadata : metadata ,
3156 })
3257 return err
3358}
@@ -36,17 +61,27 @@ func (c *CacheClientS3) Set(key string, value interface{}, exp time.Duration) er
3661// does not exist, in other case we can use minio.ToErrorResponse(err) to extract more details about the
3762// potential S3 related error
3863func (c * CacheClientS3 ) Get (key string ) (string , error ) {
39- if _ , err := c .MC .StatObject (c .CTX , c .Bucket , key , minio.StatObjectOptions {}); err != nil {
64+ // First check if object exists and get its metadata
65+ objInfo , err := c .mc .StatObject (c .ctx , c .bucket , key , minio.StatObjectOptions {})
66+ if err != nil {
4067 return "" , redis .Nil
4168 }
4269
43- object , err := c .MC .GetObject (c .CTX , c .Bucket , key , minio.GetObjectOptions {})
70+ if expiresAt , ok := objInfo .UserMetadata ["expires-at" ]; ok {
71+ expTime , err := time .Parse (time .RFC3339 , expiresAt )
72+ if err == nil && time .Now ().After (expTime ) {
73+ // Object has expired, delete it and return not found
74+ _ = c .Del (key ) // Ignore delete error
75+ return "" , redis .Nil
76+ }
77+ }
78+
79+ object , err := c .mc .GetObject (c .ctx , c .bucket , key , minio.GetObjectOptions {})
4480 if err != nil {
4581 return "" , err
4682 }
4783
4884 var val any
49-
5085 if err := json .NewDecoder (object ).Decode (& val ); err != nil {
5186 return "" , err
5287 }
@@ -63,12 +98,11 @@ func (c *CacheClientS3) Get(key string) (string, error) {
6398}
6499
65100func (c * CacheClientS3 ) Del (key string ) error {
66- return c .MC .RemoveObject (c .CTX , c .Bucket , key , minio.RemoveObjectOptions {
101+ return c .mc .RemoveObject (c .ctx , c .bucket , key , minio.RemoveObjectOptions {
67102 ForceDelete : true ,
68103 })
69104}
70105
71106func (c * CacheClientS3 ) Scan (key string , action func (context.Context , string ) error ) error {
72-
73107 return nil
74108}
0 commit comments