Big improvements?

This commit is contained in:
Daniel Flanagan 2024-01-21 09:25:17 -06:00
parent 05f63c7c77
commit 074d058825
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
4 changed files with 49 additions and 47 deletions

View file

@ -127,22 +127,42 @@ function UserSelectButton(
} }
export default function Dashboard( export default function Dashboard(
{ todos, users, unassignedTodos, lastTodoIdUpdated, lastUserIdUpdated }: props: Props,
Props,
) { ) {
console.log('lasttodo:', lastTodoIdUpdated)
console.log('lastuser:', lastUserIdUpdated)
const todoAssignUserId: Signal<string | null> = useSignal(null) const todoAssignUserId: Signal<string | null> = useSignal(null)
const showAddTodoDialog = useSignal(false) const showAddTodoDialog = useSignal(false)
const data = useSignal(props)
const {
// todos,
users,
unassignedTodos,
// lastTodoIdUpdated,
// lastUserIdUpdated,
} = data.value
const reload = async () => {
console.log('reloading...')
const newData = await (await fetch(location.href, {
headers: { accept: 'application/json' },
})).json()
data.value = newData
console.log('new data:', newData)
}
useEffect(() => { useEffect(() => {
let es = new EventSource('/api/user') let es = new EventSource('/api/user')
es.addEventListener('message', (e) => { es.addEventListener('message', async (e) => {
console.log('user event from server:', e) console.log('user event stream message:', e)
await reload()
excitement()
}) })
es.addEventListener('error', async () => { es.addEventListener('error', async (e) => {
// try and reconnect
console.log('Streaming user events error:', e)
es.close() es.close()
const backoff = 10000 + Math.random() * 5000 const backoff = 10000 + Math.random() * 5000
await new Promise((resolve) => setTimeout(resolve, backoff)) await new Promise((resolve) => setTimeout(resolve, backoff))
@ -150,47 +170,17 @@ export default function Dashboard(
}) })
}, []) }, [])
useEffect(excitement)
useEffect(() => { useEffect(() => {
let es = new EventSource('/api/todo') let es = new EventSource('/api/todo')
console.log('Streaming todo events...') console.log('Streaming todo events...')
es.addEventListener('message', (e) => { es.addEventListener('message', (e) => {
console.log('todo event from server:', e) console.log('todo event from server:', e)
const payload = JSON.parse(e.data) reload().then(excitement)
const { id: id } = payload
if (
payload.versionstamp === lastTodoIdUpdated.versionstamp &&
payload.id === lastTodoIdUpdated.value
) {
console.log('skipping...')
// skip, we hydrated with it
return
}
if (!payload.value) {
// deleted, so reload
location.reload()
} else {
const { description, doneAt, assigneeUserId, emoji } = payload.value
const t = todos[id]
if (
!t ||
id != t.id ||
description != t.description ||
doneAt != t.doneAt ||
assigneeUserId != t.assigneeUserId ||
emoji != t.emoji
) {
console.log('Should reload!')
location.reload()
}
}
}) })
es.addEventListener('error', async (e) => { es.addEventListener('error', async (e) => {
// try and reconnect
console.log('Streaming todo events error:', e) console.log('Streaming todo events error:', e)
es.close() es.close()
const backoff = 10000 + Math.random() * 5000 const backoff = 10000 + Math.random() * 5000

View file

@ -80,6 +80,8 @@ export const handler: Handlers<Todo | null> = {
// TODO: json or query params // TODO: json or query params
const accept = req.headers.get('accept') const accept = req.headers.get('accept')
if (accept === 'text/event-stream') { if (accept === 'text/event-stream') {
console.log('Request for todo event stream')
let skipFirst = true
const stream = kv.watch([['last_todo_updated']]).getReader() const stream = kv.watch([['last_todo_updated']]).getReader()
const body = new ReadableStream({ const body = new ReadableStream({
async start(controller) { async start(controller) {
@ -89,12 +91,12 @@ export const handler: Handlers<Todo | null> = {
while (true) { while (true) {
try { try {
const entries = await stream.read() const entries = await stream.read()
console.log('streaming todo entries:', entries)
for (const entry of entries.value || []) { for (const entry of entries.value || []) {
console.log('streaming todo entry:', entry) if (skipFirst) {
skipFirst = false
continue
}
if (typeof entry.value !== 'string') { if (typeof entry.value !== 'string') {
console.error('Invalid last_todo_updated entry:', entry)
continue continue
} }
@ -108,6 +110,7 @@ export const handler: Handlers<Todo | null> = {
value: todo, value: todo,
}) })
}\n\n` }\n\n`
console.log('todo event chunk:', chunk)
controller.enqueue(new TextEncoder().encode(chunk)) controller.enqueue(new TextEncoder().encode(chunk))
} }
if (entries.done) { if (entries.done) {

View file

@ -100,7 +100,6 @@ export const handler: Handlers<User | null> = {
} }
if (typeof entry.value !== 'string') { if (typeof entry.value !== 'string') {
console.error('Invalid last_user_updated:', entry.value)
continue continue
} }

View file

@ -11,7 +11,13 @@ interface Data {
} }
export const handler: Handlers = { export const handler: Handlers = {
async GET(_req, ctx) { async GET(req, ctx) {
const accept = req.headers.get('accept')
if (accept === 'text/event-stream') {
console.log('requested index event stream -- not implemented')
return new Response(JSON.stringify({ message: 'not implemented' }))
}
const users = Object.fromEntries( const users = Object.fromEntries(
(await db.users.findMany({ include: { assignedTodos: true } })).map( (await db.users.findMany({ include: { assignedTodos: true } })).map(
(u) => [u.id, u], (u) => [u.id, u],
@ -29,13 +35,17 @@ export const handler: Handlers = {
'last_user_updated', 'last_user_updated',
], ['last_todo_updated']], { consistency: 'eventual' }) ], ['last_todo_updated']], { consistency: 'eventual' })
console.log({ lastTodoIdUpdated, lastUserIdUpdated }) console.log({ lastTodoIdUpdated, lastUserIdUpdated })
return ctx.render({ const props = {
users, users,
todos, todos,
unassignedTodos, unassignedTodos,
lastUserIdUpdated, lastUserIdUpdated,
lastTodoIdUpdated, lastTodoIdUpdated,
}) }
if (accept === 'application/json') {
return new Response(JSON.stringify(props))
}
return ctx.render(props)
}, },
} }