Skip to content

Commit

Permalink
Merge pull request #243 from Zekiah-A/main
Browse files Browse the repository at this point in the history
Type safety and db param bug fixes, toQueryObject
  • Loading branch information
Zekiah-A authored Feb 25, 2024
2 parents 6f0841d + dc30349 commit 8d3ea8c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 13 deletions.
40 changes: 28 additions & 12 deletions db-worker.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable jsdoc/require-param */
/* eslint-disable jsdoc/require-returns */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-inner-declarations */
import { parentPort } from 'worker_threads'
Expand Down Expand Up @@ -81,8 +83,8 @@ export type AuthenticateUser = { token: string, ip: string }
export type DbInternals = {
setUserChatName: (data: { newName: string, intId: number }) => void,
getUserChatName: (intId: number) => string|null,
authenticateUser: (data: AuthenticateUser) => void,
getLiveChatHistory: (data: { messageId: number, count: number, before: number, channel?: string, includeDeleted?: boolean }) => LiveChatMessage[],
authenticateUser: (data: AuthenticateUser) => number|null,
getLiveChatHistory: (data: { messageId: number, count: number, before: number, channel: string, includeDeleted?: boolean }) => LiveChatMessage[],
updatePixelPlace: (intId: number) => void,
getMaxLiveChatId: () => number,
getMaxPlaceChatId: () => number,
Expand Down Expand Up @@ -202,14 +204,25 @@ const createLiveChatDeletions = `
`
db.exec(createLiveChatDeletions)

/**
* Adds % to object keys in order to make it act as a valid bun SQLite query object
*/
function toQueryObject<T extends object>(object: T): T {
// @ts-expect-error Chicanery to keep type inference whilst transforming
const queryObject:T = {}
for (const k of Object.keys(object)) {
queryObject["$" + k] = queryObject[k]
}
return queryObject
}

const insertLiveChat = db.prepare<void, LiveChatMessage>(`
const insertLiveChat = db.query<void, LiveChatMessage>(`
INSERT INTO LiveChatMessages (messageId, message, sendDate, channel, senderIntId, repliesTo, deletionId)
VALUES ($messageId, $message, $sendDate, $channel, $senderIntId, $repliesTo, $deletionId)`)
const insertPlaceChat = db.prepare<void, PlaceChatMessage>(`
const insertPlaceChat = db.query<void, PlaceChatMessage>(`
INSERT INTO PlaceChatMessages (messageId, message, sendDate, senderIntId, x, y)
VALUES ($messageId, $message, $sendDate, $senderIntId, $x, $y)`)
const updatePixelPlaces = db.prepare<void, [number, number]>(`
const updatePixelPlaces = db.query<void, [number, number]>(`
UPDATE Users SET pixelsPlaced = pixelsPlaced + ?1 WHERE intId = ?2`)

interface PublicQueue<T> extends Queue<T> {
Expand All @@ -235,11 +248,11 @@ function performBulkInsertions() {
db.transaction(() => {
while (!liveChatInserts.isEmpty()) {
const data = liveChatInserts.dequeue()
insertLiveChat.run(data)
insertLiveChat.run(toQueryObject(data))
}
while (!placeChatInserts.isEmpty()) {
const data = placeChatInserts.dequeue()
insertPlaceChat.run(data)
insertPlaceChat.run(toQueryObject(data))
}
})()
}
Expand All @@ -264,11 +277,13 @@ const internal: DbInternals = {
const insertUser = db.query<User, [string, number, number, number]>(
"INSERT INTO Users (token, lastJoined, pixelsPlaced, playTimeSeconds) VALUES (?1, ?2, ?3, ?4) RETURNING *")
user = insertUser.get(data.token, epochMs, 0, 0)
if (user == null) return null
}
else { // Update last joined
const updateUser = db.query("UPDATE Users SET lastJoined = ?1 WHERE intId = ?2")
updateUser.run(epochMs, user.intId)
}

// Add known IP if not already there
const getIpsQuery = db.query<KnownIp, [number, string]>("SELECT * FROM KnownIps WHERE userIntId = ?1 AND ip = ?2")
const ipExists = getIpsQuery.get(user.intId, data.ip)
Expand All @@ -285,7 +300,7 @@ const internal: DbInternals = {
},
getLiveChatHistory: function(data) {
const liveChatMessageId = internal.getMaxLiveChatId()
let params = []
let params:any[] = []
let query = `
SELECT LiveChatMessages.*, Users.chatName AS chatName
FROM LiveChatMessages
Expand Down Expand Up @@ -334,12 +349,12 @@ const internal: DbInternals = {
},
getMaxLiveChatId: function() {
const getMaxMessageId = db.query<{ maxMessageId: number }, any>("SELECT MAX(messageId) AS maxMessageId FROM LiveChatMessages")
const maxMessageId = getMaxMessageId.get().maxMessageId || 0
const maxMessageId = getMaxMessageId.get()?.maxMessageId || 0
return maxMessageId
},
getMaxPlaceChatId: function() {
const getMaxMessageId = db.query<{ maxMessageId: number }, any>("SELECT MAX(messageId) AS maxMessageId FROM PlaceChatMessages")
const maxMessageId = getMaxMessageId.get().maxMessageId || 0
const maxMessageId = getMaxMessageId.get()?.maxMessageId || 0
return maxMessageId
},
commitShutdown: function() {
Expand All @@ -356,7 +371,8 @@ const internal: DbInternals = {
deleteLiveChat: function(data) {
const deletionQuery = db.query<LiveChatDeletion, DeletionMessageInfo>(
"INSERT INTO LiveChatDeletions (moderatorIntId, reason, deletionDate) VALUES ($moderatorIntId, $reason, $messageId) RETURNING *")
const deletion = deletionQuery.get(data)
const deletion = deletionQuery.get(toQueryObject(data))
if (deletion == null) return

// If pending to be inserted into DB we can update the record in preflight
for (const messageData of liveChatInserts._elements) {
Expand All @@ -367,7 +383,7 @@ const internal: DbInternals = {
}

const query = db.query<void, LiveChatDeletion>("UPDATE LiveChatMessages SET deletionId = $deletionId WHERE messageId = $messageId")
query.run(deletion)
query.run(toQueryObject(deletion))
},
insertPlaceChat: function(data) {
placeChatInserts.push(data)
Expand Down
6 changes: 5 additions & 1 deletion server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,11 @@ const bunServer = Bun.serve<ClientData>({
}

// This section is the only potentially hot DB-related code in the server, investigate optimisatiions
const pIntId = await makeDbRequest("authenticateUser", { token: ws.data.token, ip: IP }) as number
const pIntId = await makeDbRequest("authenticateUser", { token: ws.data.token, ip: IP })
if (pIntId == null || typeof pIntId != "number") {
console.error(`Could not authenticate user ${IP}, user ID was null, even after new creation`)
return ws.close()
}
ws.data.intId = pIntId
playerIntIds.set(ws, pIntId)
const pIdBuf = Buffer.alloc(5)
Expand Down

0 comments on commit 8d3ea8c

Please sign in to comment.