aboutsummaryrefslogtreecommitdiffstats
path: root/lib/agent/events.go
blob: e66f758b9a970e705e5f93b7b820a9cacd327724 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package agent

import (
	"fmt"
	"time"
)

// Events constants
const (
	// EventTypePrefix Used as event prefix
	EventTypePrefix = "event:" // following by event type

	// Supported Events type
	EVTAll           = "all"
	EVTServerConfig  = "server-config"        // data type ServerCfg
	EVTProjectAdd    = "project-add"          // data type ProjectConfig
	EVTProjectDelete = "project-delete"       // data type ProjectConfig
	EVTProjectChange = "project-state-change" // data type ProjectConfig
)

var _EVTAllList = []string{
	EVTServerConfig,
	EVTProjectAdd,
	EVTProjectDelete,
	EVTProjectChange,
}

// EventMsg Message send
type EventMsg struct {
	Time string      `json:"time"`
	Type string      `json:"type"`
	Data interface{} `json:"data"`
}

type EventDef struct {
	sids map[string]int
}

type Events struct {
	*Context
	eventsMap map[string]*EventDef
}

// NewEvents creates an instance of Events
func NewEvents(ctx *Context) *Events {
	evMap := make(map[string]*EventDef)
	for _, ev := range _EVTAllList {
		evMap[ev] = &EventDef{
			sids: make(map[string]int),
		}
	}
	return &Events{
		Context:   ctx,
		eventsMap: evMap,
	}
}

// GetList returns the list of all supported events
func (e *Events) GetList() []string {
	return _EVTAllList
}

// Register Used by a client/session to register to a specific (or all) event(s)
func (e *Events) Register(evName, sessionID string) error {
	evs := _EVTAllList
	if evName != EVTAll {
		if _, ok := e.eventsMap[evName]; !ok {
			return fmt.Errorf("Unsupported event type name")
		}
		evs = []string{evName}
	}
	for _, ev := range evs {
		e.eventsMap[ev].sids[sessionID]++
	}
	return nil
}

// UnRegister Used by a client/session to unregister event(s)
func (e *Events) UnRegister(evName, sessionID string) error {
	evs := _EVTAllList
	if evName != EVTAll {
		if _, ok := e.eventsMap[evName]; !ok {
			return fmt.Errorf("Unsupported event type name")
		}
		evs = []string{evName}
	}
	for _, ev := range evs {
		if _, exist := e.eventsMap[ev].sids[sessionID]; exist {
			delete(e.eventsMap[ev].sids, sessionID)
			break
		}
	}
	return nil
}

// Emit Used to manually emit an event
func (e *Events) Emit(evName string, data interface{}) error {
	var firstErr error

	if _, ok := e.eventsMap[evName]; !ok {
		return fmt.Errorf("Unsupported event type")
	}

	if e.LogLevelSilly {
		e.Log.Debugf("Emit Event %s: %v", evName, data)
	}

	firstErr = nil
	evm := e.eventsMap[evName]
	for sid := range evm.sids {
		so := e.webServer.sessions.IOSocketGet(sid)
		if so == nil {
			if firstErr == nil {
				firstErr = fmt.Errorf("IOSocketGet return nil")
			}
			continue
		}
		msg := EventMsg{
			Time: time.Now().String(),
			Type: evName,
			Data: data,
		}
		if err := (*so).Emit(EventTypePrefix+evName, msg); err != nil {
			e.Log.Errorf("WS Emit %v error : %v", EventTypePrefix+evName, err)
			if firstErr == nil {
				firstErr = err
			}
		}
	}

	return firstErr
}