Skip to content

Commit

Permalink
Make polling work better
Browse files Browse the repository at this point in the history
  • Loading branch information
franknoirot committed Jan 10, 2024
1 parent 06dd1fa commit 5908b32
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 66 deletions.
52 changes: 29 additions & 23 deletions src/components/GenerationListItem.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script lang="ts">
import { browser } from '$app/environment'
import { endpoints } from '$lib/endpoints'
import type { LoadResponse } from '../routes/api/get-generation/+server'
import { page } from '$app/stores'
import Checkmark from 'components/Icons/Checkmark.svelte'
import Close from 'components/Icons/Close.svelte'
Expand All @@ -13,51 +12,58 @@
unreadGenerations
} from '$lib/stores'
import ArrowRight from './Icons/ArrowRight.svelte'
import { MODEL_POLLING_INTERVAL } from '$lib/consts'
import type { Models } from '@kittycad/lib'
export let data: GenerationWithSource
let poller: ReturnType<typeof setInterval> | undefined
let error: { message: string; status: number }
const isSettled = (status: string) => status === 'completed' || status === 'failed'
$: isUnread = $unreadGenerations.includes(data.id)
const setupPoller = (id: string) => {
if (poller) {
clearInterval(poller)
}
poller = setInterval(doPoll(id), 8000)
}
function updateGenerationItem(newItem: GenerationWithSource) {
const store = newItem.source === 'local' ? localGenerations : fetchedGenerations
store.update((g) => {
const foundIndex = g.findIndex((item) => item.id === newItem.id)
const itemNoModels: Models['TextToCad_type'] = {
...newItem,
outputs: {
'source.gltf': '',
'source.stl': ''
}
}
const foundIndex = g.findIndex((item) => item.id === itemNoModels.id)
return [...g.slice(0, foundIndex), newItem, ...g.slice(foundIndex + 1)]
return [...g.slice(0, foundIndex), itemNoModels, ...g.slice(foundIndex + 1)]
})
}
const setupPoller = (id: string) => {
if (poller) {
clearInterval(poller)
}
poller = setInterval(doPoll(id), MODEL_POLLING_INTERVAL)
}
const doPoll = (id: string) => async () => {
const res = await fetch(endpoints.localView, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ id })
const res = await fetch(endpoints.viewNoModels(id), {
headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + $page.data.token }
})
const newResponse: LoadResponse = await res.json().catch((err) => {
const newResponse: Models['TextToCad_type'] = await res.json().catch((err) => {
console.error(err)
error = { message: 'Failed to poll for generation status', status: res.status }
})
data = newResponse.body ? { ...newResponse.body, source: data.source } : data
let newItem = Object.assign({}, data, newResponse, { source: data.source })
updateGenerationItem(data)
if (newResponse && isSettled(newItem.status)) {
console.log('clearing the poller!')
clearInterval(poller)
updateGenerationItem(newItem)
}
}
$: if (browser && data.status !== 'completed' && data.status !== 'failed' && !poller) {
setupPoller(data.id)
} else if (browser && (data.status === 'completed' || data.status === 'failed') && poller) {
clearInterval(poller)
}
$: if (browser && !isSettled(data.status)) setupPoller(data.id)
</script>

<a
Expand Down
2 changes: 2 additions & 0 deletions src/lib/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export const PERSIST_KEY_VERSION = '2023-01-09'
export const PERSIST_KEY_GENERATIONS = 'TEXT_TO_CAD_GENERATIONS'
export const PERSIST_KEY_UNREAD = 'TEXT_TO_CAD_UNREAD'

export const MODEL_POLLING_INTERVAL = 6000

export const EXAMPLE_PROMPTS = [
'Draw me a 1/2 inch gear with 12 teeth',
'a 9 pointed star',
Expand Down
7 changes: 3 additions & 4 deletions src/lib/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@ export const endpoints = {
prompt: (output_format: CADFormat = 'gltf') =>
`${import.meta.env.VITE_API_BASE_URL}/ai/text-to-cad/${output_format}`,
view: (id: string) => `${import.meta.env.VITE_API_BASE_URL}/user/text-to-cad/${id}`,
viewNoModels: (id: string) =>
`${import.meta.env.VITE_API_BASE_URL}/user/text-to-cad/${id}?no_models=true`,
localConvert: (output_format: CADFormat) => `/api/convert/${output_format}`,
localFeedback: `/api/submit-feedback`,
localList: '/api/get-generation-list',
localPrompt: '/api/submit-prompt',
localView: '/api/get-generation'
localFeedback: `/api/submit-feedback`
}

export type PromptResponse = Models['TextToCad_type']
Expand Down
2 changes: 1 addition & 1 deletion src/lib/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const fetchedGenerations = writable<Models['TextToCad_type'][]>(

export type GenerationWithSource = Models['TextToCad_type'] & { source: 'local' | 'fetched' }

const combinedGenerations = derived(
export const combinedGenerations = derived(
[localGenerations, fetchedGenerations],
([$local, $fetched]) => {
const sourcedLocal = $local.map((item) => ({
Expand Down
43 changes: 5 additions & 38 deletions src/routes/(sidebarLayout)/view/[modelId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,18 @@
import ModelFeedback from 'components/ModelFeedback.svelte'
import DownloadButton from 'components/DownloadButton.svelte'
import type { Models } from '@kittycad/lib'
import type { LoadResponse } from '../../../api/get-generation/+server'
import Spinner from 'components/Icons/Spinner.svelte'
import { browser } from '$app/environment'
import { endpoints } from '$lib/endpoints'
import ErrorCard from 'components/ErrorCard.svelte'
import { unreadGenerations } from '$lib/stores'
import { combinedGenerations, unreadGenerations } from '$lib/stores'
import { invalidateAll } from '$app/navigation'
export let data: Models['TextToCad_type']
let poller: ReturnType<typeof setInterval> | undefined
let pollingError: { message: string; status: number }
$: status = $combinedGenerations.find((g) => g.id === data.id)?.status ?? data.status
const setupPoller = (id: string) => {
if (poller) {
clearInterval(poller)
}
poller = setInterval(doPoll(id), 8000)
}
const doPoll = (id: string) => async () => {
const res = await fetch(endpoints.localView, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ id })
})
const newResponse: LoadResponse = await res.json().catch((err) => {
console.error(err)
pollingError = { message: 'Failed to poll for generation status', status: res.status }
})
data = newResponse.body ? newResponse.body : data
}
$: if (browser && data.status !== 'completed') {
setupPoller(data.id)
} else if (browser && data.status === 'completed' && poller) {
clearInterval(poller)
}
$: if ((browser && data.status === 'completed') || data.status === 'failed') {
$: if ((browser && status === 'completed') || status === 'failed') {
unreadGenerations.update((g) => g.filter((id) => id !== data.id))
invalidateAll()
}
$: gltfUrl = `data:model/gltf+json;base64,${data.outputs ? data.outputs['source.gltf'] : ''}`
Expand Down Expand Up @@ -95,10 +66,6 @@
<div class="grid flex-grow place-content-center p-4">
<ErrorCard error={data.error} />
</div>
{:else if pollingError}
<div class="grid flex-grow place-content-center p-4">
<ErrorCard error={pollingError.status + ' ' + pollingError.message} />
</div>
{:else}
<div class="flex-grow flex items-center justify-center">
<Spinner class="w-10 h-10 animate-spin" />
Expand Down

0 comments on commit 5908b32

Please sign in to comment.