Big improvements?
This commit is contained in:
parent
05f63c7c77
commit
074d058825
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue