Skip to content

Commit

Permalink
Add session keep alive. If client doesn't send a keep alive, after a
Browse files Browse the repository at this point in the history
specified amount of time the scheduler closes the session
  • Loading branch information
xetorthio committed Oct 16, 2017
1 parent 8769aa3 commit 1b0d363
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 3 deletions.
10 changes: 10 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"flag"
"fmt"
"log"
"os"
"regexp"
"time"
Expand Down Expand Up @@ -39,6 +40,8 @@ var SecureCookie *securecookie.SecureCookie
var GithubClientID, GithubClientSecret string
var FacebookClientID, FacebookClientSecret string
var DockerClientID, DockerClientSecret string
var SessionKeepAlive time.Duration
var sessionKeepAlive string

type stringslice []string

Expand Down Expand Up @@ -72,6 +75,7 @@ func ParseFlags() {
flag.StringVar(&SSHKeyPath, "ssh_key_path", "", "SSH Private Key to use")
flag.StringVar(&CookieHashKey, "cookie-hash-key", "", "Hash key to use to validate cookies")
flag.StringVar(&CookieBlockKey, "cookie-block-key", "", "Block key to use to encrypt cookies")
flag.StringVar(&sessionKeepAlive, "session-keep-alive", "5m", "Duration for which a session will be kept alive when no more heartbeats arrive")

flag.StringVar(&GithubClientID, "oauth-github-client-id", "", "Github OAuth Client ID")
flag.StringVar(&GithubClientSecret, "oauth-github-client-secret", "", "Github OAuth Client Secret")
Expand All @@ -86,6 +90,12 @@ func ParseFlags() {

SecureCookie = securecookie.New([]byte(CookieHashKey), []byte(CookieBlockKey))

dur, err := time.ParseDuration(sessionKeepAlive)
if err != nil {
log.Fatalf("Cannot parse duration of flag [-session-keep-alive]. Got: %v\n", err)
}
SessionKeepAlive = dur

registerOAuthProviders()
}

Expand Down
1 change: 1 addition & 0 deletions event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var (
SESSION_END = EventType("session end")
SESSION_READY = EventType("session ready")
SESSION_BUILDER_OUT = EventType("session builder out")
SESSION_KEEP_ALIVE = EventType("session keep alive")
)

type Handler func(sessionId string, args ...interface{})
Expand Down
5 changes: 5 additions & 0 deletions handlers/ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/googollee/go-socket.io"
"github.com/gorilla/mux"
"github.com/play-with-docker/play-with-docker/event"
)

func WS(so socketio.Socket) {
Expand Down Expand Up @@ -65,6 +66,10 @@ func WS(so socketio.Socket) {
m.Close()
core.ClientClose(client)
})

so.On("session keep alive", func() {
e.Emit(event.SESSION_KEEP_ALIVE, sessionId)
})
}

func WSError(so socketio.Socket) {
Expand Down
23 changes: 21 additions & 2 deletions scheduler/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"time"

"github.com/play-with-docker/play-with-docker/config"
"github.com/play-with-docker/play-with-docker/event"
"github.com/play-with-docker/play-with-docker/pwd"
"github.com/play-with-docker/play-with-docker/pwd/types"
Expand All @@ -23,8 +24,9 @@ type SchedulerApi interface {
}

type scheduledSession struct {
session *types.Session
cancel context.CancelFunc
session *types.Session
keepAlive *time.Timer
cancel context.CancelFunc
}

type scheduledInstance struct {
Expand Down Expand Up @@ -68,6 +70,10 @@ func (s *scheduler) processSession(ctx context.Context, ss *scheduledSession) {
// Session has expired. Need to close the session.
s.pwd.SessionClose(ss.session)
return
case <-ss.keepAlive.C:
// No keep alive has been received after the defined interval
log.Printf("No keep alive has been received for session %s after %s. Closing.\n", ss.session.Id, config.SessionKeepAlive)
s.pwd.SessionClose(ss.session)
case <-ctx.Done():
return
}
Expand Down Expand Up @@ -141,6 +147,7 @@ func (s *scheduler) scheduleSession(session *types.Session) {
s.scheduledSessions[session.Id] = ss
ctx, cancel := context.WithCancel(context.Background())
ss.cancel = cancel
ss.keepAlive = time.NewTimer(config.SessionKeepAlive)
go s.processSession(ctx, ss)
log.Printf("Scheduled session %s\n", session.Id)
}
Expand Down Expand Up @@ -225,6 +232,18 @@ func (s *scheduler) Start() error {
instance := &types.Instance{Name: instanceName}
s.unscheduleInstance(instance)
})
s.event.On(event.SESSION_KEEP_ALIVE, func(sessionId string, args ...interface{}) {
log.Printf("Keep alive recevied for session %s\n", sessionId)
if _, found := s.scheduledSessions[sessionId]; !found {
log.Printf("Session %s was not found. Ignoring.\n", sessionId)
return
}
ss := s.scheduledSessions[sessionId]
if ss.keepAlive.Stop() {
log.Printf("Keep alive reset for session %s\n", sessionId)
ss.keepAlive.Reset(config.SessionKeepAlive)
}
})
s.started = true

return nil
Expand Down
7 changes: 6 additions & 1 deletion www/assets/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@

var socket = io({ path: '/sessions/' + sessionId + '/ws' });



socket.on('instance terminal status', function(name, status) {
var instance = $scope.idx[name];
instance.status = status;
Expand Down Expand Up @@ -247,8 +249,11 @@
socket.on('connect_error', function() {
$scope.connected = false;
});
socket.on('connect', function() {
socket.on('connect', function(s) {
$scope.connected = true;
setInterval(function() {
socket.emit('session keep alive', 'keep me alive please! ' + new Date());
}, 30*1000);
});

socket.on('instance stats', function(stats) {
Expand Down

0 comments on commit 1b0d363

Please sign in to comment.