@@ -2,17 +2,19 @@ package redis
22
33import (
44 "context"
5- "encoding/json"
65 "sync"
76 "time"
87
98 "github.com/go-redis/redis"
9+ "github.com/json-iterator/go"
1010 "gopkg.in/session.v2"
1111)
1212
1313var (
14- _ session.ManagerStore = & managerStore {}
15- _ session.Store = & store {}
14+ _ session.ManagerStore = & managerStore {}
15+ _ session.Store = & store {}
16+ jsonMarshal = jsoniter .Marshal
17+ jsonUnmarshal = jsoniter .Unmarshal
1618)
1719
1820// NewRedisStore Create an instance of a redis store
@@ -23,6 +25,11 @@ func NewRedisStore(opt *Options) session.ManagerStore {
2325 return & managerStore {cli : redis .NewClient (opt .redisOptions ())}
2426}
2527
28+ // NewRedisStoreWithCli Create an instance of a redis store
29+ func NewRedisStoreWithCli (cli * redis.Client ) session.ManagerStore {
30+ return & managerStore {cli : cli }
31+ }
32+
2633type managerStore struct {
2734 cli * redis.Client
2835}
@@ -39,33 +46,43 @@ func (s *managerStore) getValue(sid string) (string, error) {
3946 return cmd .Val (), nil
4047}
4148
42- func (s * managerStore ) parseValue (value string ) (map [string ]string , error ) {
43- var values map [string ]string
44-
49+ func (s * managerStore ) parseValue (value string ) (map [string ]interface {}, error ) {
50+ var values map [string ]interface {}
4551 if len (value ) > 0 {
46- err := json . Unmarshal ([]byte (value ), & values )
52+ err := jsonUnmarshal ([]byte (value ), & values )
4753 if err != nil {
4854 return nil , err
4955 }
5056 }
5157
5258 if values == nil {
53- values = make (map [string ]string )
59+ values = make (map [string ]interface {} )
5460 }
5561 return values , nil
5662}
5763
5864func (s * managerStore ) Create (ctx context.Context , sid string , expired int64 ) (session.Store , error ) {
59- values := make (map [string ]string )
60- return & store {ctx : ctx , sid : sid , cli : s .cli , expired : expired , values : values }, nil
65+ return & store {
66+ ctx : ctx ,
67+ sid : sid ,
68+ cli : s .cli ,
69+ expired : expired ,
70+ values : make (map [string ]interface {}),
71+ }, nil
6172}
6273
6374func (s * managerStore ) Update (ctx context.Context , sid string , expired int64 ) (session.Store , error ) {
6475 value , err := s .getValue (sid )
6576 if err != nil {
6677 return nil , err
6778 } else if value == "" {
68- return s .Create (ctx , sid , expired )
79+ return & store {
80+ ctx : ctx ,
81+ sid : sid ,
82+ cli : s .cli ,
83+ expired : expired ,
84+ values : make (map [string ]interface {}),
85+ }, nil
6986 }
7087
7188 cmd := s .cli .Set (sid , value , time .Duration (expired )* time .Second )
@@ -77,37 +94,80 @@ func (s *managerStore) Update(ctx context.Context, sid string, expired int64) (s
7794 if err != nil {
7895 return nil , err
7996 }
80-
81- return & store {ctx : ctx , sid : sid , cli : s .cli , expired : expired , values : values }, nil
97+ return & store {
98+ ctx : ctx ,
99+ sid : sid ,
100+ cli : s .cli ,
101+ expired : expired ,
102+ values : values ,
103+ }, nil
82104}
83105
84106func (s * managerStore ) Delete (_ context.Context , sid string ) error {
107+ if ok , err := s .Check (nil , sid ); err != nil {
108+ return err
109+ } else if ! ok {
110+ return nil
111+ }
112+
85113 cmd := s .cli .Del (sid )
86114 return cmd .Err ()
87115}
88116
89117func (s * managerStore ) Check (_ context.Context , sid string ) (bool , error ) {
90- cmd := s .cli .Get (sid )
118+ cmd := s .cli .Exists (sid )
91119 if err := cmd .Err (); err != nil {
92- if err == redis .Nil {
93- return false , nil
94- }
95120 return false , err
96121 }
97- return true , nil
122+ return cmd .Val () > 0 , nil
123+ }
124+
125+ func (s * managerStore ) Refresh (ctx context.Context , oldsid , sid string , expired int64 ) (session.Store , error ) {
126+ value , err := s .getValue (oldsid )
127+ if err != nil {
128+ return nil , err
129+ } else if value == "" {
130+ return & store {
131+ ctx : ctx ,
132+ sid : sid ,
133+ cli : s .cli ,
134+ expired : expired ,
135+ values : make (map [string ]interface {}),
136+ }, nil
137+ }
138+
139+ pipe := s .cli .TxPipeline ()
140+ pipe .Set (sid , value , time .Duration (expired )* time .Second )
141+ pipe .Del (oldsid )
142+ _ , err = pipe .Exec ()
143+ if err != nil {
144+ return nil , err
145+ }
146+
147+ values , err := s .parseValue (value )
148+ if err != nil {
149+ return nil , err
150+ }
151+ return & store {
152+ ctx : ctx ,
153+ sid : sid ,
154+ cli : s .cli ,
155+ expired : expired ,
156+ values : values ,
157+ }, nil
98158}
99159
100160func (s * managerStore ) Close () error {
101161 return s .cli .Close ()
102162}
103163
104164type store struct {
165+ sync.RWMutex
166+ ctx context.Context
105167 sid string
106- cli * redis.Client
107168 expired int64
108- values map [string ]string
109- sync.RWMutex
110- ctx context.Context
169+ values map [string ]interface {}
170+ cli * redis.Client
111171}
112172
113173func (s * store ) Context () context.Context {
@@ -118,20 +178,20 @@ func (s *store) SessionID() string {
118178 return s .sid
119179}
120180
121- func (s * store ) Set (key , value string ) {
181+ func (s * store ) Set (key string , value interface {} ) {
122182 s .Lock ()
123183 s .values [key ] = value
124184 s .Unlock ()
125185}
126186
127- func (s * store ) Get (key string ) (string , bool ) {
187+ func (s * store ) Get (key string ) (interface {} , bool ) {
128188 s .RLock ()
129189 defer s .RUnlock ()
130190 val , ok := s .values [key ]
131191 return val , ok
132192}
133193
134- func (s * store ) Delete (key string ) string {
194+ func (s * store ) Delete (key string ) interface {} {
135195 s .RLock ()
136196 v , ok := s .values [key ]
137197 s .RUnlock ()
@@ -145,7 +205,7 @@ func (s *store) Delete(key string) string {
145205
146206func (s * store ) Flush () error {
147207 s .Lock ()
148- s .values = make (map [string ]string )
208+ s .values = make (map [string ]interface {} )
149209 s .Unlock ()
150210 return s .Save ()
151211}
@@ -155,7 +215,11 @@ func (s *store) Save() error {
155215
156216 s .RLock ()
157217 if len (s .values ) > 0 {
158- buf , _ := json .Marshal (s .values )
218+ buf , err := jsonMarshal (s .values )
219+ if err != nil {
220+ s .RUnlock ()
221+ return err
222+ }
159223 value = string (buf )
160224 }
161225 s .RUnlock ()
0 commit comments