11package xcache
22
33import (
4+ "context"
45 "github.com/pkg/errors"
56 "golang.org/x/sync/singleflight"
67 "time"
@@ -10,39 +11,78 @@ type (
1011 basis struct {
1112 data map [string ]node
1213 loadGroup * singleflight.Group
14+ ctx context.Context
1315 }
1416
1517 node struct {
1618 data []byte
1719 expire time.Duration
1820 creatTime time.Time
1921 }
22+
23+ do func () (interface {}, error )
2024)
2125
26+ func (b * basis ) GetContext () context.Context {
27+ if b .ctx == nil {
28+ b .ctx = context .Background ()
29+ }
30+ return b .ctx
31+ }
32+
33+ func (b * basis ) WithContext (ctx context.Context ) Cache {
34+ b .ctx = ctx
35+ return b
36+ }
37+
2238func NewBasis () * basis {
2339 return & basis {
2440 data : make (map [string ]node ),
2541 loadGroup : & singleflight.Group {},
2642 }
2743}
2844
29- func (b basis ) Del (keys ... string ) error {
30- for _ , key := range keys {
31- b .doDel (key )
45+ func (b * basis ) Del (keys ... string ) error {
46+ _ , err := done (b .GetContext (), func () (interface {}, error ) {
47+ for _ , key := range keys {
48+ b .doDel (key )
49+ }
50+ return nil , nil
51+ })
52+ return err
53+ }
54+
55+ func done (ctx context.Context , df do ) (interface {}, error ) {
56+ var (
57+ c = make (chan struct {})
58+ ret interface {}
59+ err error
60+ )
61+ go func () {
62+ ret , err = df ()
63+ close (c )
64+ }()
65+ select {
66+ case <- ctx .Done ():
67+ return nil , ctx .Err ()
68+ case <- c :
3269 }
33- return nil
70+ return ret , err
3471}
3572
3673func (b basis ) GetE (key string ) ([]byte , error ) {
37- node , ok := b .data [key ]
38- if ! ok {
39- return nil , nilError
40- }
41- if b .checkExpire (node ) {
42- b .doDel (key )
43- return nil , nilError
44- }
45- return node .data , nil
74+ ret , err := done (b .GetContext (), func () (interface {}, error ) {
75+ node , ok := b .data [key ]
76+ if ! ok {
77+ return nil , nilError
78+ }
79+ if b .checkExpire (node ) {
80+ b .doDel (key )
81+ return nil , nilError
82+ }
83+ return node .data , nil
84+ })
85+ return toByte (ret , err )
4686}
4787
4888func (b basis ) Get (key string ) []byte {
@@ -51,22 +91,27 @@ func (b basis) Get(key string) []byte {
5191}
5292
5393func (b basis ) GetWithCreateE (key string , h Handle ) ([]byte , error ) {
54- data , err := b .GetE (key )
55- if err == nil {
56- return data , err
57- }
58- if ! b .IsNilError (err ) {
59- return nil , err
60- }
61- do , err , _ := b .loadGroup .Do (key , func () (interface {}, error ) {
62- return h .Create ()
94+ ret , err := done (b .GetContext (), func () (interface {}, error ) {
95+ data , err := b .GetE (key )
96+ if err == nil {
97+ return data , err
98+ }
99+ if ! b .IsNilError (err ) {
100+ return nil , err
101+ }
102+ doData , err , _ := b .loadGroup .Do (key , func () (interface {}, error ) {
103+ data , err := h .Create (b .GetContext ())
104+ if err == nil {
105+ b .doSetWithData (key , data , h .Expire ())
106+ }
107+ return data , err
108+ })
109+ if err != nil {
110+ return nil , errors .Wrap (err , "x cache create data error" )
111+ }
112+ return doData , err
63113 })
64- if err != nil {
65- return nil , errors .Wrap (err , "x cache create data error" )
66- }
67- data , _ = do .([]byte )
68- b .doSetWithData (key , data , h .Expire ())
69- return data , nil
114+ return toByte (ret , err )
70115}
71116
72117func (b basis ) GetWithCreate (key string , h Handle ) []byte {
@@ -83,23 +128,31 @@ func (b basis) doSetWithData(key string, data []byte, expire time.Duration) {
83128}
84129
85130func (b basis ) Set (key string , h Handle ) error {
86- do , err , _ := b .loadGroup .Do (key , func () (interface {}, error ) {
87- return h .Create ()
131+ _ , err := done (b .GetContext (), func () (interface {}, error ) {
132+ _ , err , _ := b .loadGroup .Do (key , func () (interface {}, error ) {
133+ data , err := h .Create (b .GetContext ())
134+ if err == nil {
135+ b .doSetWithData (key , data , h .Expire ())
136+ }
137+ return data , err
138+ })
139+ if err != nil {
140+ return nil , errors .Wrap (err , "x cache create data error" )
141+ }
142+ return nil , nil
88143 })
89- if err != nil {
90- return errors .Wrap (err , "x cache create data error" )
91- }
92- data , _ := do .([]byte )
93- b .doSetWithData (key , data , h .Expire ())
94- return nil
144+ return err
95145}
96146
97147func (b basis ) IsNilError (err error ) bool {
98148 return err == nilError
99149}
100150
101151func (b basis ) IsExist (key string ) bool {
102- return b .doIsExist (key ) == nilError
152+ _ , err := done (b .GetContext (), func () (interface {}, error ) {
153+ return nil , b .doIsExist (key )
154+ })
155+ return err == nilError
103156}
104157
105158func (b basis ) checkExpire (n node ) bool {
@@ -119,3 +172,10 @@ func (b basis) doIsExist(key string) error {
119172func (b basis ) doDel (key string ) {
120173 delete (b .data , key )
121174}
175+
176+ func toByte (ret interface {}, err error ) ([]byte , error ) {
177+ if data , ok := ret .([]byte ); ok {
178+ return data , err
179+ }
180+ return nil , err
181+ }
0 commit comments