Fix "Missing queryFn" error when reloading with project openn (#10894)

- Fix https://github.com/enso-org/cloud-v2/issues/1451
- Fix "Missing queryFn" error due to
- This is done by providing a default value to the query. A more ideal solution may be to use the full query with the `queryFn`, but this is not an option here as the full query for this query requires a lot more info, some of which we don't have.

# Important Notes
- Test opening a top-level project and then refreshing
- Test opening a project in a nested directory and then refreshing (to make sure the query is not being executed just because the corresponding row is visible)
This commit is contained in:
somebody1234 2024-08-27 17:40:27 +10:00 committed by GitHub
parent 4d286e02b6
commit bd3ebc5000
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 22 additions and 32 deletions

View File

@ -169,7 +169,7 @@ export default function AssetRow(props: AssetRowProps) {
// This is SAFE, as `isOpened` is only true for projects.
// eslint-disable-next-line no-restricted-syntax
...createGetProjectDetailsQuery.createPassiveListener(item.item.id as backendModule.ProjectId),
select: (data) => data.state.type,
select: (data) => data?.state.type,
enabled: item.type === backendModule.AssetType.project,
})

View File

@ -74,13 +74,9 @@ export default function ProjectIcon(props: ProjectIconProps) {
const { user } = authProvider.useFullUserSession()
const { getText } = textProvider.useText()
const {
data: projectState,
isLoading,
isError,
} = reactQuery.useQuery({
const { data: projectState, isError } = reactQuery.useQuery({
...projectHooks.createGetProjectDetailsQuery.createPassiveListener(item.id),
select: (data) => data.state,
select: (data) => data?.state,
enabled: isOpened,
})
const status = projectState?.type
@ -95,12 +91,8 @@ export default function ProjectIcon(props: ProjectIconProps) {
// Project is closed, show open button
if (!isOpened) {
return backendModule.ProjectState.closed
} else if (!isLoading && status == null) {
// Project is opened, but not yet queried.
return backendModule.ProjectState.openInProgress
} else if (isLoading) {
return backendModule.ProjectState.openInProgress
} else if (status == null) {
// Project is opened, but not yet queried.
return backendModule.ProjectState.openInProgress
} else if (status === backendModule.ProjectState.closed) {
// Project is opened locally, but not on the backend yet.
@ -113,8 +105,6 @@ export default function ProjectIcon(props: ProjectIconProps) {
const spinnerState = (() => {
if (!isOpened) {
return spinner.SpinnerState.initial
} else if (isLoading) {
return spinner.SpinnerState.loadingSlow
} else if (isError) {
return spinner.SpinnerState.initial
} else if (status == null) {

View File

@ -28,6 +28,14 @@ import type RemoteBackend from '#/services/RemoteBackend'
// ====================================
// === createGetProjectDetailsQuery ===
// ====================================
/** Default interval for refetching project status when the project is opened. */
const OPENED_INTERVAL_MS = 30_000
/** Interval when we open a cloud project.
* Since opening a cloud project is a long operation, we want to check the status less often. */
const CLOUD_OPENING_INTERVAL_MS = 5_000
/** Interval when we open a local project or when we want to sync the project status as soon as
* possible. */
const ACTIVE_SYNC_INTERVAL_MS = 100
/** Options for {@link createGetProjectDetailsQuery}. */
export interface CreateOpenedProjectQueryOptions {
@ -51,14 +59,6 @@ export function createGetProjectDetailsQuery(options: CreateOpenedProjectQueryOp
meta: { persist: false },
gcTime: 0,
refetchInterval: ({ state }) => {
/** Default interval for refetching project status when the project is opened. */
const openedIntervalMS = 30_000
/** Interval when we open a cloud project.
* Since opening a cloud project is a long operation, we want to check the status less often. */
const cloudOpeningIntervalMS = 5_000
/** Interval when we open a local project or when we want to sync the project status as soon as
* possible. */
const activeSyncIntervalMS = 100
const states = [backendModule.ProjectState.opened, backendModule.ProjectState.closed]
if (state.status === 'error') {
@ -67,17 +67,17 @@ export function createGetProjectDetailsQuery(options: CreateOpenedProjectQueryOp
}
if (isLocal) {
if (state.data?.state.type === backendModule.ProjectState.opened) {
return openedIntervalMS
return OPENED_INTERVAL_MS
} else {
return activeSyncIntervalMS
return ACTIVE_SYNC_INTERVAL_MS
}
} else {
if (state.data == null) {
return activeSyncIntervalMS
return ACTIVE_SYNC_INTERVAL_MS
} else if (states.includes(state.data.state.type)) {
return openedIntervalMS
return OPENED_INTERVAL_MS
} else {
return cloudOpeningIntervalMS
return CLOUD_OPENING_INTERVAL_MS
}
}
},
@ -93,8 +93,9 @@ export function createGetProjectDetailsQuery(options: CreateOpenedProjectQueryOp
}
createGetProjectDetailsQuery.getQueryKey = (id: LaunchedProjectId) => ['project', id] as const
createGetProjectDetailsQuery.createPassiveListener = (id: LaunchedProjectId) =>
reactQuery.queryOptions<backendModule.Project>({
reactQuery.queryOptions<backendModule.Project | null>({
queryKey: createGetProjectDetailsQuery.getQueryKey(id),
initialData: null,
})
// ==============================

View File

@ -149,7 +149,7 @@ export default function DriveBar(props: DriveBarProps) {
})
}, [isCloud, doCreateDirectory, doCreateProject, inputBindings])
const createdProjectQuery = useQuery<Project>(
const createdProjectQuery = useQuery<Project | null>(
createdProjectId ?
createGetProjectDetailsQuery.createPassiveListener(createdProjectId)
: { queryKey: ['__IGNORE__'], queryFn: skipToken },

View File

@ -207,14 +207,13 @@ export function Tab(props: InternalTabProps) {
}
}, [actuallyActive, id, setSelectedTab])
const { isLoading, data } = reactQuery.useQuery<backend.Project>(
const { isLoading, data } = reactQuery.useQuery<backend.Project | null>(
project?.id ?
projectHooks.createGetProjectDetailsQuery.createPassiveListener(project.id)
: { queryKey: ['__IGNORE__'], queryFn: reactQuery.skipToken },
)
const isFetching =
(isLoading || (data && data.state.type !== backend.ProjectState.opened)) ?? false
const isFetching = isLoading || data == null || data.state.type !== backend.ProjectState.opened
React.useEffect(() => {
if (!isFetching && isLoadingRef.current) {