summaryrefslogtreecommitdiff
path: root/ws.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ws.go34
1 files changed, 33 insertions, 1 deletions
diff --git a/ws.go b/ws.go
index 04714e5..68dc77a 100644
--- a/ws.go
+++ b/ws.go
@@ -52,6 +52,7 @@ import (
"net/http"
"strconv"
"sync"
+ "time"
"github.com/coder/websocket"
"github.com/jackc/pgx/v5"
@@ -326,6 +327,18 @@ func handleConn(
}
courseID := int(_courseID)
course := courses[courseID]
+ /*
+ * TODO: Ensure that the user is not already enrolled in this course
+ * and pay attention to relevant race conditions. It might be useful
+ * to restructure this part, to begin a transaction that adds the user
+ * to the database (and check the (currently not existing) uniqueness)
+ * constraint at that exact moment, and abort the transaction if the
+ * course limit is exceeded.
+ * Or perhaps choices should be also stored in an internal data
+ * structure, though that requires extra attention on consistency
+ * issues between the internal data structure and the database.
+ * (Sometime I should really go fix the LMDB bindings...)
+ */
ok := false
func() {
course.SelectedLock.Lock()
@@ -339,7 +352,26 @@ func handleConn(
ok = false
}()
if ok {
- /* TODO: Add it to the database */
+ _, err = db.Exec(
+ ctx, /* TODO: Do we really want this to be in a request context? */
+ "INSERT INTO choices (seltime, userid, courseid) VALUES ($1, $2, $3)",
+ time.Now().UnixMicro(),
+ userID,
+ courseID,
+ /* TODO: Set uniqueness constraint for each (userid, courseid) pair */
+ )
+ if err != nil {
+ go func() { /* Separate goroutine because we don't need a response from this operation */
+ course.SelectedLock.Lock()
+ defer course.SelectedLock.Unlock()
+ course.Selected--
+ propagateCouldFail(fmt.Sprintf("N %d %d", courseID, course.Selected))
+ }()
+ err := writeText(ctx, c, "R "+mar[1]+" :Database error") /* TODO: Handle this better */
+ if err != nil {
+ return fmt.Errorf("error rejecting course choice: %w", err)
+ }
+ }
err := writeText(ctx, c, "Y "+mar[1])
if err != nil {
return fmt.Errorf("error affirming course choice: %w", err)