databag/net/server/internal/api_status.go

172 lines
3.5 KiB
Go
Raw Normal View History

2022-01-11 06:20:32 +00:00
package databag
import (
"log"
2022-01-14 18:57:19 +00:00
"sync"
2022-01-11 06:20:32 +00:00
"net/http"
2022-01-14 21:36:02 +00:00
"encoding/json"
"github.com/gorilla/websocket"
2022-01-14 18:57:19 +00:00
"databag/internal/store"
2022-01-11 06:20:32 +00:00
)
2022-01-14 18:57:19 +00:00
type accountRevision struct {
ProfileRevision int64
ContentRevision int64
ViewRevision int64
GroupRevision int64
LabelRevision int64
CardRevision int64
DialogueRevision int64
InsightRevision int64
}
2022-01-14 21:36:02 +00:00
var wsSync sync.Mutex
var wsExit = make(chan bool, 1)
2022-01-14 21:36:02 +00:00
var statusListener = make(map[uint][]chan<-[]byte)
var upgrader = websocket.Upgrader{}
2022-01-11 06:20:32 +00:00
func Status(w http.ResponseWriter, r *http.Request) {
2022-01-14 18:57:19 +00:00
// accept websocket connection
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
2022-01-14 21:36:02 +00:00
log.Println("Status: failed upgrade connection")
2022-01-14 18:57:19 +00:00
return
}
defer conn.Close()
log.Println("CONNECTED")
// receive announce message
2022-01-14 21:36:02 +00:00
var act uint = 0
// get revisions for the account
2022-01-16 07:25:43 +00:00
var account accountRevision
err = store.DB.Model(&store.Account{}).Where("ID = ?", act).First(&account).Error
2022-01-14 21:36:02 +00:00
if err != nil {
log.Println("Status - failed to get account revision")
// return
2022-01-14 21:36:02 +00:00
}
2022-01-16 07:25:43 +00:00
rev := getRevision(account)
2022-01-14 21:36:02 +00:00
// send current version
var msg []byte
msg, err = json.Marshal(rev)
if err != nil {
log.Println("Status - failed to marshal revision")
return
}
err = conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
log.Println("Status - failed to send initial revision")
return
}
2022-01-14 18:57:19 +00:00
// open channel for revisions
2022-01-14 21:36:02 +00:00
c := make(chan []byte)
defer close(c)
// register channel for revisions
AddStatusListener(0, c)
defer RemoveStatusListener(act, c)
// send revision until channel is closed
for {
select {
case msg := <-c:
err = conn.WriteMessage(websocket.TextMessage, msg)
if err != nil {
log.Println("Status - failed to send revision, closing")
return
}
case <-wsExit:
log.Println("Status - server exit")
wsExit<-true
return
}
}
2022-01-14 21:36:02 +00:00
}
2022-01-14 18:57:19 +00:00
2022-01-14 21:36:02 +00:00
func getRevision(rev accountRevision) Revision {
var r Revision
r.Profile = rev.ProfileRevision
r.Content = rev.ContentRevision
r.Label = rev.LabelRevision
r.Group = rev.GroupRevision
r.Card = rev.CardRevision
r.Dialogue = rev.DialogueRevision
r.Insight = rev.InsightRevision
return r
2022-01-14 18:57:19 +00:00
}
func ExitStatus() {
wsExit <- true
}
2022-01-14 18:57:19 +00:00
func SetStatus(act uint) {
// get revisions for the account
2022-01-14 21:36:02 +00:00
var ar accountRevision
err := store.DB.Model(&Revision{}).Where("ID = ?", act).First(&ar).Error
if err != nil {
log.Println("SetStatus - failed to retrieve account revisions")
return
}
rev := getRevision(ar)
var msg []byte
msg, err = json.Marshal(rev)
2022-01-14 18:57:19 +00:00
if err != nil {
2022-01-14 21:36:02 +00:00
log.Println("SetStatus - failed to marshal revision")
return
2022-01-14 18:57:19 +00:00
}
// lock access to statusListener
wsSync.Lock()
2022-01-14 21:36:02 +00:00
defer wsSync.Unlock()
2022-01-14 18:57:19 +00:00
2022-01-14 21:36:02 +00:00
// notify all listeners
2022-01-14 18:57:19 +00:00
chs, ok := statusListener[act]
if ok {
for _, ch := range chs {
2022-01-14 21:36:02 +00:00
ch <- msg
}
2022-01-14 18:57:19 +00:00
}
}
2022-01-14 21:36:02 +00:00
func AddStatusListener(act uint, ch chan<-[]byte) {
2022-01-14 18:57:19 +00:00
// lock access to statusListener
wsSync.Lock()
2022-01-14 21:36:02 +00:00
defer wsSync.Unlock()
2022-01-14 18:57:19 +00:00
2022-01-14 21:36:02 +00:00
// add new listener to map
2022-01-14 18:57:19 +00:00
chs, ok := statusListener[act]
if ok {
2022-01-14 21:36:02 +00:00
chs = append(chs, ch)
2022-01-14 18:57:19 +00:00
} else {
2022-01-14 21:36:02 +00:00
statusListener[act] = []chan<-[]byte{ch}
2022-01-14 18:57:19 +00:00
}
}
2022-01-14 21:36:02 +00:00
func RemoveStatusListener(act uint, ch chan<-[]byte) {
2022-01-14 18:57:19 +00:00
// lock access to statusListener
wsSync.Lock()
2022-01-14 21:36:02 +00:00
defer wsSync.Unlock()
2022-01-14 18:57:19 +00:00
2022-01-14 21:36:02 +00:00
// remove channel from map
2022-01-14 18:57:19 +00:00
chs, ok := statusListener[act]
if ok {
for i, c := range chs {
if ch == c {
if len(chs) == 1 {
delete(statusListener, act)
} else {
chs[i] = chs[len(chs)-1]
statusListener[act] = chs[:len(chs)-1]
}
2022-01-14 18:57:19 +00:00
}
}
2022-01-14 18:57:19 +00:00
}
2022-01-11 06:20:32 +00:00
}
2022-01-14 18:57:19 +00:00