From 24c75e8125161b7a98f737e3eda7a132b76636c1 Mon Sep 17 00:00:00 2001 From: Liang Ding Date: Mon, 15 Sep 2014 18:03:52 +0800 Subject: [PATCH] #49 --- conf/wide.go | 59 +++++++++++++++++++---------------- event/events.go | 37 ++++++++++++++++------ main.go | 7 +++++ notification/notifications.go | 57 +++++++++++++++++---------------- static/js/notification.js | 28 +++++++++++++++++ view/index.html | 5 +++ 6 files changed, 127 insertions(+), 66 deletions(-) create mode 100644 static/js/notification.js diff --git a/conf/wide.go b/conf/wide.go index cc09812..91b4f18 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -9,6 +9,7 @@ import ( "path/filepath" "runtime" "strings" + "time" "github.com/b3log/wide/event" _ "github.com/b3log/wide/i18n" @@ -38,35 +39,42 @@ type conf struct { var Wide conf var rawWide conf -// 检查 Wide 运行环境. +// 定时检查 Wide 运行环境. // 如果是特别严重的问题(比如 $GOPATH 不存在)则退出进程。另一些不太严重的问题(比如 gocode 不存在)则放入全局通知队列。 -func (*conf) CheckEnv() { - if "" == os.Getenv("GOPATH") { - glog.Fatal("Not found $GOPATH") - os.Exit(-1) - } +func CheckEnv() { + go func() { + for { - if "" == os.Getenv("GOROOT") { - glog.Fatal("Not found $GOROOT") + if "" == os.Getenv("GOPATH") { + glog.Fatal("Not found $GOPATH") + os.Exit(-1) + } - os.Exit(-1) - } + if "" == os.Getenv("GOROOT") { + glog.Fatal("Not found $GOROOT") - gocode := Wide.GetGocode() - cmd := exec.Command(gocode, "close") - _, err := cmd.Output() - if nil != err { - event.EventQueue <- event.EvtGocodeNotFount - glog.Warningf("Not found gocode [%s]", gocode) - } + os.Exit(-1) + } - ide_stub := Wide.GetIDEStub() - cmd = exec.Command(ide_stub, "version") - _, err = cmd.Output() - if nil != err { - event.EventQueue <- event.EvtIDEStubNotFound - glog.Warningf("Not found ide_stub [%s]", ide_stub) - } + gocode := Wide.GetGocode() + cmd := exec.Command(gocode, "close") + _, err := cmd.Output() + if nil != err { + event.EventQueue <- event.EvtGocodeNotFount + glog.Warningf("Not found gocode [%s]", gocode) + } + + ide_stub := Wide.GetIDEStub() + cmd = exec.Command(ide_stub, "version") + _, err = cmd.Output() + if nil != err { + event.EventQueue <- event.EvtIDEStubNotFound + glog.Warningf("Not found ide_stub [%s]", ide_stub) + } + + time.Sleep(time.Second * 2) + } + }() } // 获取 username 指定的用户的工作空间路径. @@ -140,9 +148,6 @@ func Save() bool { // 加载 Wide 配置. func Load() { - // 检查 Wide 运行环境 - Wide.CheckEnv() - bytes, _ := ioutil.ReadFile("conf/wide.json") err := json.Unmarshal(bytes, &Wide) diff --git a/event/events.go b/event/events.go index 0dfd4e2..8e86c6c 100644 --- a/event/events.go +++ b/event/events.go @@ -1,38 +1,55 @@ // 事件处理. package event -import ( - "github.com/golang/glog" -) +import "github.com/golang/glog" const ( EvtGOPATHNotFound = iota // 事件:找不到环境变量 $GOPATH EvtGOROOTNotFound // 事件:找不到环境变量 $GOROOT EvtGocodeNotFount // 事件:找不到 gocode EvtIDEStubNotFound // 事件:找不到 IDE stub + ) +const MaxQueueLength = 10 + // 全局事件队列. // 入队的事件将分发到每个用户的通知队列. -var EventQueue = make(chan int, 10) +var EventQueue = make(chan int, MaxQueueLength) // 用户事件队列. // 入队的事件将翻译为通知,并通过通知通道推送到前端. -var UserEventQueue map[string]chan int +var UserEventQueues = map[string]chan int{} // 加载事件处理. func Load() { go func() { - for { - // 获取事件 - event := <-EventQueue - + for event := range EventQueue { glog.V(5).Info("收到全局事件 [%d]", event) // 将事件分发到每个用户的事件队列里 - for _, userQueue := range UserEventQueue { + for _, userQueue := range UserEventQueues { userQueue <- event } } }() } + +// 添加一个用户事件队列. +func InitUserQueue(sid string) { + // FIXME: 会话过期后需要销毁对应的用户事件队列 + + q := UserEventQueues[sid] + if nil != q { + close(q) + } + + q = make(chan int, MaxQueueLength) + UserEventQueues[sid] = q + + go func() { + for event := range q { + glog.Infof("Session [%s] received a event [%d]", sid, event) + } + }() +} diff --git a/main.go b/main.go index b2e7866..f6aeb57 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "github.com/b3log/wide/event" "github.com/b3log/wide/file" "github.com/b3log/wide/i18n" + "github.com/b3log/wide/notification" "github.com/b3log/wide/output" "github.com/b3log/wide/shell" "github.com/b3log/wide/user" @@ -31,6 +32,9 @@ func init() { // 加载配置 conf.Load() + + // 定时检查 Wide 运行环境 + conf.CheckEnv() } // Wide 首页. @@ -108,6 +112,9 @@ func main() { http.HandleFunc("/shell/ws", shell.WSHandler) http.HandleFunc("/shell", shell.IndexHandler) + // 通知 + http.HandleFunc("/notification/ws", notification.WSHandler) + // 用户 http.HandleFunc("/user/new", user.AddUser) http.HandleFunc("/user/repos/init", user.InitGitRepos) diff --git a/notification/notifications.go b/notification/notifications.go index 56aceb2..f4c19b6 100644 --- a/notification/notifications.go +++ b/notification/notifications.go @@ -6,9 +6,10 @@ import ( "os" "os/exec" "runtime" - "strings" + "time" "github.com/b3log/wide/conf" + "github.com/b3log/wide/event" "github.com/b3log/wide/user" "github.com/golang/glog" "github.com/gorilla/websocket" @@ -22,25 +23,42 @@ type Notification struct { Message string } +// 一个用户会话的 WebSocket 通道结构. +type WSChannel struct { + Conn *websocket.Conn // WebSocket 连接 + Time time.Time // 该通道最近一次使用时间 +} + // 通知通道. -var notificationWS = map[string]*websocket.Conn{} +// , }> +var notificationWSs = map[string]map[string]WSChannel{} func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") username := session.Values["username"].(string) sid := session.Values["id"].(string) - notificationWS[sid], _ = websocket.Upgrade(w, r, nil, 1024, 1024) + conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) + wsChan := WSChannel{Conn: conn, Time: time.Now()} + + wsChans := notificationWSs[username] + if nil == wsChans { + wsChans = map[string]WSChannel{} + } + + wsChans[sid] = wsChan ret := map[string]interface{}{"output": "Notification initialized", "cmd": "init-notification"} - notificationWS[sid].WriteJSON(&ret) + wsChan.Conn.WriteJSON(&ret) - glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(notificationWS)) + glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(wsChans)) + + event.InitUserQueue(sid) input := map[string]interface{}{} for { - if err := notificationWS[sid].ReadJSON(&input); err != nil { + if err := wsChan.Conn.ReadJSON(&input); err != nil { if err.Error() == "EOF" { return } @@ -49,35 +67,16 @@ func WSHandler(w http.ResponseWriter, r *http.Request) { return } - glog.Error("Shell WS ERROR: " + err.Error()) + glog.Error("Notification WS ERROR: " + err.Error()) return } - inputCmd := input["cmd"].(string) - - cmds := strings.Split(inputCmd, "|") - commands := []*exec.Cmd{} - for _, cmdWithArgs := range cmds { - cmdWithArgs = strings.TrimSpace(cmdWithArgs) - cmdWithArgs := strings.Split(cmdWithArgs, " ") - args := []string{} - if len(cmdWithArgs) > 1 { - args = cmdWithArgs[1:] - } - - cmd := exec.Command(cmdWithArgs[0], args...) - commands = append(commands, cmd) - } - output := "" - if !strings.Contains(inputCmd, "clear") { - output = pipeCommands(username, commands...) - } - ret = map[string]interface{}{"output": output, "cmd": "shell-output"} + ret = map[string]interface{}{"output": output, "cmd": "notification-output"} - if err := notificationWS[sid].WriteJSON(&ret); err != nil { - glog.Error("Shell WS ERROR: " + err.Error()) + if err := wsChan.Conn.WriteJSON(&ret); err != nil { + glog.Error("Notification WS ERROR: " + err.Error()) return } } diff --git a/static/js/notification.js b/static/js/notification.js new file mode 100644 index 0000000..8bd4067 --- /dev/null +++ b/static/js/notification.js @@ -0,0 +1,28 @@ +var notificationWS = new WebSocket(config.channel.shell + '/notification/ws'); +notificationWS.onopen = function() { + console.log('[notification onopen] connected'); +}; +notificationWS.onmessage = function(e) { + console.log('[notification onmessage]' + e.data); + var data = JSON.parse(e.data); + if ('init-notification' !== data.cmd) { + $('#notification').val(data.output); + } +}; +notificationWS.onclose = function(e) { + console.log('[notification onclose] disconnected (' + e.code + ')'); + delete notificationWS; +}; +notificationWS.onerror = function(e) { + console.log('[notification onerror] ' + e); +}; + +var notification = { + init: function() { + + } +}; + +$(document).ready(function() { + notification.init(); +}); \ No newline at end of file diff --git a/view/index.html b/view/index.html index 709b09f..98215de 100644 --- a/view/index.html +++ b/view/index.html @@ -143,6 +143,10 @@ + + + + @@ -196,6 +200,7 @@ +