Skip to content

Commit 70fdb6e

Browse files
committed
feat(app): configure TanStack Query client with default options
Add defaultOptions to QueryClient to disable automatic refetching: - refetchOnReconnect: false - refetchOnMount: false - refetchOnWindowFocus: false
1 parent a45d9a9 commit 70fdb6e

6 files changed

Lines changed: 218 additions & 216 deletions

File tree

packages/app/src/app.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,15 @@ declare global {
8282
}
8383

8484
function QueryProvider(props: ParentProps) {
85-
const client = new QueryClient()
85+
const client = new QueryClient({
86+
defaultOptions: {
87+
queries: {
88+
refetchOnReconnect: false,
89+
refetchOnMount: false,
90+
refetchOnWindowFocus: false,
91+
},
92+
},
93+
})
8694
return <QueryClientProvider client={client}>{props.children}</QueryClientProvider>
8795
}
8896

packages/app/src/components/dialog-select-mcp.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export const DialogSelectMcp: Component = () => {
4747
.status()
4848
.then((result) => {
4949
sync.set("mcp", result.data ?? {})
50-
sync.set("mcp_ready", true)
50+
// sync.set("mcp_ready", true)
5151
setState("done", true)
5252
})
5353
.catch((err) => {

packages/app/src/components/status-popover-body.tsx

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,6 @@ export function StatusPopoverBody(props: { shown: Accessor<boolean> }) {
162162
const dialog = useDialog()
163163
const language = useLanguage()
164164
const navigate = useNavigate()
165-
const sdk = useSDK()
166-
167-
const [load, setLoad] = createStore({
168-
lspDone: false,
169-
lspLoading: false,
170-
mcpDone: false,
171-
mcpLoading: false,
172-
})
173165

174166
const fail = (err: unknown) => {
175167
showToast({
@@ -181,40 +173,6 @@ export function StatusPopoverBody(props: { shown: Accessor<boolean> }) {
181173

182174
createEffect(() => {
183175
if (!props.shown()) return
184-
185-
if (!sync.data.mcp_ready && !load.mcpDone && !load.mcpLoading) {
186-
setLoad("mcpLoading", true)
187-
void sdk.client.mcp
188-
.status()
189-
.then((result) => {
190-
sync.set("mcp", result.data ?? {})
191-
sync.set("mcp_ready", true)
192-
})
193-
.catch((err) => {
194-
setLoad("mcpDone", true)
195-
fail(err)
196-
})
197-
.finally(() => {
198-
setLoad("mcpLoading", false)
199-
})
200-
}
201-
202-
if (!sync.data.lsp_ready && !load.lspDone && !load.lspLoading) {
203-
setLoad("lspLoading", true)
204-
void sdk.client.lsp
205-
.status()
206-
.then((result) => {
207-
sync.set("lsp", result.data ?? [])
208-
sync.set("lsp_ready", true)
209-
})
210-
.catch((err) => {
211-
setLoad("lspDone", true)
212-
fail(err)
213-
})
214-
.finally(() => {
215-
setLoad("lspLoading", false)
216-
})
217-
}
218176
})
219177

220178
let dialogRun = 0

packages/app/src/context/global-sync.tsx

Lines changed: 83 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,25 @@ import { useLanguage } from "@/context/language"
1515
import { Persist, persisted } from "@/utils/persist"
1616
import type { InitError } from "../pages/error"
1717
import { useGlobalSDK } from "./global-sdk"
18-
import { bootstrapDirectory, bootstrapGlobal, clearProviderRev } from "./global-sync/bootstrap"
18+
import {
19+
bootstrapDirectory,
20+
bootstrapGlobal,
21+
clearProviderRev,
22+
loadGlobalConfigQuery,
23+
loadPathQuery,
24+
loadProjectsQuery,
25+
loadProvidersQuery,
26+
} from "./global-sync/bootstrap"
1927
import { createChildStoreManager } from "./global-sync/child-store"
2028
import { applyDirectoryEvent, applyGlobalEvent, cleanupDroppedSessionCaches } from "./global-sync/event-reducer"
21-
import { createRefreshQueue } from "./global-sync/queue"
2229
import { clearSessionPrefetchDirectory } from "./global-sync/session-prefetch"
2330
import { estimateRootSessionTotal, loadRootSessionsWithFallback } from "./global-sync/session-load"
2431
import { trimSessions } from "./global-sync/session-trim"
2532
import type { ProjectMeta } from "./global-sync/types"
2633
import { SESSION_RECENT_LIMIT } from "./global-sync/types"
2734
import { sanitizeProject } from "./global-sync/utils"
2835
import { formatServerError } from "@/utils/server-errors"
29-
import { queryOptions, skipToken, useQueryClient } from "@tanstack/solid-query"
36+
import { queryOptions, skipToken, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/solid-query"
3037

3138
type GlobalStore = {
3239
ready: boolean
@@ -45,6 +52,18 @@ type GlobalStore = {
4552
export const loadSessionsQuery = (directory: string) =>
4653
queryOptions<null>({ queryKey: [directory, "loadSessions"], queryFn: skipToken })
4754

55+
export const loadMcpQuery = (directory: string, sdk?: OpencodeClient) =>
56+
queryOptions({
57+
queryKey: [directory, "mcp"],
58+
queryFn: sdk ? () => sdk.mcp.status().then((r) => r.data ?? {}) : skipToken,
59+
})
60+
61+
export const loadLspQuery = (directory: string, sdk?: OpencodeClient) =>
62+
queryOptions({
63+
queryKey: [directory, "lsp"],
64+
queryFn: sdk ? () => sdk.lsp.status().then((r) => r.data ?? {}) : skipToken,
65+
})
66+
4867
function createGlobalSync() {
4968
const globalSDK = useGlobalSDK()
5069
const language = useLanguage()
@@ -61,15 +80,34 @@ function createGlobalSync() {
6180
createStore({ value: [] as Project[] }),
6281
)
6382

83+
const [configQuery, providerQuery, pathQuery] = useQueries(() => ({
84+
queries: [loadGlobalConfigQuery(), loadProvidersQuery(null), loadPathQuery(null), loadProjectsQuery()],
85+
}))
86+
6487
const [globalStore, setGlobalStore] = createStore<GlobalStore>({
65-
ready: false,
66-
path: { state: "", config: "", worktree: "", directory: "", home: "" },
88+
get ready() {
89+
return bootstrap.isPending
90+
},
6791
project: projectCache.value,
6892
session_todo: {},
69-
provider: { all: [], connected: [], default: {} },
7093
provider_auth: {},
71-
config: {},
72-
reload: undefined,
94+
get path() {
95+
const EMPTY = { state: "", config: "", worktree: "", directory: "", home: "" }
96+
if (pathQuery.isLoading) return EMPTY
97+
return pathQuery.data ?? EMPTY
98+
},
99+
get provider() {
100+
const EMPTY = { all: [], connected: [], default: {} }
101+
if (providerQuery.isLoading) return EMPTY
102+
return providerQuery.data ?? EMPTY
103+
},
104+
get config() {
105+
if (configQuery.isLoading) return {}
106+
return configQuery.data ?? {}
107+
},
108+
get reload() {
109+
return updateConfigMutation.isPending ? "pending" : undefined
110+
},
73111
})
74112
const queryClient = useQueryClient()
75113

@@ -109,6 +147,22 @@ function createGlobalSync() {
109147
return (setGlobalStore as (...args: unknown[]) => unknown)(...input)
110148
}) as typeof setGlobalStore
111149

150+
const bootstrap = useQuery(() => ({
151+
queryKey: ["bootstrap"],
152+
queryFn: async () => {
153+
await bootstrapGlobal({
154+
globalSDK: globalSDK.client,
155+
requestFailedTitle: language.t("common.requestFailed"),
156+
translate: language.t,
157+
formatMoreCount: (count) => language.t("common.moreCountSuffix", { count }),
158+
setGlobalStore: setBootStore,
159+
queryClient,
160+
})
161+
bootedAt = Date.now()
162+
return bootedAt
163+
},
164+
}))
165+
112166
const set = ((...input: unknown[]) => {
113167
if (input[0] === "project" && (Array.isArray(input[1]) || typeof input[1] === "function")) {
114168
setProjects(input[1] as Project[] | ((draft: Project[]) => Project[]))
@@ -143,11 +197,11 @@ function createGlobalSync() {
143197

144198
const paused = () => untrack(() => globalStore.reload) !== undefined
145199

146-
const queue = createRefreshQueue({
147-
paused,
148-
bootstrap,
149-
bootstrapInstance,
150-
})
200+
// const queue = createRefreshQueue({
201+
// paused,
202+
// bootstrap: () => queryClient.fetchQuery({ queryKey: ["bootstrap"] }),
203+
// bootstrapInstance,
204+
// })
151205

152206
const children = createChildStoreManager({
153207
owner,
@@ -157,7 +211,7 @@ function createGlobalSync() {
157211
void bootstrapInstance(directory)
158212
},
159213
onDispose: (directory) => {
160-
queue.clear(directory)
214+
// queue.clear(directory)
161215
sessionMeta.delete(directory)
162216
sdkCache.delete(directory)
163217
clearProviderRev(directory)
@@ -301,14 +355,14 @@ function createGlobalSync() {
301355
project: globalStore.project,
302356
refresh: () => {
303357
if (recent) return
304-
queue.refresh()
358+
bootstrap.refetch()
305359
},
306360
setGlobalProject: setProjects,
307361
})
308362
if (event.type === "server.connected" || event.type === "global.disposed") {
309363
if (recent) return
310364
for (const directory of Object.keys(children.children)) {
311-
queue.push(directory)
365+
// queue.push(directory)
312366
}
313367
}
314368
return
@@ -323,47 +377,27 @@ function createGlobalSync() {
323377
directory,
324378
store,
325379
setStore,
326-
push: queue.push,
380+
push: () => {}, // queue.push,
327381
setSessionTodo,
328382
vcsCache: children.vcsCache.get(directory),
329383
loadLsp: () => {
330-
void sdkFor(directory)
331-
.lsp.status()
332-
.then((x) => {
333-
setStore("lsp", x.data ?? [])
334-
setStore("lsp_ready", true)
335-
})
384+
void queryClient.fetchQuery(loadLspQuery(directory, sdkFor(directory))).then((data) => {
385+
setStore("lsp", data ?? [])
386+
})
336387
},
337388
})
338389
})
339390

340391
onCleanup(unsub)
341-
onCleanup(() => {
342-
queue.dispose()
343-
})
392+
// onCleanup(() => {
393+
// queue.dispose()
394+
// })
344395
onCleanup(() => {
345396
for (const directory of Object.keys(children.children)) {
346397
children.disposeDirectory(directory)
347398
}
348399
})
349400

350-
async function bootstrap() {
351-
bootingRoot = true
352-
try {
353-
await bootstrapGlobal({
354-
globalSDK: globalSDK.client,
355-
requestFailedTitle: language.t("common.requestFailed"),
356-
translate: language.t,
357-
formatMoreCount: (count) => language.t("common.moreCountSuffix", { count }),
358-
setGlobalStore: setBootStore,
359-
queryClient,
360-
})
361-
bootedAt = Date.now()
362-
} finally {
363-
bootingRoot = false
364-
}
365-
}
366-
367401
onMount(() => {
368402
if (typeof requestAnimationFrame === "function") {
369403
eventFrame = requestAnimationFrame(() => {
@@ -379,7 +413,6 @@ function createGlobalSync() {
379413
void globalSDK.event.start()
380414
}, 0)
381415
}
382-
void bootstrap()
383416
})
384417

385418
const projectApi = {
@@ -392,21 +425,10 @@ function createGlobalSync() {
392425
},
393426
}
394427

395-
const updateConfig = async (config: Config) => {
396-
setGlobalStore("reload", "pending")
397-
return globalSDK.client.global.config
398-
.update({ config })
399-
.then(bootstrap)
400-
.then(() => {
401-
queue.refresh()
402-
setGlobalStore("reload", undefined)
403-
queue.refresh()
404-
})
405-
.catch((error) => {
406-
setGlobalStore("reload", undefined)
407-
throw error
408-
})
409-
}
428+
const updateConfigMutation = useMutation(() => ({
429+
mutationFn: (config: Config) => globalSDK.client.global.config.update({ config }),
430+
// onSuccess: () => bootstrap.refetch(),
431+
}))
410432

411433
return {
412434
data: globalStore,
@@ -419,8 +441,8 @@ function createGlobalSync() {
419441
},
420442
child: children.child,
421443
peek: children.peek,
422-
bootstrap,
423-
updateConfig,
444+
// bootstrap,
445+
updateConfig: updateConfigMutation.mutateAsync,
424446
project: projectApi,
425447
todo: {
426448
set: setSessionTodo,

0 commit comments

Comments
 (0)