Skip to content

Instantly share code, notes, and snippets.

@xlab
Created December 23, 2015 17:40
Show Gist options
  • Save xlab/add5507824e130083745 to your computer and use it in GitHub Desktop.
Save xlab/add5507824e130083745 to your computer and use it in GitHub Desktop.
import "time"
type Session struct {
ID string
CreatedAt time.Time
}
type SessionPool struct {
size int
ttl time.Duration
flow chan Session
producer func() (Session, error)
}
func NewSessionPool(producer func() Session, size int, ttl time.Duration) *SessionPool {
s := &SessionPool{
ttl: ttl,
size: size,
producer: producer,
flow: make(chan Session, size),
}
go s.renew()
}
func (s *SessionPool) Put(sess Session) {
if time.Since(sess.CreatedAt) >= s.ttl {
return
}
s.tryPutSession(sess)
}
func (s *SessionPool) Get(timeout time.Duration) Session {
select {
case session := <-s.flow:
if time.Since(session.CreatedAt) < s.ttl {
return session
}
default:
}
for i := 0; i < 3; i++ {
go s.tryPutSession(s.producer())
}
return <-s.flow
}
func (s *SessionPool) renew() {
t := time.NewTimer(s.ttl)
for range t.C {
for i := 0; i < s.size; i++ {
s.trySkipSession()
}
for i := 0; i < s.size; i++ {
go s.tryPutSession(s.producer())
}
t.Reset(s.ttl)
}
}
func (s *SessionPool) trySkipSession() {
select {
case <-s.flow:
default:
}
}
func (s *SessionPool) tryPutSession(sess Session) {
select {
case s.flow <- sess:
default:
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment