Commit message (Collapse) | Author | Age | Files | Lines | |
---|---|---|---|---|---|
* | ws.go: Decrement course.Selected counter on commit failures | Runxi Yu | 2024-10-01 | 1 | -0/+6 |
| | |||||
* | ws.go: Reaffirm course choice when duplicate is requested | Runxi Yu | 2024-10-01 | 1 | -5/+13 |
| | | | | | | | | Laggy clients, extremely fast clicks, or other conditions could cause duplicate course choices to be sent, which would violate the uniqueness constraint. In this case the fact that the user has already chosen the course should be reaffirmed, rather than making it look like their choice was rejected. | ||||
* | ws.go: propagateCouldFail -> propagateIgnoreFailures | Runxi Yu | 2024-10-01 | 1 | -2/+2 |
| | | | | | | I think the new name better reflects the fact that it just ignores failures when propagating to each channel. The old name sounds like "this function itself could fail". | ||||
* | ws.go, schema.sql: Enforce uniqueness of course choices | Runxi Yu | 2024-10-01 | 1 | -42/+64 |
| | | | | References: https://todo.sr.ht/~runxiyu/cca/1 | ||||
* | ws.go, *.sql: Add course choices to the database | Runxi Yu | 2024-10-01 | 1 | -1/+33 |
| | | | | | | | | | | | | | | | | | | | | Note that this naive implementation currently allows users to submit multiple requests for the same course. See the TODO comment below: /* * 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...) */ References: https://todo.sr.ht/~runxiyu/cca/1 | ||||
* | ws.go: propagate -> propagateCouldFail | Runxi Yu | 2024-10-01 | 1 | -3/+8 |
| | |||||
* | ws.go: propagate course number updates in another goroutine | Runxi Yu | 2024-10-01 | 1 | -1/+1 |
| | |||||
* | ws.go: Separate c.Write calls into writeText() | Runxi Yu | 2024-09-30 | 1 | -25/+17 |
| | |||||
* | ws.go, utils.go: Document some synchronization design choices | Runxi Yu | 2024-09-30 | 1 | -1/+18 |
| | | | | Also use TryLock in setupChanPool, and fail when not successful. | ||||
* | *: Change license to AGPL-3.0-or-later | Runxi Yu | 2024-09-30 | 1 | -21/+11 |
| | |||||
* | {auth,index,ws}.go, schema.sql: Move session cookie into the user table | Runxi Yu | 2024-09-30 | 1 | -8/+8 |
| | | | | | | | One user shall only have one session at a time. This reduces the possibility of strange race conditions and simplifies the code a lot. References: https://todo.sr.ht/~runxiyu/cca/4 | ||||
* | index.html, main.js, ws.go: Enhance course selection rejection message | Runxi Yu | 2024-09-30 | 1 | -1/+1 |
| | |||||
* | ws.go, config.go, config.scfg.example: Attempt to fix deadlock | Runxi Yu | 2024-09-29 | 1 | -4/+7 |
| | | | | | | | When propagate tries to propagate a message to a connection that actually called propagate, it deadlocks because the it tries to send to that connection's send channel in the same goroutine. This is an attempt at a fix. | ||||
* | ws.go: Attempt to propagate messages | Runxi Yu | 2024-09-29 | 1 | -1/+11 |
| | |||||
* | ws.go: Implement course choice limits | Runxi Yu | 2024-09-29 | 1 | -0/+31 |
| | |||||
* | ws.go: protocolError is now its own function | Runxi Yu | 2024-09-29 | 1 | -28/+15 |
| | |||||
* | .ws.go: Close websocket on protocol errors | Runxi Yu | 2024-09-29 | 1 | -0/+12 |
| | |||||
* | ws.go: Stub for commands "Y" and "N", currently only counting arguments | Runxi Yu | 2024-09-29 | 1 | -0/+14 |
| | |||||
* | ws.go: chanPoolLock should be locked during setupChanPool | Runxi Yu | 2024-09-27 | 1 | -0/+2 |
| | |||||
* | ws.go: chanPool should be a map too | Runxi Yu | 2024-09-27 | 1 | -19/+8 |
| | |||||
* | *.go, cca.scfg.example: Expose performance options | Runxi Yu | 2024-09-26 | 1 | -3/+3 |
| | |||||
* | *.go: Wrap errors | Runxi Yu | 2024-09-26 | 1 | -3/+4 |
| | |||||
* | {auth,index,ws}.go: Add contexts for database calls | Runxi Yu | 2024-09-26 | 1 | -1/+1 |
| | |||||
* | ws.go: Reformat | Runxi Yu | 2024-09-26 | 1 | -1/+1 |
| | |||||
* | ws.go: Document chanPoolLock's purpose | Runxi Yu | 2024-09-24 | 1 | -0/+9 |
| | |||||
* | *.go: Linting | Runxi Yu | 2024-09-24 | 1 | -14/+20 |
| | |||||
* | {index,utils,ws}.go: Handle write errors | Runxi Yu | 2024-09-24 | 1 | -8/+28 |
| | |||||
* | {utils,auth,index,ws}.go: Handle errors in random number generation | Runxi Yu | 2024-09-24 | 1 | -1/+1 |
| | |||||
* | ws.go: Log userid and sessionid with channel pointer | Runxi Yu | 2024-09-24 | 1 | -3/+4 |
| | |||||
* | ws.go: chanPoolLock should be a RWMutex rather than a pointer to one | Runxi Yu | 2024-09-23 | 1 | -1/+1 |
| | | | | | | | A pointer to one could always be obtained via &chanPoolLock; but if I declare it as a pointer globally, I would need to initialize it somewhere so I don't get a null pointer dereference. It's more convenient to just declare it as the value. | ||||
* | ws.go: Add missing returns after authentication failure | Runxi Yu | 2024-09-23 | 1 | -0/+2 |
| | |||||
* | ws.go: Initial attempt to manage chanPool | Runxi Yu | 2024-09-23 | 1 | -13/+22 |
| | |||||
* | auth.go, ws.go: Update comments | Runxi Yu | 2024-09-23 | 1 | -5/+5 |
| | |||||
* | ws.go, main.js, index.html: Better WS documentation and structure | Runxi Yu | 2024-09-16 | 1 | -19/+55 |
| | |||||
* | ws.go: Fix previous commit's type inconsistencies | Runxi Yu | 2024-09-13 | 1 | -4/+5 |
| | |||||
* | ws.go: Very basic channels | Runxi Yu | 2024-09-13 | 1 | -5/+17 |
| | |||||
* | ws.go: Clarrify handleWs's purpose | Runxi Yu | 2024-09-12 | 1 | -1/+2 |
| | |||||
* | ws.go: Move the login logic to handleWs from handleConn | Runxi Yu | 2024-09-12 | 1 | -19/+38 |
| | |||||
* | ws.go: gofmt | Runxi Yu | 2024-09-12 | 1 | -3/+2 |
| | |||||
* | ws.go: Use channels to handle incoming messages | Runxi Yu | 2024-09-12 | 1 | -11/+30 |
| | |||||
* | ws.go: Document the message format | Runxi Yu | 2024-09-12 | 1 | -0/+25 |
| | |||||
* | ws.go: TODO: Select c.Read and a broadcast channel | Runxi Yu | 2024-09-11 | 1 | -0/+1 |
| | | | | | | | I'm not sure whether we need to spawn an entirely different goroutine, make a shared channel, and select between the channels. It certainlly doesn't seem like there's a trivial way to block from a synchronous function and a channel, but I might be wrong, being unfamiliar with Go's concurrency. | ||||
* | *.go: Shorter line lengths | Runxi Yu | 2024-09-09 | 1 | -3/+15 |
| | |||||
* | *.go: Add comments | Runxi Yu | 2024-09-09 | 1 | -1/+44 |
| | |||||
* | ws.go: splitMsg should return strings instead of bytes | Runxi Yu | 2024-09-09 | 1 | -7/+9 |
| | |||||
* | ws.go: Split IRC-style messages | Runxi Yu | 2024-09-09 | 1 | -3/+27 |
| | |||||
* | ws.go: gofmt | Runxi Yu | 2024-09-09 | 1 | -1/+1 |
| | |||||
* | ws.go: Check session cookie | Runxi Yu | 2024-09-08 | 1 | -2/+24 |
| | | | | I'm not sure if all browsers send them along in WebSocket requests. | ||||
* | ws.go: Don't close the connection that fast | Runxi Yu | 2024-09-08 | 1 | -7/+8 |
| | |||||
* | ws.go: Don't echo messages back | Runxi Yu | 2024-09-08 | 1 | -4/+9 |
| |