Fix #50
This commit is contained in:
parent
24c75e8125
commit
a4ce0583b7
|
@ -44,7 +44,6 @@ var rawWide conf
|
||||||
func CheckEnv() {
|
func CheckEnv() {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
|
||||||
if "" == os.Getenv("GOPATH") {
|
if "" == os.Getenv("GOPATH") {
|
||||||
glog.Fatal("Not found $GOPATH")
|
glog.Fatal("Not found $GOPATH")
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
|
@ -60,7 +59,7 @@ func CheckEnv() {
|
||||||
cmd := exec.Command(gocode, "close")
|
cmd := exec.Command(gocode, "close")
|
||||||
_, err := cmd.Output()
|
_, err := cmd.Output()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
event.EventQueue <- event.EvtGocodeNotFount
|
event.EventQueue <- event.EvtCodeGocodeNotFound
|
||||||
glog.Warningf("Not found gocode [%s]", gocode)
|
glog.Warningf("Not found gocode [%s]", gocode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +67,12 @@ func CheckEnv() {
|
||||||
cmd = exec.Command(ide_stub, "version")
|
cmd = exec.Command(ide_stub, "version")
|
||||||
_, err = cmd.Output()
|
_, err = cmd.Output()
|
||||||
if nil != err {
|
if nil != err {
|
||||||
event.EventQueue <- event.EvtIDEStubNotFound
|
event.EventQueue <- event.EvtCodeIDEStubNotFound
|
||||||
glog.Warningf("Not found ide_stub [%s]", ide_stub)
|
glog.Warningf("Not found ide_stub [%s]", ide_stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Second * 2)
|
// 7 分钟进行一次检查
|
||||||
|
time.Sleep(time.Minute * 7)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,31 @@ package event
|
||||||
import "github.com/golang/glog"
|
import "github.com/golang/glog"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EvtGOPATHNotFound = iota // 事件:找不到环境变量 $GOPATH
|
EvtCodeGOPATHNotFound = iota // 事件代码:找不到环境变量 $GOPATH
|
||||||
EvtGOROOTNotFound // 事件:找不到环境变量 $GOROOT
|
EvtCodeGOROOTNotFound // 事件代码:找不到环境变量 $GOROOT
|
||||||
EvtGocodeNotFount // 事件:找不到 gocode
|
EvtCodeGocodeNotFound // 事件代码:找不到 gocode
|
||||||
EvtIDEStubNotFound // 事件:找不到 IDE stub
|
EvtCodeIDEStubNotFound // 事件代码:找不到 IDE stub
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 事件队列最大长度.
|
||||||
const MaxQueueLength = 10
|
const MaxQueueLength = 10
|
||||||
|
|
||||||
|
// 事件结构.
|
||||||
|
type Event struct {
|
||||||
|
Code int `json:"code"` // 事件代码
|
||||||
|
Sid string `json:"sid"` // 用户会话 id
|
||||||
|
}
|
||||||
|
|
||||||
// 全局事件队列.
|
// 全局事件队列.
|
||||||
// 入队的事件将分发到每个用户的通知队列.
|
// 入队的事件将分发到每个用户的通知队列.
|
||||||
var EventQueue = make(chan int, MaxQueueLength)
|
var EventQueue = make(chan int, MaxQueueLength)
|
||||||
|
|
||||||
// 用户事件队列.
|
// 用户事件队列.
|
||||||
// 入队的事件将翻译为通知,并通过通知通道推送到前端.
|
|
||||||
var UserEventQueues = map[string]chan int{}
|
var UserEventQueues = map[string]chan int{}
|
||||||
|
|
||||||
|
// 用户事件处理器集.
|
||||||
|
var UserEventHandlers = map[string]*Handlers{}
|
||||||
|
|
||||||
// 加载事件处理.
|
// 加载事件处理.
|
||||||
func Load() {
|
func Load() {
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -35,21 +43,51 @@ func Load() {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加一个用户事件队列.
|
// 初始化一个用户事件队列.
|
||||||
func InitUserQueue(sid string) {
|
func InitUserQueue(sid string, handlers ...Handler) {
|
||||||
// FIXME: 会话过期后需要销毁对应的用户事件队列
|
// FIXME: 会话过期后需要销毁对应的用户事件队列
|
||||||
|
|
||||||
q := UserEventQueues[sid]
|
q := UserEventQueues[sid]
|
||||||
if nil != q {
|
if nil != q {
|
||||||
close(q)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
q = make(chan int, MaxQueueLength)
|
q = make(chan int, MaxQueueLength)
|
||||||
UserEventQueues[sid] = q
|
UserEventQueues[sid] = q
|
||||||
|
|
||||||
|
if nil == UserEventHandlers[sid] {
|
||||||
|
UserEventHandlers[sid] = new(Handlers)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, handler := range handlers {
|
||||||
|
UserEventHandlers[sid].add(handler)
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for event := range q {
|
for evtCode := range q {
|
||||||
glog.Infof("Session [%s] received a event [%d]", sid, event)
|
glog.V(5).Infof("Session [%s] received a event [%d]", sid, evtCode)
|
||||||
|
|
||||||
|
// 将事件交给事件处理器进行处理
|
||||||
|
for _, handler := range *UserEventHandlers[sid] {
|
||||||
|
e := Event{Code: evtCode, Sid: sid}
|
||||||
|
handler.Handle(&e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Handler interface {
|
||||||
|
Handle(event *Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandleFunc func(event *Event)
|
||||||
|
|
||||||
|
func (fn HandleFunc) Handle(event *Event) {
|
||||||
|
fn(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handlers []Handler
|
||||||
|
|
||||||
|
func (handlers *Handlers) add(handler Handler) {
|
||||||
|
*handlers = append(*handlers, handler)
|
||||||
|
}
|
||||||
|
|
|
@ -272,7 +272,7 @@ func listFiles(dirname string) []string {
|
||||||
|
|
||||||
func getIconSkin(filenameExtension string) string {
|
func getIconSkin(filenameExtension string) string {
|
||||||
switch filenameExtension {
|
switch filenameExtension {
|
||||||
case ".gitignore", "", ".exe", ".s":
|
case ".gitignore", "", ".exe", ".s", ".tar", ".zip", ".rar", ".gz": // 不支持显示图标的文件
|
||||||
return "ico-ztree-other "
|
return "ico-ztree-other "
|
||||||
case ".json", ".js":
|
case ".json", ".js":
|
||||||
return "ico-ztree-js "
|
return "ico-ztree-js "
|
||||||
|
|
|
@ -21,5 +21,7 @@
|
||||||
"goget": "go get",
|
"goget": "go get",
|
||||||
"goinstall": "go install",
|
"goinstall": "go install",
|
||||||
"build_n_run": "构建 & 运行",
|
"build_n_run": "构建 & 运行",
|
||||||
"full_screen": "全屏"
|
"full_screen": "全屏",
|
||||||
|
"notification_2": "没有检查到 gocode,这将会导致 [自动完成] 失效",
|
||||||
|
"notification_3": "没有检查到 ide_stub,这将会导致 [跳转到声明]、[查找使用] 失效"
|
||||||
}
|
}
|
|
@ -8,52 +8,83 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"strconv"
|
||||||
"github.com/b3log/wide/conf"
|
"github.com/b3log/wide/conf"
|
||||||
"github.com/b3log/wide/event"
|
"github.com/b3log/wide/event"
|
||||||
|
"github.com/b3log/wide/i18n"
|
||||||
"github.com/b3log/wide/user"
|
"github.com/b3log/wide/user"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Error = "ERROR" // 通知.严重程度:ERROR
|
||||||
|
Warn = "WARN" // 通知.严重程度:WARN
|
||||||
|
Info = "INFO" // 通知.严重程度:INFO
|
||||||
|
|
||||||
|
Setup = "Setup" // 通知.类型:安装
|
||||||
|
)
|
||||||
|
|
||||||
// 通知结构.
|
// 通知结构.
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
Event int
|
event *event.Event
|
||||||
Type string
|
Type string `json:"type"`
|
||||||
Severity string // ERROR/WARN/INFO
|
Severity string `json:"severity"`
|
||||||
Message string
|
Message string `json:"message"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一个用户会话的 WebSocket 通道结构.
|
// 一个用户会话的 WebSocket 通道结构.
|
||||||
type WSChannel struct {
|
type WSChannel struct {
|
||||||
Conn *websocket.Conn // WebSocket 连接
|
Conn *websocket.Conn // WebSocket 连接
|
||||||
|
Request *http.Request // 关联的 HTTP 请求
|
||||||
Time time.Time // 该通道最近一次使用时间
|
Time time.Time // 该通道最近一次使用时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通知通道.
|
// 通知通道.
|
||||||
// <username, {<sid1, WSChannel1>, <sid2, WSChannel2>}>
|
// <sid, WSChannel>
|
||||||
var notificationWSs = map[string]map[string]WSChannel{}
|
var notificationWSs = map[string]*WSChannel{}
|
||||||
|
|
||||||
|
func event2Notification(e *event.Event) {
|
||||||
|
if nil == notificationWSs[e.Sid] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wsChannel := notificationWSs[e.Sid]
|
||||||
|
|
||||||
|
var notification Notification
|
||||||
|
|
||||||
|
switch e.Code {
|
||||||
|
case event.EvtCodeGocodeNotFound:
|
||||||
|
notification = Notification{event: e, Type: Setup, Severity: Error}
|
||||||
|
case event.EvtCodeIDEStubNotFound:
|
||||||
|
notification = Notification{event: e, Type: Setup, Severity: Error}
|
||||||
|
default:
|
||||||
|
glog.Warningf("Can't handle event[code=%d]", e.Code)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msgs := i18n.GetLangs(wsChannel.Request)
|
||||||
|
notification.Message = msgs["notification_"+strconv.Itoa(e.Code)].(string)
|
||||||
|
|
||||||
|
wsChannel.Conn.WriteJSON(¬ification)
|
||||||
|
}
|
||||||
|
|
||||||
func WSHandler(w http.ResponseWriter, r *http.Request) {
|
func WSHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
session, _ := user.Session.Get(r, "wide-session")
|
session, _ := user.Session.Get(r, "wide-session")
|
||||||
username := session.Values["username"].(string)
|
|
||||||
sid := session.Values["id"].(string)
|
sid := session.Values["id"].(string)
|
||||||
|
|
||||||
conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024)
|
conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024)
|
||||||
wsChan := WSChannel{Conn: conn, Time: time.Now()}
|
wsChan := WSChannel{Conn: conn, Request: r, Time: time.Now()}
|
||||||
|
|
||||||
wsChans := notificationWSs[username]
|
notificationWSs[sid] = &wsChan
|
||||||
if nil == wsChans {
|
|
||||||
wsChans = map[string]WSChannel{}
|
|
||||||
}
|
|
||||||
|
|
||||||
wsChans[sid] = wsChan
|
|
||||||
|
|
||||||
ret := map[string]interface{}{"output": "Notification initialized", "cmd": "init-notification"}
|
ret := map[string]interface{}{"output": "Notification initialized", "cmd": "init-notification"}
|
||||||
wsChan.Conn.WriteJSON(&ret)
|
wsChan.Conn.WriteJSON(&ret)
|
||||||
|
|
||||||
glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(wsChans))
|
glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(notificationWSs))
|
||||||
|
|
||||||
event.InitUserQueue(sid)
|
// 初始化用户事件队列
|
||||||
|
event.InitUserQueue(sid, event.HandleFunc(event2Notification))
|
||||||
|
|
||||||
input := map[string]interface{}{}
|
input := map[string]interface{}{}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue