aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--endpoint_ws.go14
-rw-r--r--errors.go4
-rw-r--r--ws_connection.go28
-rw-r--r--ws_utils.go24
-rw-r--r--wsmsg_choose.go40
-rw-r--r--wsmsg_confirm.go5
-rw-r--r--wsmsg_hello.go5
-rw-r--r--wsmsg_unchoose.go19
-rw-r--r--wsmsg_unconfirm.go3
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
}
}
diff --git a/errors.go b/errors.go
index 3aa92f4..3921d49 100644
--- a/errors.go
+++ b/errors.go
@@ -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(