Skip to content

Commit 135ffd6

Browse files
committed
*.go: Restructure backend files
1 parent 27e54bf commit 135ffd6

14 files changed

+161
-143
lines changed

Diff for: course_groups.go

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Course groups
3+
*
4+
* Copyright (C) 2024 Runxi Yu <https://runxiyu.org>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU Affero General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU Affero General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Affero General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
package main
22+
23+
import (
24+
"context"
25+
"fmt"
26+
)
27+
28+
type userCourseGroupsT map[courseGroupT]struct{}
29+
30+
type courseGroupT string
31+
32+
func checkCourseGroup(cg courseGroupT) bool {
33+
_, ok := courseGroups[cg]
34+
return ok
35+
}
36+
37+
const (
38+
mw1 courseGroupT = "MW1"
39+
mw2 courseGroupT = "MW2"
40+
mw3 courseGroupT = "MW3"
41+
tt1 courseGroupT = "TT1"
42+
tt2 courseGroupT = "TT2"
43+
tt3 courseGroupT = "TT3"
44+
)
45+
46+
var courseGroups = map[courseGroupT]string{
47+
mw1: "Monday/Wednesday CCA1",
48+
mw2: "Monday/Wednesday CCA2",
49+
mw3: "Monday/Wednesday CCA3",
50+
tt1: "Tuesday/Thursday CCA1",
51+
tt2: "Tuesday/Thursday CCA2",
52+
tt3: "Tuesday/Thursday CCA3",
53+
}
54+
55+
func populateUserCourseGroups(
56+
ctx context.Context,
57+
userCourseGroups *userCourseGroupsT,
58+
userID string,
59+
) error {
60+
rows, err := db.Query(
61+
ctx,
62+
"SELECT courseid FROM choices WHERE userid = $1",
63+
userID,
64+
)
65+
if err != nil {
66+
return fmt.Errorf(
67+
"%w: %w",
68+
errUnexpectedDBError,
69+
err,
70+
)
71+
}
72+
for {
73+
if !rows.Next() {
74+
err := rows.Err()
75+
if err != nil {
76+
return fmt.Errorf(
77+
"%w: %w",
78+
errUnexpectedDBError,
79+
err,
80+
)
81+
}
82+
break
83+
}
84+
var thisCourseID int
85+
err := rows.Scan(&thisCourseID)
86+
if err != nil {
87+
return fmt.Errorf(
88+
"%w: %w",
89+
errUnexpectedDBError,
90+
err,
91+
)
92+
}
93+
var thisGroupName courseGroupT
94+
_course, ok := courses.Load(thisCourseID)
95+
if !ok {
96+
return fmt.Errorf(
97+
"%w: %d",
98+
errNoSuchCourse,
99+
thisCourseID,
100+
)
101+
}
102+
course, ok := _course.(*courseT)
103+
if !ok {
104+
panic("courses map has non-\"*courseT\" items")
105+
}
106+
thisGroupName = course.Group
107+
if _, ok := (*userCourseGroups)[thisGroupName]; ok {
108+
return fmt.Errorf(
109+
"%w: user %v, group %v",
110+
errMultipleChoicesInOneGroup,
111+
userID,
112+
thisGroupName,
113+
)
114+
}
115+
(*userCourseGroups)[thisGroupName] = struct{}{}
116+
}
117+
return nil
118+
}

Diff for: wsx.go renamed to course_types.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Generic WebSocket auxiliary functions
2+
* Course types
33
*
44
* Copyright (C) 2024 Runxi Yu <https://runxiyu.org>
55
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -20,17 +20,19 @@
2020

2121
package main
2222

23-
import (
24-
"context"
25-
"fmt"
23+
type courseTypeT string
2624

27-
"github.com/coder/websocket"
25+
const (
26+
sport courseTypeT = "Sport"
27+
nonSport courseTypeT = "Non-sport"
2828
)
2929

30-
func writeText(ctx context.Context, c *websocket.Conn, msg string) error {
31-
err := c.Write(ctx, websocket.MessageText, []byte(msg))
32-
if err != nil {
33-
return fmt.Errorf("%w: %w", errWebSocketWrite, err)
34-
}
35-
return nil
30+
var courseTypes = map[courseTypeT]struct{}{
31+
sport: {},
32+
nonSport: {},
33+
}
34+
35+
func checkCourseType(ct courseTypeT) bool {
36+
_, ok := courseTypes[ct]
37+
return ok
3638
}

Diff for: courses.go

-110
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@ import (
2929
"github.com/coder/websocket"
3030
)
3131

32-
type (
33-
courseTypeT string
34-
courseGroupT string
35-
)
36-
3732
type courseT struct {
3833
/*
3934
* Selected is usually accessed atomically, but a lock is still
@@ -55,44 +50,6 @@ type courseT struct {
5550
Usems sync.Map /* string, *usemT */
5651
}
5752

58-
const (
59-
sport courseTypeT = "Sport"
60-
nonSport courseTypeT = "Non-sport"
61-
)
62-
63-
var courseTypes = map[courseTypeT]struct{}{
64-
sport: {},
65-
nonSport: {},
66-
}
67-
68-
const (
69-
mw1 courseGroupT = "MW1"
70-
mw2 courseGroupT = "MW2"
71-
mw3 courseGroupT = "MW3"
72-
tt1 courseGroupT = "TT1"
73-
tt2 courseGroupT = "TT2"
74-
tt3 courseGroupT = "TT3"
75-
)
76-
77-
var courseGroups = map[courseGroupT]string{
78-
mw1: "Monday/Wednesday CCA1",
79-
mw2: "Monday/Wednesday CCA2",
80-
mw3: "Monday/Wednesday CCA3",
81-
tt1: "Tuesday/Thursday CCA1",
82-
tt2: "Tuesday/Thursday CCA2",
83-
tt3: "Tuesday/Thursday CCA3",
84-
}
85-
86-
func checkCourseType(ct courseTypeT) bool {
87-
_, ok := courseTypes[ct]
88-
return ok
89-
}
90-
91-
func checkCourseGroup(cg courseGroupT) bool {
92-
_, ok := courseGroups[cg]
93-
return ok
94-
}
95-
9653
var courses sync.Map /* int, *courseT */
9754

9855
var numCourses uint32 /* atomic */
@@ -172,73 +129,6 @@ func setupCourses(ctx context.Context) error {
172129
return nil
173130
}
174131

175-
type userCourseGroupsT map[courseGroupT]struct{}
176-
177-
func populateUserCourseGroups(
178-
ctx context.Context,
179-
userCourseGroups *userCourseGroupsT,
180-
userID string,
181-
) error {
182-
rows, err := db.Query(
183-
ctx,
184-
"SELECT courseid FROM choices WHERE userid = $1",
185-
userID,
186-
)
187-
if err != nil {
188-
return fmt.Errorf(
189-
"%w: %w",
190-
errUnexpectedDBError,
191-
err,
192-
)
193-
}
194-
for {
195-
if !rows.Next() {
196-
err := rows.Err()
197-
if err != nil {
198-
return fmt.Errorf(
199-
"%w: %w",
200-
errUnexpectedDBError,
201-
err,
202-
)
203-
}
204-
break
205-
}
206-
var thisCourseID int
207-
err := rows.Scan(&thisCourseID)
208-
if err != nil {
209-
return fmt.Errorf(
210-
"%w: %w",
211-
errUnexpectedDBError,
212-
err,
213-
)
214-
}
215-
var thisGroupName courseGroupT
216-
_course, ok := courses.Load(thisCourseID)
217-
if !ok {
218-
return fmt.Errorf(
219-
"%w: %d",
220-
errNoSuchCourse,
221-
thisCourseID,
222-
)
223-
}
224-
course, ok := _course.(*courseT)
225-
if !ok {
226-
panic("courses map has non-\"*courseT\" items")
227-
}
228-
thisGroupName = course.Group
229-
if _, ok := (*userCourseGroups)[thisGroupName]; ok {
230-
return fmt.Errorf(
231-
"%w: user %v, group %v",
232-
errMultipleChoicesInOneGroup,
233-
userID,
234-
thisGroupName,
235-
)
236-
}
237-
(*userCourseGroups)[thisGroupName] = struct{}{}
238-
}
239-
return nil
240-
}
241-
242132
func (course *courseT) decrementSelectedAndPropagate(
243133
ctx context.Context,
244134
conn *websocket.Conn,

Diff for: db.go renamed to database.go

File renamed without changes.

Diff for: auth.go renamed to endpoint_auth.go

File renamed without changes.

Diff for: export.go renamed to endpoint_export.go

File renamed without changes.

Diff for: index.go renamed to endpoint_index.go

File renamed without changes.

Diff for: newcourses.go renamed to endpoint_newcourses.go

File renamed without changes.

Diff for: wsh.go renamed to endpoint_ws.go

File renamed without changes.

Diff for: err.go renamed to errors.go

File renamed without changes.

Diff for: utils.go renamed to misc_utils.go

File renamed without changes.

Diff for: usem.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Additional synchronization routines
2+
* Increase-unblocking capped semaphores
33
*
44
* Copyright (C) 2024 Runxi Yu <https://runxiyu.org>
55
* SPDX-License-Identifier: AGPL-3.0-or-later

Diff for: wsc.go renamed to ws_connection.go

-20
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"context"
2525
"errors"
2626
"fmt"
27-
"log"
2827
"sync"
2928
"sync/atomic"
3029
"time"
@@ -348,22 +347,3 @@ func handleConn(
348347
var cancelPool sync.Map /* string, *context.CancelFunc */
349348

350349
var chanPool sync.Map /* string, *chan string */
351-
352-
func propagate(msg string) {
353-
chanPool.Range(func(_userID, _ch interface{}) bool {
354-
ch, ok := _ch.(*chan string)
355-
if !ok {
356-
panic("chanPool has non-\"*chan string\" key")
357-
}
358-
select {
359-
case *ch <- msg:
360-
default:
361-
userID, ok := _userID.(string)
362-
if !ok {
363-
panic("chanPool has non-string key")
364-
}
365-
log.Println("WARNING: SendQ exceeded for " + userID)
366-
}
367-
return true
368-
})
369-
}

Diff for: wsp.go renamed to ws_utils.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* WebSocket-based protocol auxiliary functions
2+
* WebSocket auxiliary functions
33
*
44
* Copyright (C) 2024 Runxi Yu <https://runxiyu.org>
55
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -23,6 +23,7 @@ package main
2323
import (
2424
"context"
2525
"fmt"
26+
"log"
2627
"sync/atomic"
2728

2829
"github.com/coder/websocket"
@@ -141,3 +142,30 @@ func sendSelectedUpdate(
141142
}
142143
return nil
143144
}
145+
146+
func propagate(msg string) {
147+
chanPool.Range(func(_userID, _ch interface{}) bool {
148+
ch, ok := _ch.(*chan string)
149+
if !ok {
150+
panic("chanPool has non-\"*chan string\" key")
151+
}
152+
select {
153+
case *ch <- msg:
154+
default:
155+
userID, ok := _userID.(string)
156+
if !ok {
157+
panic("chanPool has non-string key")
158+
}
159+
log.Println("WARNING: SendQ exceeded for " + userID)
160+
}
161+
return true
162+
})
163+
}
164+
165+
func writeText(ctx context.Context, c *websocket.Conn, msg string) error {
166+
err := c.Write(ctx, websocket.MessageText, []byte(msg))
167+
if err != nil {
168+
return fmt.Errorf("%w: %w", errWebSocketWrite, err)
169+
}
170+
return nil
171+
}

0 commit comments

Comments
 (0)