generated from cloudwego/.github
-
Notifications
You must be signed in to change notification settings - Fork 2
/
gls.go
160 lines (144 loc) · 4.26 KB
/
gls.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
158
159
160
// Copyright 2023 CloudWeGo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package localsession
import (
"fmt"
"os"
"strconv"
"strings"
"sync"
"time"
)
// SESSION_CONFIG_KEY is the env key for configuring default session manager.
//
// Value format: [EnableImplicitlyTransmitAsync][,ShardNumber][,GCInterval]
// - EnableImplicitlyTransmitAsync: 'true' means enabled, otherwist means disabled
// - ShardNumber: integer > 0
// - GCInterval: Golang time.Duration format, such as '10m' means ten minutes for each GC
//
// Once the key is set, default option values will be set if the option value doesn't exist.
const SESSION_CONFIG_KEY = "CLOUDWEGO_SESSION_CONFIG_KEY"
var (
defaultManagerObj *SessionManager
defaultManagerOnce sync.Once
)
// DefaultManagerOptions returns default options for the default manager
func DefaultManagerOptions() ManagerOptions {
return ManagerOptions{
ShardNumber: 100,
GCInterval: time.Minute * 10,
EnableImplicitlyTransmitAsync: false,
}
}
// GetDefaultManager returns the default manager
func GetDefaultManager() *SessionManager {
return defaultManagerObj
}
// InitDefaultManager update and restart default manager.
// It accept argument opts and env config both.
//
// NOTICE:
// - It use env SESSION_CONFIG_KEY prior to argument opts;
// - If both env and opts are empty, it won't reset manager;
// - For concurrent safety, you can only successfully reset manager ONCE.
//
//go:nocheckptr
func InitDefaultManager(opts ManagerOptions) {
defaultManagerOnce.Do(func() {
// env config has high priority
checkEnvOptions(&opts)
if defaultManagerObj != nil {
defaultManagerObj.Close()
}
obj := NewSessionManager(opts)
defaultManagerObj = &obj
})
}
func checkEnvOptions(opts *ManagerOptions) {
if env := os.Getenv(SESSION_CONFIG_KEY); env != "" {
envs := strings.Split(env, ",")
// parse first option as EnableTransparentTransmitAsync
if strings.ToLower(envs[0]) == "true" {
opts.EnableImplicitlyTransmitAsync = true
}
// parse first option as ShardNumber
if len(envs) > 1 {
if opt, err := strconv.Atoi(envs[1]); err == nil {
opts.ShardNumber = opt
}
}
// parse third option as EnableTransparentTransmitAsync
if len(envs) > 2 {
if d, err := time.ParseDuration(envs[2]); err == nil && d > time.Second {
opts.GCInterval = d
}
}
}
}
// CurSession gets the session for current goroutine
//
// NOTICE: MUST call `InitDefaultManager()` once before using this API
func CurSession() (Session, bool) {
if defaultManagerObj == nil {
return nil, false
}
s, ok := defaultManagerObj.GetSession(SessionID(goID()))
return s, ok
}
// BindSession binds the session with current goroutine
//
// NOTICE: MUST call `InitDefaultManager()` once before using this API
func BindSession(s Session) {
if defaultManagerObj == nil {
return
}
defaultManagerObj.BindSession(SessionID(goID()), s)
}
// UnbindSession unbind a session (if any) with current goroutine
//
// NOTICE: If you want to end the session,
// please call `Disable()` (or whatever make the session invalid)
// on your session's implementation
//
// NOTICE: MUST call `InitDefaultManager()` once before using this API
func UnbindSession() {
if defaultManagerObj == nil {
return
}
defaultManagerObj.UnbindSession(SessionID(goID()))
}
// Go calls f asynchronously and pass caller's session to the new goroutine
func Go(f func()) {
s, ok := CurSession()
if !ok {
GoSession(nil, f)
} else {
GoSession(s, f)
}
}
// SessionGo calls f asynchronously and pass s session to the new goroutine
func GoSession(s Session, f func()) {
go func() {
defer func() {
if v := recover(); v != nil {
println(fmt.Sprintf("GoSession recover: %v", v))
}
UnbindSession()
}()
if s != nil {
BindSession(s)
}
f()
}()
}