2019-05-17 06:28:50 +03:00
|
|
|
// Copyright (c) 2014-present, b3log.org
|
2014-12-07 06:22:05 +03:00
|
|
|
//
|
2014-11-12 18:13:14 +03:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
2014-12-07 06:22:05 +03:00
|
|
|
//
|
2018-03-12 07:28:33 +03:00
|
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
2014-12-07 06:22:05 +03:00
|
|
|
//
|
2014-11-12 18:13:14 +03:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2014-12-07 06:22:05 +03:00
|
|
|
// Package event includes event related manipulations.
|
2014-09-15 10:24:40 +04:00
|
|
|
package event
|
|
|
|
|
2014-12-13 13:47:41 +03:00
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
|
2019-12-01 15:21:00 +03:00
|
|
|
"github.com/88250/gulu"
|
2014-12-13 13:47:41 +03:00
|
|
|
)
|
2014-09-15 10:24:40 +04:00
|
|
|
|
|
|
|
const (
|
2014-12-07 06:22:05 +03:00
|
|
|
// EvtCodeGOPATHNotFound indicates an event: not found $GOPATH env variable
|
|
|
|
EvtCodeGOPATHNotFound = iota
|
|
|
|
// EvtCodeGOROOTNotFound indicates an event: not found $GOROOT env variable
|
|
|
|
EvtCodeGOROOTNotFound
|
|
|
|
// EvtCodeGocodeNotFound indicates an event: not found gocode
|
|
|
|
EvtCodeGocodeNotFound
|
2015-08-05 07:58:39 +03:00
|
|
|
// EvtCodeIDEStubNotFound indicates an event: not found gotools
|
2014-12-07 06:22:05 +03:00
|
|
|
EvtCodeIDEStubNotFound
|
|
|
|
// EvtCodeServerInternalError indicates an event: server internal error
|
|
|
|
EvtCodeServerInternalError
|
2014-09-15 10:24:40 +04:00
|
|
|
)
|
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// Max length of queue.
|
2014-12-07 06:22:05 +03:00
|
|
|
const maxQueueLength = 10
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-12-13 13:47:41 +03:00
|
|
|
// Logger.
|
2019-05-24 16:04:25 +03:00
|
|
|
var logger = gulu.Log.NewLogger(os.Stdout)
|
2014-12-13 13:47:41 +03:00
|
|
|
|
2014-12-07 06:22:05 +03:00
|
|
|
// Event represents an event.
|
2014-09-15 19:20:01 +04:00
|
|
|
type Event struct {
|
2014-10-29 13:15:18 +03:00
|
|
|
Code int `json:"code"` // event code
|
|
|
|
Sid string `json:"sid"` // wide session id related
|
|
|
|
Data interface{} `json:"data"` // event data
|
2014-09-15 19:20:01 +04:00
|
|
|
}
|
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// Global event queue.
|
2014-09-25 09:37:59 +04:00
|
|
|
//
|
2014-10-29 13:15:18 +03:00
|
|
|
// Every event in this queue will be dispatched to each user event queue.
|
2014-12-07 06:22:05 +03:00
|
|
|
var EventQueue = make(chan *Event, maxQueueLength)
|
2014-09-15 10:24:40 +04:00
|
|
|
|
2014-12-07 06:22:05 +03:00
|
|
|
// UserEventQueue represents a user event queue.
|
2014-09-19 15:21:13 +04:00
|
|
|
type UserEventQueue struct {
|
2014-10-29 13:15:18 +03:00
|
|
|
Sid string // wide session id related
|
|
|
|
Queue chan *Event // queue
|
|
|
|
Handlers []Handler // event handlers
|
2014-09-19 15:21:13 +04:00
|
|
|
}
|
|
|
|
|
2014-12-07 06:22:05 +03:00
|
|
|
type queues map[string]*UserEventQueue
|
2014-09-15 10:24:40 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// User event queues.
|
2014-09-25 09:37:59 +04:00
|
|
|
//
|
2014-09-19 15:21:13 +04:00
|
|
|
// <sid, *UserEventQueue>
|
2014-12-07 06:22:05 +03:00
|
|
|
var UserEventQueues = queues{}
|
2014-09-15 19:20:01 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// Load initializes the event handling.
|
2014-09-15 10:24:40 +04:00
|
|
|
func Load() {
|
|
|
|
go func() {
|
2019-08-06 07:04:27 +03:00
|
|
|
defer gulu.Panic.Recover(nil)
|
2015-03-16 06:24:55 +03:00
|
|
|
|
2014-09-15 14:03:52 +04:00
|
|
|
for event := range EventQueue {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Debugf("Received a global event [code=%d]", event.Code)
|
2014-09-15 10:24:40 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// dispatch the event to each user event queue
|
2014-09-15 14:03:52 +04:00
|
|
|
for _, userQueue := range UserEventQueues {
|
2014-10-28 19:04:46 +03:00
|
|
|
event.Sid = userQueue.Sid
|
|
|
|
|
2014-09-19 15:21:13 +04:00
|
|
|
userQueue.Queue <- event
|
2014-09-15 10:24:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// AddHandler adds the specified handlers to user event queues.
|
2014-09-19 15:21:13 +04:00
|
|
|
func (uq *UserEventQueue) AddHandler(handlers ...Handler) {
|
2015-04-27 08:54:49 +03:00
|
|
|
uq.Handlers = append(uq.Handlers, handlers...)
|
2014-09-19 15:21:13 +04:00
|
|
|
}
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// New initializes a user event queue with the specified wide session id.
|
2014-12-07 06:22:05 +03:00
|
|
|
func (ueqs queues) New(sid string) *UserEventQueue {
|
2015-06-22 03:36:02 +03:00
|
|
|
|
|
|
|
if q, ok := ueqs[sid]; ok {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Warnf("Already exist a user queue in session [%s]", sid)
|
2014-09-15 14:03:52 +04:00
|
|
|
|
2014-09-19 15:21:13 +04:00
|
|
|
return q
|
2014-09-15 19:20:01 +04:00
|
|
|
}
|
|
|
|
|
2015-06-22 03:36:02 +03:00
|
|
|
q := &UserEventQueue{
|
2014-09-19 15:21:13 +04:00
|
|
|
Sid: sid,
|
2014-12-07 06:22:05 +03:00
|
|
|
Queue: make(chan *Event, maxQueueLength),
|
2014-09-15 19:20:01 +04:00
|
|
|
}
|
|
|
|
|
2014-09-19 15:21:13 +04:00
|
|
|
ueqs[sid] = q
|
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
go func() { // start listening
|
2019-08-06 07:04:27 +03:00
|
|
|
defer gulu.Panic.Recover(nil)
|
2015-03-16 06:24:55 +03:00
|
|
|
|
2014-10-28 19:04:46 +03:00
|
|
|
for evt := range q.Queue {
|
2014-12-13 13:47:41 +03:00
|
|
|
logger.Debugf("Session [%s] received an event [%d]", sid, evt.Code)
|
2014-09-15 19:20:01 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// process event by each handlers
|
2014-09-19 15:21:13 +04:00
|
|
|
for _, handler := range q.Handlers {
|
2014-10-28 19:04:46 +03:00
|
|
|
handler.Handle(evt)
|
2014-09-15 19:20:01 +04:00
|
|
|
}
|
2014-09-15 14:03:52 +04:00
|
|
|
}
|
|
|
|
}()
|
2014-09-19 15:21:13 +04:00
|
|
|
|
|
|
|
return q
|
2014-09-15 14:03:52 +04:00
|
|
|
}
|
2014-09-15 19:20:01 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// Close closes a user event queue with the specified wide session id.
|
2014-12-07 06:22:05 +03:00
|
|
|
func (ueqs queues) Close(sid string) {
|
2014-09-20 06:39:29 +04:00
|
|
|
|
2015-06-22 03:36:02 +03:00
|
|
|
if q, ok := ueqs[sid]; ok {
|
|
|
|
close(q.Queue)
|
|
|
|
delete(ueqs, sid)
|
|
|
|
}
|
2014-09-20 06:39:29 +04:00
|
|
|
}
|
|
|
|
|
2014-12-07 06:22:05 +03:00
|
|
|
// Handler represents an event handler.
|
2014-09-15 19:20:01 +04:00
|
|
|
type Handler interface {
|
|
|
|
Handle(event *Event)
|
|
|
|
}
|
|
|
|
|
2014-12-07 06:29:45 +03:00
|
|
|
// HandleFunc represents a handler function.
|
|
|
|
type HandleFunc func(event *Event)
|
2014-09-15 19:20:01 +04:00
|
|
|
|
2014-10-29 13:15:18 +03:00
|
|
|
// Default implementation of event handling.
|
2014-12-07 06:29:45 +03:00
|
|
|
func (fn HandleFunc) Handle(event *Event) {
|
2014-09-15 19:20:01 +04:00
|
|
|
fn(event)
|
|
|
|
}
|