Code is more robust and should now never try to send a notification to a web client that can block, using a context with cancellation.
This commit is contained in:
parent
55468c7135
commit
1983ee24de
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"converge/pkg/server/converge"
|
"converge/pkg/server/converge"
|
||||||
"converge/pkg/support/websocketutil"
|
"converge/pkg/support/websocketutil"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -134,13 +135,14 @@ func main() {
|
|||||||
// for the web browser getting live status updates.
|
// for the web browser getting live status updates.
|
||||||
sessionService := websocketutil.WebSocketService{
|
sessionService := websocketutil.WebSocketService{
|
||||||
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) {
|
||||||
websession := websessions.NewSession(conn)
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
websession := websessions.NewSession(conn, ctx)
|
||||||
defer websessions.SessionClosed(websession)
|
defer websessions.SessionClosed(websession)
|
||||||
location, err := converge.GetUserLocation(r)
|
location, err := converge.GetUserLocation(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
websession.WriteNotifications(location)
|
websession.WriteNotifications(location, cancel)
|
||||||
},
|
},
|
||||||
Text: true,
|
Text: true,
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ type WebSessions struct {
|
|||||||
type WebSession struct {
|
type WebSession struct {
|
||||||
notifications chan *models.State
|
notifications chan *models.State
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWebSessions(notifications chan *models.State) *WebSessions {
|
func NewWebSessions(notifications chan *models.State) *WebSessions {
|
||||||
@ -41,16 +42,22 @@ func (sessions *WebSessions) notifyWebSessions(notification *models.State) {
|
|||||||
defer sessions.mutex.Unlock()
|
defer sessions.mutex.Unlock()
|
||||||
sessions.lastNotification = notification
|
sessions.lastNotification = notification
|
||||||
for session, _ := range sessions.sessions {
|
for session, _ := range sessions.sessions {
|
||||||
session.notifications <- notification
|
select {
|
||||||
|
case <-session.ctx.Done():
|
||||||
|
// session is closed, will be removed at higher level when session is done.
|
||||||
|
case session.notifications <- notification:
|
||||||
|
// Sent notification
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sessions *WebSessions) NewSession(wsConnection net.Conn) *WebSession {
|
func (sessions *WebSessions) NewSession(wsConnection net.Conn, ctx context.Context) *WebSession {
|
||||||
sessions.mutex.Lock()
|
sessions.mutex.Lock()
|
||||||
defer sessions.mutex.Unlock()
|
defer sessions.mutex.Unlock()
|
||||||
session := &WebSession{
|
session := &WebSession{
|
||||||
notifications: make(chan *models.State, 10),
|
notifications: make(chan *models.State, 10),
|
||||||
conn: wsConnection,
|
conn: wsConnection,
|
||||||
|
ctx: ctx,
|
||||||
}
|
}
|
||||||
sessions.sessions[session] = true
|
sessions.sessions[session] = true
|
||||||
sessions.logSessions()
|
sessions.logSessions()
|
||||||
@ -70,9 +77,11 @@ func GetUserLocation(r *http.Request) (*time.Location, error) {
|
|||||||
return time.LoadLocation(tzName)
|
return time.LoadLocation(tzName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *WebSession) WriteNotifications(location *time.Location) {
|
func (session *WebSession) WriteNotifications(location *time.Location, cancel context.CancelFunc) {
|
||||||
timer := time.NewTicker(10 * time.Second)
|
timer := time.NewTicker(10 * time.Second)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
// if for some reason we cannot send notifications to the web client then the context is canceled.
|
||||||
|
defer cancel()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case notification, ok := <-session.notifications:
|
case notification, ok := <-session.notifications:
|
||||||
|
Loading…
Reference in New Issue
Block a user