Skip to content

Commit

Permalink
Merge pull request #7 from COSI-Lab/appendonly
Browse files Browse the repository at this point in the history
Replace sqlite database with append only file
  • Loading branch information
Alextopher authored Jul 18, 2023
2 parents dd67bec + 483fbaf commit b408d38
Show file tree
Hide file tree
Showing 16 changed files with 841 additions and 242 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.DS_Store
.env
go-talks
talks.db
main
gin-bin
backups
config.toml
config.toml
*.db*
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ go-talks (Or more commonly known as just Talks) is an app to manage talks at COS
- /posts directory supports rendering pre-written markdown files
- Image caching/proxying
- Create future talks and view historic talks
- Backed by SQLITE database
- Backed by an append only log database

## Endpoints

Expand All @@ -27,3 +27,4 @@ go-talks (Or more commonly known as just Talks) is an app to manage talks at COS
| GET | /img/{id} | Image proxy |
| GET | /health | Indicates how many active connections there are |
| GET | /ws | Websocket endpoint |

37 changes: 0 additions & 37 deletions backup.go

This file was deleted.

103 changes: 84 additions & 19 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,58 @@ const (
DELETE
// AUTH communicates authentication request/response
AUTH
// SYNC requests a sync of the talks
SYNC
)

// Message is the format of messages sent between the client and server
// Since go doesn't have the strongest type system we pack every message
// into a single struct
type Message struct {
Type MessageType `json:"type"`
ID uint32 `json:"id,omitempty"`
Password string `json:"password,omitempty"`
Name string `json:"name,omitempty"`
Talktype *TalkType `json:"talktype,omitempty"`
Description string `json:"description,omitempty"`
Week string `json:"week,omitempty"`
Type MessageType `json:"type"`
New *NewMessage `json:"new,omitempty"`
Hide *HideMessage `json:"hide,omitempty"`
Del *DeleteMessage `json:"delete,omitempty"`
Auth *AuthMessage `json:"auth,omitempty"`
Sync *SyncMessage `json:"sync,omitempty"`
}

// NewMessage gives the client all the information needed to add a new talk to
// the page
type NewMessage struct {
ID uint32 `json:"id"`
Name string `json:"name"`
Talktype TalkType `json:"talktype"`
Description string `json:"description"`
Week string `json:"week"`
}

// HideMessage gives the client the ID of the talk to hide
type HideMessage struct {
ID uint32 `json:"id"`
}

// DeleteMessage gives the client the ID of the talk to delete
type DeleteMessage struct {
ID uint32 `json:"id"`
}

// AuthMessage gives the client the password to authenticate
type AuthMessage struct {
Password string `json:"password"`
}

// SyncMessage starts and caps off a sync
type SyncMessage struct {
Week string `json:"week"`
}

func authenticatedMessage(b bool) []byte {
if b {
return []byte("{\"type\": 3, \"status\": true}")
return []byte("{\"type\": 3, \"auth\": {\"status\": true}}")
}

return []byte("{\"type\": 3, \"status\": false}")
return []byte("{\"type\": 3, \"auth\": {\"status\": false}}")
}

func (c *Client) read() {
Expand All @@ -73,21 +104,54 @@ func (c *Client) read() {
var message Message
err = json.Unmarshal(raw, &message)
if err != nil {
// Print the message and continue
log.Printf("[WARN] %v", err)
continue
}

// Handle authentication without consulting the hub
if message.Type == AUTH {
switch message.Type {
case NEW, HIDE, DELETE:
// NEW, HIDE, and DELETE need to be serialized through the hub
hub.broadcast <- message
case AUTH:
// AUTH is handled without having to contact the hub
log.Printf("[INFO] Client %v is trying to authenticate", c.conn.RemoteAddr())

c.auth = message.Password == config.Password
c.send <- authenticatedMessage(c.auth)

continue
c.send <- authenticatedMessage(message.Auth.Password == config.Password)
case SYNC:
// SYNC messages don't need to be serialized, go straight to the db
log.Printf("[INFO] Client %v is requesting a sync", c.conn.RemoteAddr())
for _, talk := range talks.AllTalks(message.Sync.Week) {
var msg Message
if talk.Hidden {
// Send a hide message
msg = Message{
Type: HIDE,
Hide: &HideMessage{
ID: talk.ID,
},
}
} else {
// Send a create message
msg = Message{
Type: NEW,
New: &NewMessage{
ID: talk.ID,
Name: talk.Name,
Talktype: talk.Type,
Description: talk.Description,
Week: talk.Week,
},
}
}
// Send the message
raw, _ := json.Marshal(msg)
c.send <- raw
}
raw, _ := json.Marshal(message)
c.send <- raw
default:
log.Printf("[WARN] Client %v sent an invalid message type", c.conn.RemoteAddr())
}

// Forward all other message to be processed and broadcasted to other client
hub.broadcast <- message
}
}

Expand All @@ -103,6 +167,7 @@ func (c *Client) write() {
select {
case message, ok := <-c.send:
if !ok {
log.Println("[INFO] Closing connection")
return
}

Expand Down
Loading

0 comments on commit b408d38

Please sign in to comment.