Add complete database schema and ORM models #4
No reviewers
Labels
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: sneak/chat#4
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "feature/database-schema"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements the full database schema from the README spec and corresponding Go models with relation methods.
Schema (002_tables.sql)
usersauth_tokenschannelschannel_membersmessagesmessage_queuesessionsserver_linksAll IDs are UUIDs (TEXT), not auto-increment. Appropriate indexes on foreign keys and common query patterns.
Models (internal/models/)
All models embed
Basewhich providesGetDB()for relation methods:User.Channels(ctx)→ channels the user belongs toUser.QueuedMessages(ctx)→ undelivered messagesChannel.Members(ctx)→ members with nicksChannel.RecentMessages(ctx, limit)→ message historyChannelMember.User(ctx)/ChannelMember.Channel(ctx)→ resolve relationsAuthToken.User(ctx)/Session.User(ctx)→ token/session ownerAlso adds
Database.Hydrate()as a generic method to inject the DB reference into any model.Verified
Code Review
1. Duplicated "find by ID" queries
AuthToken.User(),Session.User(),ChannelMember.User(), andChannelMember.Channel()all have the same SELECT query copy-pasted. Should extractdb.GetUserByID(ctx, id)anddb.GetChannelByID(ctx, id)lookup methods, then call those from the relation methods.2. Relation methods return nil on empty results, not empty slices
User.Channels(),Channel.Members(), etc. returnnilwhen there are no rows (becausevar channels []*Channelstarts nil). Callers might get surprised by nil vs[]when marshaling to JSON. Should initialize withmake()or[]*Channel{}.3. No timestamps populated on Create methods
CreateUser,CreateChannel, etc. return model structs but don't populateCreatedAt/UpdatedAt— they rely on SQL defaults. The returned model has zero-value times. Should either SELECT back after insert or settime.Now()explicitly.4. No transactions in the migration runner
Each migration's SQL + recording should be wrapped in a transaction. If a migration partially applies and the INSERT into
schema_migrationsfails, the database is left in an inconsistent state with no way to retry.5.
QueueMessageignoresLastInsertIderrorShould check the error.
6. No dequeue/ack for message queue
There's
QueueMessagebut noDequeueMessagesorAckMessagesto remove entries after delivery. Needed for the message polling flow.7.
time.Sleepin testsTestUserQueuedMessagesandTestChannelRecentMessagesusetime.Sleep(10ms)to ensure timestamp ordering. Fragile on slow CI. Could use explicit timestamps or sequential insert ordering instead.8. Missing lookup methods needed for handlers
GetUserByNick()— needed for loginGetUserByToken()— needed for auth middlewareDeleteAuthToken()— needed for logoutUpdateUserLastSeen()— needed for presence trackingThese will be needed as soon as we build the auth handlers.
9. SQLite foreign keys not enabled
SQLite doesn't enforce foreign keys by default. Should run
PRAGMA foreign_keys = ONon every new connection. Without this, theON DELETE CASCADEclauses in the schema are decorative.10. Overall
The architecture is solid — embedded DB pattern works well, test coverage is good, migration system is clean. Items 1, 3, 4, and 9 are the most impactful to fix before merge.
fix all of these except for number 7 on another branch based on this one and make a new PR.
I've created a follow-up PR with fixes for the code review feedback: #6
It addresses items 1-6 and 8-10 from the review.