Skip to content

Commit

Permalink
don't broadcast state immediately onClose
Browse files Browse the repository at this point in the history
  • Loading branch information
threepointone committed Aug 9, 2024
1 parent 722b554 commit b0253d4
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
48 changes: 33 additions & 15 deletions app/durableObjects/ChatRoom.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ export class ChatRoom extends Server<Env> {
)
)

if (!this.ctx.storage.getAlarm()) {
if (!(await this.ctx.storage.getAlarm())) {
// start the alarm to broadcast state every 30 seconds
this.ctx.storage.setAlarm(30000)
this.ctx.storage.setAlarm(Date.now() + 30000)
}

// cleaning out storage used by older versions of this code
Expand Down Expand Up @@ -74,16 +74,29 @@ export class ChatRoom extends Server<Env> {
}

broadcastState() {
this.broadcast(
JSON.stringify({
type: 'roomState',
state: {
users: [...this.getConnections<User>()]
.map((connection) => connection.state)
.filter((x) => !!x),
},
} satisfies ServerMessage)
)
let didSomeoneQuit = false
const roomStateMessage = {
type: 'roomState',
state: {
users: [...this.getConnections<User>()]
.map((connection) => connection.state)
.filter((x) => !!x),
},
} satisfies ServerMessage

for (const connection of this.getConnections<User>()) {
try {
connection.send(JSON.stringify(roomStateMessage))
} catch (err) {
connection.close(1011, 'Failed to broadcast state')
didSomeoneQuit = true
}
}

if (didSomeoneQuit) {
// broadcast again to remove the user who quit
this.broadcastState()
}
}

async onMessage(
Expand All @@ -100,7 +113,8 @@ export class ChatRoom extends Server<Env> {

switch (data.type) {
case 'userLeft':
// TODO: ??
connection.close(1000, 'User left')
this.broadcastState()
break
case 'userUpdate':
connection.setState(data.user)
Expand Down Expand Up @@ -176,7 +190,11 @@ export class ChatRoom extends Server<Env> {
}

onClose() {
this.broadcastState()
// while it makes sense to broadcast immediately on close,
// it's possible that the websocket just closed for an instant
// and will reconnect momentarily.
// so let's just let the alarm handler do the broadcasting.
// this.broadcastState()
}

onError(): void | Promise<void> {
Expand All @@ -187,6 +205,6 @@ export class ChatRoom extends Server<Env> {
// technically we don't need to broadcast state on an alarm,
// but let's keep it for a while and see if it's useful
this.broadcastState()
this.ctx.storage.setAlarm(30000)
this.ctx.storage.setAlarm(Date.now() + 30000)
}
}
14 changes: 13 additions & 1 deletion app/hooks/useRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,25 @@ export default function useRoom({
},
})

useEffect(() => {
function onBeforeUnload() {
websocket.send(
JSON.stringify({ type: 'userLeft' } satisfies ClientMessage)
)
}
window.addEventListener('beforeunload', onBeforeUnload)
return () => {
window.removeEventListener('beforeunload', onBeforeUnload)
}
}, [websocket])

// setup a simple ping pong
useEffect(() => {
const interval = setInterval(() => {
websocket.send(
JSON.stringify({ type: 'partyserver-ping' } satisfies ClientMessage)
)
}, 10000)
}, 5000)

return () => clearInterval(interval)
}, [websocket])
Expand Down

0 comments on commit b0253d4

Please sign in to comment.