/
provider.go
157 lines (133 loc) · 3.91 KB
/
provider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package memcache
import (
"errors"
"github.com/bradfitz/gomemcache/memcache"
"github.com/phachon/fasthttpsession"
"reflect"
)
// session MemCache provider
const ProviderName = "memcache"
var (
provider = NewProvider()
encrypt = fasthttpsession.NewEncrypt()
)
type Provider struct {
config *Config
values *fasthttpsession.CCMap
memCacheClient *memcache.Client
maxLifeTime int64
}
// new memcache provider
func NewProvider() *Provider {
return &Provider{
config: &Config{},
values: fasthttpsession.NewDefaultCCMap(),
memCacheClient: &memcache.Client{},
}
}
// init provider config
func (mcp *Provider) Init(lifeTime int64, memCacheConfig fasthttpsession.ProviderConfig) error {
if memCacheConfig.Name() != ProviderName {
return errors.New("session memcache provider init error, config must memcache config")
}
vc := reflect.ValueOf(memCacheConfig)
rc := vc.Interface().(*Config)
mcp.config = rc
// config check
if len(mcp.config.ServerList) == 0 {
return errors.New("session memcache provider init error, config ServerList not empty")
}
if mcp.config.MaxIdle <= 0 {
return errors.New("session memcache provider init error, config MaxIdle must be more than 0")
}
// init config serialize func
if mcp.config.SerializeFunc == nil {
mcp.config.SerializeFunc = encrypt.GobEncode
}
if mcp.config.UnSerializeFunc == nil {
mcp.config.UnSerializeFunc = encrypt.GobDecode
}
// create memcache client
mcp.memCacheClient = memcache.New(mcp.config.ServerList...)
mcp.memCacheClient.MaxIdleConns = mcp.config.MaxIdle
mcp.maxLifeTime = lifeTime
return nil
}
// not need gc
func (mcp *Provider) NeedGC() bool {
return false
}
// session memcache provider not need garbage collection
func (mcp *Provider) GC() {}
// read session store by session id
func (mcp *Provider) ReadStore(sessionId string) (fasthttpsession.SessionStore, error) {
memClient := mcp.getMemCacheClient()
item, err := memClient.Get(mcp.getMemCacheSessionKey(sessionId))
if err != nil {
if err == memcache.ErrCacheMiss {
return NewMemCacheStore(sessionId), nil
} else {
return nil, err
}
}
if len(item.Value) == 0 {
return NewMemCacheStore(sessionId), nil
}
data, err := mcp.config.UnSerializeFunc(item.Value)
if err != nil {
return nil, err
}
return NewMemCacheStoreData(sessionId, data), nil
}
// regenerate session
func (mcp *Provider) Regenerate(oldSessionId string, sessionId string) (fasthttpsession.SessionStore, error) {
memClient := mcp.getMemCacheClient()
item, err := memClient.Get(mcp.getMemCacheSessionKey(oldSessionId))
if err != nil || len(item.Value) == 0 {
// false, old sessionId not exists
err := memClient.Set(&memcache.Item{
Key: mcp.getMemCacheSessionKey(sessionId),
Value: []byte(""),
Expiration: int32(mcp.maxLifeTime),
})
if err != nil {
return nil, err
}
return NewMemCacheStore(sessionId), nil
}
// true, old sessionId exists, delete old sessionId
err = memClient.Delete(mcp.getMemCacheSessionKey(oldSessionId))
if err != nil {
return nil, err
}
item.Key = mcp.getMemCacheSessionKey(sessionId)
item.Expiration = int32(mcp.maxLifeTime)
err = memClient.Set(item)
if err != nil {
return nil, err
}
return mcp.ReadStore(sessionId)
}
// destroy session by sessionId
func (mcp *Provider) Destroy(sessionId string) error {
memClient := mcp.getMemCacheClient()
return memClient.Delete(mcp.getMemCacheSessionKey(sessionId))
}
// session values count
func (mcp *Provider) Count() int {
return 0
}
// get memcache session key, prefix:sessionId
func (mcp *Provider) getMemCacheSessionKey(sessionId string) string {
return mcp.config.KeyPrefix + ":" + sessionId
}
func (mcp *Provider) getMemCacheClient() *memcache.Client {
if mcp.memCacheClient == nil {
mcp.memCacheClient = memcache.New(mcp.config.ServerList...)
}
return mcp.memCacheClient
}
// register session provider
func init() {
fasthttpsession.Register(ProviderName, provider)
}