1
0
mirror of https://github.com/bingohuang/docker-labs.git synced 2025-07-14 18:27:25 +08:00

Refactor sessions and add locking to avoid concurrent requests to create

more instances
This commit is contained in:
Marcos Lilljedahl 2016-10-14 12:54:25 -03:00
parent d19e8a0cd3
commit a56af3dc22
7 changed files with 21 additions and 26 deletions

4
api.go
View File

@ -18,7 +18,7 @@ func main() {
mux.Get("/", http.HandlerFunc(handlers.NewSession)) mux.Get("/", http.HandlerFunc(handlers.NewSession))
mux.Get("/sessions/:sessionId", http.HandlerFunc(handlers.GetSession)) mux.Get("/sessions/:sessionId", http.HandlerFunc(handlers.GetSession))
mux.Post("/sessions/:sessionId/instances", http.HandlerFunc(handlers.NewInstance)) mux.Post("/sessions/:sessionId/instances", http.HandlerFunc(handlers.NewInstance))
mux.Delete("/sessions/:sessionId/instances/:instanceId", http.HandlerFunc(handlers.DeleteInstance)) mux.Delete("/sessions/:sessionId/instances/:instanceName", http.HandlerFunc(handlers.DeleteInstance))
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./www/index.html") http.ServeFile(w, r, "./www/index.html")
@ -26,7 +26,7 @@ func main() {
mux.Get("/p/:sessionId", h) mux.Get("/p/:sessionId", h)
mux.Get("/assets/*", http.FileServer(http.Dir("./www"))) mux.Get("/assets/*", http.FileServer(http.Dir("./www")))
mux.Get("/sessions/:sessionId/instances/:instanceId/attach", websocket.Handler(handlers.Exec)) mux.Get("/sessions/:sessionId/instances/:instanceName/attach", websocket.Handler(handlers.Exec))
n := negroni.Classic() n := negroni.Classic()
n.UseHandler(mux) n.UseHandler(mux)

View File

@ -9,10 +9,10 @@ import (
func DeleteInstance(rw http.ResponseWriter, req *http.Request) { func DeleteInstance(rw http.ResponseWriter, req *http.Request) {
sessionId := bone.GetValue(req, "sessionId") sessionId := bone.GetValue(req, "sessionId")
instanceId := bone.GetValue(req, "instanceId") instanceName := bone.GetValue(req, "instanceName")
s := services.GetSession(sessionId) s := services.GetSession(sessionId)
i := services.GetInstance(s, instanceId) i := services.GetInstance(s, instanceName)
err := services.DeleteInstance(s, i) err := services.DeleteInstance(s, i)
if err != nil { if err != nil {
rw.WriteHeader(http.StatusInternalServerError) rw.WriteHeader(http.StatusInternalServerError)

View File

@ -15,12 +15,12 @@ import (
// Echo the data received on the WebSocket. // Echo the data received on the WebSocket.
func Exec(ws *websocket.Conn) { func Exec(ws *websocket.Conn) {
sessionId := bone.GetValue(ws.Request(), "sessionId") sessionId := bone.GetValue(ws.Request(), "sessionId")
instanceId := bone.GetValue(ws.Request(), "instanceId") instanceName := bone.GetValue(ws.Request(), "instanceName")
ctx := context.Background() ctx := context.Background()
session := services.GetSession(sessionId) session := services.GetSession(sessionId)
instance := services.GetInstance(session, instanceId) instance := services.GetInstance(session, instanceName)
if instance.Stdout == nil { if instance.Stdout == nil {
id, err := services.CreateExecConnection(instance.Name, ctx) id, err := services.CreateExecConnection(instance.Name, ctx)

View File

@ -14,12 +14,14 @@ func NewInstance(rw http.ResponseWriter, req *http.Request) {
s := services.GetSession(sessionId) s := services.GetSession(sessionId)
s.Lock()
if len(s.Instances) >= 5 { if len(s.Instances) >= 5 {
rw.WriteHeader(http.StatusConflict) rw.WriteHeader(http.StatusConflict)
return return
} }
i, err := services.NewInstance(s) i, err := services.NewInstance(s)
s.Unlock()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
//TODO: Set a status error //TODO: Set a status error

View File

@ -7,13 +7,10 @@ import (
"github.com/franela/play-with-docker/types" "github.com/franela/play-with-docker/types"
) )
var instances map[string]map[string]*types.Instance
var dindImage string var dindImage string
var defaultDindImageName string var defaultDindImageName string
func init() { func init() {
instances = make(map[string]map[string]*types.Instance)
dindImage = getDindImageName() dindImage = getDindImageName()
} }
@ -37,21 +34,20 @@ func NewInstance(session *types.Session) (*types.Instance, error) {
return nil, err return nil, err
} }
if instances[session.Id] == nil { if session.Instances == nil {
instances[session.Id] = make(map[string]*types.Instance) session.Instances = make(map[string]*types.Instance)
} }
instances[session.Id][instance.Name] = instance session.Instances[instance.Name] = instance
return instance, nil return instance, nil
} }
func GetInstance(session *types.Session, instanceId string) *types.Instance { func GetInstance(session *types.Session, name string) *types.Instance {
//TODO: Use redis //TODO: Use redis
i := instances[session.Id][instanceId] return session.Instances[name]
return i
} }
func DeleteInstance(session *types.Session, instance *types.Instance) error { func DeleteInstance(session *types.Session, instance *types.Instance) error {
//TODO: Use redis //TODO: Use redis
delete(instances[session.Id], instance.Name) delete(session.Instances, instance.Name)
return DeleteContainer(instance.Name) return DeleteContainer(instance.Name)
} }

View File

@ -49,11 +49,5 @@ func NewSession() (*types.Session, error) {
func GetSession(sessionId string) *types.Session { func GetSession(sessionId string) *types.Session {
//TODO: Use redis //TODO: Use redis
s, found := sessions[sessionId] return sessions[sessionId]
if found {
s.Instances = instances[sessionId]
return s
} else {
return nil
}
} }

View File

@ -1,11 +1,14 @@
package types package types
import ( import (
"sync"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/franela/play-with-docker/cookoo" "github.com/franela/play-with-docker/cookoo"
) )
type Session struct { type Session struct {
sync.Mutex
Id string `json:"id"` Id string `json:"id"`
Instances map[string]*Instance `json:"instances"` Instances map[string]*Instance `json:"instances"`
} }