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 | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"converge/pkg/server/converge" | ||||
| 	"converge/pkg/support/websocketutil" | ||||
| 	"fmt" | ||||
| @ -134,13 +135,14 @@ func main() { | ||||
| 	// for the web browser getting live status updates.
 | ||||
| 	sessionService := websocketutil.WebSocketService{ | ||||
| 		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) | ||||
| 			location, err := converge.GetUserLocation(r) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			websession.WriteNotifications(location) | ||||
| 			websession.WriteNotifications(location, cancel) | ||||
| 		}, | ||||
| 		Text: true, | ||||
| 	} | ||||
|  | ||||
| @ -20,6 +20,7 @@ type WebSessions struct { | ||||
| type WebSession struct { | ||||
| 	notifications chan *models.State | ||||
| 	conn          net.Conn | ||||
| 	ctx           context.Context | ||||
| } | ||||
| 
 | ||||
| func NewWebSessions(notifications chan *models.State) *WebSessions { | ||||
| @ -41,16 +42,22 @@ func (sessions *WebSessions) notifyWebSessions(notification *models.State) { | ||||
| 	defer sessions.mutex.Unlock() | ||||
| 	sessions.lastNotification = notification | ||||
| 	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() | ||||
| 	defer sessions.mutex.Unlock() | ||||
| 	session := &WebSession{ | ||||
| 		notifications: make(chan *models.State, 10), | ||||
| 		conn:          wsConnection, | ||||
| 		ctx:           ctx, | ||||
| 	} | ||||
| 	sessions.sessions[session] = true | ||||
| 	sessions.logSessions() | ||||
| @ -70,9 +77,11 @@ func GetUserLocation(r *http.Request) (*time.Location, error) { | ||||
| 	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) | ||||
| 	defer timer.Stop() | ||||
| 	// if for some reason we cannot send notifications to the web client then the context is canceled.
 | ||||
| 	defer cancel() | ||||
| 	for { | ||||
| 		select { | ||||
| 		case notification, ok := <-session.notifications: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user