Add idle timeout into session manager
This commit is contained in:
parent
0a133dc395
commit
16726e2461
@ -10,9 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type SessionManager struct {
|
type SessionManager struct {
|
||||||
logger *logrus.Logger
|
logger *logrus.Logger
|
||||||
sessions map[string]*client.Client
|
sessions map[string]*client.Client
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
idleTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSessionManager(logger *logrus.Logger) *SessionManager {
|
func NewSessionManager(logger *logrus.Logger) *SessionManager {
|
||||||
@ -23,6 +24,10 @@ func NewSessionManager(logger *logrus.Logger) *SessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *SessionManager) SetIdleTimeout(timeout time.Duration) {
|
||||||
|
m.idleTimeout = timeout
|
||||||
|
}
|
||||||
|
|
||||||
func (m *SessionManager) IDs() []string {
|
func (m *SessionManager) IDs() []string {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
@ -79,6 +84,10 @@ func (m *SessionManager) Len() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *SessionManager) Cleanup() int {
|
func (m *SessionManager) Cleanup() int {
|
||||||
|
if m.idleTimeout == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
removed := 0
|
removed := 0
|
||||||
|
|
||||||
m.logger.Debug("starting idle sessions cleanup")
|
m.logger.Debug("starting idle sessions cleanup")
|
||||||
@ -97,6 +106,8 @@ func (m *SessionManager) Cleanup() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *SessionManager) RunPeriodicCleanup() {
|
func (m *SessionManager) RunPeriodicCleanup() {
|
||||||
|
m.logger.WithField("timeout", m.idleTimeout).Info("session manager cleanup enabled")
|
||||||
|
|
||||||
for range time.Tick(time.Minute) {
|
for range time.Tick(time.Minute) {
|
||||||
m.Cleanup()
|
m.Cleanup()
|
||||||
}
|
}
|
||||||
@ -106,9 +117,11 @@ func (m *SessionManager) staleSessions() []string {
|
|||||||
m.mu.TryLock()
|
m.mu.TryLock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
ids := []string{}
|
ids := []string{}
|
||||||
|
|
||||||
for id, conn := range m.sessions {
|
for id, conn := range m.sessions {
|
||||||
if conn.IsIdle() {
|
if now.Sub(conn.LastQueryTime()) > m.idleTimeout {
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ package api
|
|||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/sosedoff/pgweb/pkg/client"
|
"github.com/sosedoff/pgweb/pkg/client"
|
||||||
"github.com/sosedoff/pgweb/pkg/command"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSessionManager(t *testing.T) {
|
func TestSessionManager(t *testing.T) {
|
||||||
@ -60,20 +60,16 @@ func TestSessionManager(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("clean up stale sessions", func(t *testing.T) {
|
t.Run("clean up stale sessions", func(t *testing.T) {
|
||||||
defer func() {
|
|
||||||
command.Opts.ConnectionIdleTimeout = 0
|
|
||||||
}()
|
|
||||||
|
|
||||||
manager := NewSessionManager(logrus.New())
|
manager := NewSessionManager(logrus.New())
|
||||||
conn := &client.Client{}
|
conn := &client.Client{}
|
||||||
manager.Add("foo", conn)
|
manager.Add("foo", conn)
|
||||||
|
|
||||||
command.Opts.ConnectionIdleTimeout = 0
|
|
||||||
assert.Equal(t, 1, manager.Len())
|
assert.Equal(t, 1, manager.Len())
|
||||||
assert.Equal(t, 0, manager.Cleanup())
|
assert.Equal(t, 0, manager.Cleanup())
|
||||||
assert.Equal(t, 1, manager.Len())
|
assert.Equal(t, 1, manager.Len())
|
||||||
|
|
||||||
command.Opts.ConnectionIdleTimeout = 1
|
conn.Query("select 1")
|
||||||
|
manager.SetIdleTimeout(time.Minute)
|
||||||
assert.Equal(t, 1, manager.Cleanup())
|
assert.Equal(t, 1, manager.Cleanup())
|
||||||
assert.Equal(t, 0, manager.Len())
|
assert.Equal(t, 0, manager.Len())
|
||||||
assert.True(t, conn.IsClosed())
|
assert.True(t, conn.IsClosed())
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jessevdk/go-flags"
|
"github.com/jessevdk/go-flags"
|
||||||
@ -266,6 +267,7 @@ func Run() {
|
|||||||
api.DbSessions = api.NewSessionManager(logger)
|
api.DbSessions = api.NewSessionManager(logger)
|
||||||
|
|
||||||
if !command.Opts.DisableConnectionIdleTimeout {
|
if !command.Opts.DisableConnectionIdleTimeout {
|
||||||
|
api.DbSessions.SetIdleTimeout(time.Minute * time.Duration(command.Opts.ConnectionIdleTimeout))
|
||||||
go api.DbSessions.RunPeriodicCleanup()
|
go api.DbSessions.RunPeriodicCleanup()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,6 +335,10 @@ func (client *Client) ServerVersion() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) query(query string, args ...interface{}) (*Result, error) {
|
func (client *Client) query(query string, args ...interface{}) (*Result, error) {
|
||||||
|
if client.db == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Update the last usage time
|
// Update the last usage time
|
||||||
defer func() {
|
defer func() {
|
||||||
client.lastQueryTime = time.Now().UTC()
|
client.lastQueryTime = time.Now().UTC()
|
||||||
@ -366,7 +370,7 @@ func (client *Client) query(query string, args ...interface{}) (*Result, error)
|
|||||||
result := Result{
|
result := Result{
|
||||||
Columns: []string{"Rows Affected"},
|
Columns: []string{"Rows Affected"},
|
||||||
Rows: []Row{
|
Rows: []Row{
|
||||||
Row{affected},
|
{affected},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +450,10 @@ func (c *Client) IsClosed() bool {
|
|||||||
return c.closed
|
return c.closed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) LastQueryTime() time.Time {
|
||||||
|
return c.lastQueryTime
|
||||||
|
}
|
||||||
|
|
||||||
func (client *Client) IsIdle() bool {
|
func (client *Client) IsIdle() bool {
|
||||||
mins := int(time.Since(client.lastQueryTime).Minutes())
|
mins := int(time.Since(client.lastQueryTime).Minutes())
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user