diff options
Diffstat (limited to '')
-rw-r--r-- | endpoint_ws.go | 14 | ||||
-rw-r--r-- | errors.go | 4 | ||||
-rw-r--r-- | ws_connection.go | 28 | ||||
-rw-r--r-- | ws_utils.go | 24 | ||||
-rw-r--r-- | wsmsg_choose.go | 40 | ||||
-rw-r--r-- | wsmsg_confirm.go | 5 | ||||
-rw-r--r-- | wsmsg_hello.go | 5 | ||||
-rw-r--r-- | wsmsg_unchoose.go | 19 | ||||
-rw-r--r-- | wsmsg_unconfirm.go | 3 |
9 files changed, 40 insertions, 102 deletions
diff --git a/endpoint_ws.go b/endpoint_ws.go index 4ec31cb..e17c262 100644 --- a/endpoint_ws.go +++ b/endpoint_ws.go @@ -67,14 +67,12 @@ func handleWs(w http.ResponseWriter, req *http.Request) { err = handleConn(req.Context(), c, userID, department) if err != nil { - err := writeText(req.Context(), c, "E :"+err.Error()) - if err != nil { - slog.Error( - "websocket", - "user", userID, - "error", err, - ) - } + slog.Error( + "websocket", + "user", userID, + "error", err, + ) + _ = writeText(req.Context(), c, "E :"+err.Error()) return } } @@ -39,6 +39,7 @@ var ( errInvalidCourseType = errors.New("invalid course type") errInvalidCourseGroup = errors.New("invalid course group") errMultipleChoicesInOneGroup = errors.New("multiple choices per group per user") + errCourseGroupHandlingError = errors.New("error handling course group") errUnsupportedDatabaseType = errors.New("unsupported db type") errUnexpectedDBError = errors.New("unexpected database error") errCannotSend = errors.New("cannot send") @@ -73,6 +74,9 @@ var ( errUnexpectedNilCSVLine = errors.New("unexpected nil csv line") errWhileSetttingUpCourseTablesAgain = errors.New("error while setting up course tables again") errCannotWriteTemplate = errors.New("cannot write template") + errUnknownCommand = errors.New("unknown command") + errBadNumberOfArguments = errors.New("bad number of arguments") + errInvalidYearGroupOrCourseType = errors.New("invalid year group or course type (something is broken)") // errInvalidCourseID = errors.New("invalid course id") ) diff --git a/ws_connection.go b/ws_connection.go index abe8425..fcddbcd 100644 --- a/ws_connection.go +++ b/ws_connection.go @@ -22,8 +22,6 @@ package main import ( "context" - "errors" - "fmt" "log/slog" "sync" "sync/atomic" @@ -53,12 +51,11 @@ func handleConn( c *websocket.Conn, userID string, department string, -) (retErr error) { +) error { send := make(chan string, config.Perf.SendQ) chanPool.Store(userID, &send) defer chanPool.CompareAndDelete(userID, &send) - reportError := makeReportError(ctx, c) newCtx, newCancel := context.WithCancel(ctx) _cancel, ok := cancelPool.Load(userID) @@ -73,15 +70,6 @@ func handleConn( defer func() { cancelPool.CompareAndDelete(userID, &newCancel) - if errors.Is(retErr, context.Canceled) { - /* - * Only works if it's newCtx that has been canceled - * rather than the original ctx, which is kinda what - * we intend - */ - _ = writeText(ctx, c, "E :Context canceled") - } - /* TODO: Report errors properly */ }() /* TODO: Tell the user their current choices here. Deprecate HELLO. */ @@ -154,12 +142,7 @@ func handleConn( var userCourseTypes userCourseTypesT = make(map[string]int) err := populateUserCourseTypesAndGroups(newCtx, &userCourseTypes, &userCourseGroups, userID) if err != nil { - return reportError( - fmt.Sprintf( - "cannot populate user course types/groups: %v", - err, - ), - ) + return err } /* @@ -296,7 +279,6 @@ func handleConn( err := messageHello( newCtx, c, - reportError, mar, userID, ) @@ -307,7 +289,6 @@ func handleConn( err := messageChooseCourse( newCtx, c, - reportError, mar, userID, &userCourseGroups, @@ -320,7 +301,6 @@ func handleConn( err := messageUnchooseCourse( newCtx, c, - reportError, mar, userID, &userCourseGroups, @@ -333,7 +313,6 @@ func handleConn( err := messageConfirm( newCtx, c, - reportError, mar, userID, department, @@ -346,7 +325,6 @@ func handleConn( err := messageUnconfirm( newCtx, c, - reportError, mar, userID, ) @@ -354,7 +332,7 @@ func handleConn( return err } default: - return reportError("Unknown command " + mar[0]) + return wrapAny(errUnknownCommand, mar[0]) } } } diff --git a/ws_utils.go b/ws_utils.go index da51224..76b9714 100644 --- a/ws_utils.go +++ b/ws_utils.go @@ -80,30 +80,6 @@ endl: return mar } -func baseReportError( - ctx context.Context, - conn *websocket.Conn, - e string, -) error { - err := writeText(ctx, conn, "E :"+e) - if err != nil { - return fmt.Errorf("error reporting protocol violation: %w", err) - } - err = conn.Close(websocket.StatusProtocolError, e) - if err != nil { - return fmt.Errorf("error closing websocket: %w", err) - } - return nil -} - -type reportErrorT func(e string) error - -func makeReportError(ctx context.Context, conn *websocket.Conn) reportErrorT { - return func(e string) error { - return baseReportError(ctx, conn, e) - } -} - func propagateSelectedUpdate(course *courseT) { course.Usems.Range(func(key, value interface{}) bool { _ = key diff --git a/wsmsg_choose.go b/wsmsg_choose.go index 8a177db..4c03431 100644 --- a/wsmsg_choose.go +++ b/wsmsg_choose.go @@ -23,7 +23,6 @@ package main import ( "context" "errors" - "fmt" "log/slog" "strconv" "sync/atomic" @@ -37,7 +36,6 @@ import ( func messageChooseCourse( ctx context.Context, c *websocket.Conn, - reportError reportErrorT, mar []string, userID string, userCourseGroups *userCourseGroupsT, @@ -64,24 +62,24 @@ func messageChooseCourse( } if len(mar) != 2 { - return reportError("Invalid number of arguments for Y") + return errBadNumberOfArguments } _courseID, err := strconv.ParseInt(mar[1], 10, strconv.IntSize) if err != nil { - return reportError("Course ID must be an integer") + return errNoSuchCourse } courseID := int(_courseID) _course, ok := courses.Load(courseID) if !ok { - return reportError("no such course") + return errNoSuchCourse } course, ok := _course.(*courseT) if !ok { panic("courses map has non-\"*courseT\" items") } if course == nil { - return reportError("couse is nil") + return errNoSuchCourse } if _, ok := (*userCourseGroups)[course.Group]; ok { @@ -98,16 +96,12 @@ func messageChooseCourse( err = func() (returnedError error) { tx, err := db.Begin(ctx) if err != nil { - return reportError( - "Database error while beginning transaction", - ) + return wrapError(errUnexpectedDBError, err) } defer func() { err := tx.Rollback(ctx) if err != nil && (!errors.Is(err, pgx.ErrTxClosed)) { - returnedError = reportError( - "Database error while rolling back transaction in defer block", - ) + returnedError = wrapError(errUnexpectedDBError, err) return } }() @@ -123,18 +117,16 @@ func messageChooseCourse( var pgErr *pgconn.PgError if errors.As(err, &pgErr) && pgErr.Code == pgErrUniqueViolation { - err := writeText(ctx, c, "Y "+mar[1]) - if err != nil { - return fmt.Errorf( - "error reaffirming course choice: %w", - err, + err2 := writeText(ctx, c, "Y "+mar[1]) + if err2 != nil { + return wrapError( + err2, + wrapError(errUnexpectedDBError, err), ) } return nil } - return reportError( - "Database error while inserting course choice", - ) + return wrapError(errUnexpectedDBError, err) } ok := func() bool { @@ -170,9 +162,7 @@ func messageChooseCourse( err, ) } - return reportError( - "Database error while committing transaction", - ) + return wrapError(errUnexpectedDBError, err) } /* @@ -202,9 +192,7 @@ func messageChooseCourse( } else { err := tx.Rollback(ctx) if err != nil { - return reportError( - "Database error while rolling back transaction due to course limit", - ) + return wrapError(errUnexpectedDBError, err) } err = writeText(ctx, c, "R "+mar[1]+" :Full") if err != nil { diff --git a/wsmsg_confirm.go b/wsmsg_confirm.go index 2f2b07f..7657034 100644 --- a/wsmsg_confirm.go +++ b/wsmsg_confirm.go @@ -31,7 +31,6 @@ import ( func messageConfirm( ctx context.Context, c *websocket.Conn, - reportError reportErrorT, mar []string, userID string, department string, @@ -62,7 +61,7 @@ func messageConfirm( for courseType := range courseTypes { minimum, err := getCourseTypeMinimumForYearGroup(department, courseType) if err != nil { - return reportError("Invalid year group or course type, something is broken") + return wrapError(errInvalidYearGroupOrCourseType, err) } if (*userCourseTypes)[courseType] < minimum { return writeText( @@ -84,7 +83,7 @@ func messageConfirm( userID, ) if err != nil { - return reportError("error updating database setting confirmation") + return wrapError(errUnexpectedDBError, err) } return writeText( diff --git a/wsmsg_hello.go b/wsmsg_hello.go index 08e8e8c..f015552 100644 --- a/wsmsg_hello.go +++ b/wsmsg_hello.go @@ -32,7 +32,6 @@ import ( func messageHello( ctx context.Context, c *websocket.Conn, - reportError reportErrorT, mar []string, userID string, ) error { @@ -53,11 +52,11 @@ func messageHello( userID, ) if err != nil { - return reportError("error fetching choices") + return wrapError(errUnexpectedDBError, err) } courseIDs, err := pgx.CollectRows(rows, pgx.RowTo[string]) if err != nil { - return reportError("error collecting choices") + return wrapError(errUnexpectedDBError, err) } if atomic.LoadUint32(&state) == 2 { diff --git a/wsmsg_unchoose.go b/wsmsg_unchoose.go index ea1fa1f..90c8eca 100644 --- a/wsmsg_unchoose.go +++ b/wsmsg_unchoose.go @@ -31,7 +31,6 @@ import ( func messageUnchooseCourse( ctx context.Context, c *websocket.Conn, - reportError reportErrorT, mar []string, userID string, userCourseGroups *userCourseGroupsT, @@ -58,24 +57,24 @@ func messageUnchooseCourse( } if len(mar) != 2 { - return reportError("Invalid number of arguments for N") + return errBadNumberOfArguments } _courseID, err := strconv.ParseInt(mar[1], 10, strconv.IntSize) if err != nil { - return reportError("Course ID must be an integer") + return errNoSuchCourse } courseID := int(_courseID) _course, ok := courses.Load(courseID) if !ok { - return reportError("no such course") + return errNoSuchCourse } course, ok := _course.(*courseT) if !ok { panic("courses map has non-\"*courseT\" items") } if course == nil { - return reportError("couse is nil") + return errNoSuchCourse } ct, err := db.Exec( @@ -85,9 +84,7 @@ func messageUnchooseCourse( courseID, ) if err != nil { - return reportError( - "Database error while deleting course choice", - ) + return wrapError(errUnexpectedDBError, err) } if ct.RowsAffected() != 0 { @@ -101,18 +98,18 @@ func messageUnchooseCourse( _course, ok := courses.Load(courseID) if !ok { - return reportError("no such course") + return errNoSuchCourse } course, ok := _course.(*courseT) if !ok { panic("courses map has non-\"*courseT\" items") } if course == nil { - return reportError("couse is nil") + return errNoSuchCourse } if _, ok := (*userCourseGroups)[course.Group]; !ok { - return reportError("inconsistent user course groups") + return errCourseGroupHandlingError } delete(*userCourseGroups, course.Group) (*userCourseTypes)[course.Type]-- diff --git a/wsmsg_unconfirm.go b/wsmsg_unconfirm.go index 48e95c7..43390a9 100644 --- a/wsmsg_unconfirm.go +++ b/wsmsg_unconfirm.go @@ -30,7 +30,6 @@ import ( func messageUnconfirm( ctx context.Context, c *websocket.Conn, - reportError reportErrorT, mar []string, userID string, ) error { @@ -62,7 +61,7 @@ func messageUnconfirm( userID, ) if err != nil { - return reportError("error updating database setting confirmation") + return wrapError(errUnexpectedDBError, err) } return writeText( |