perf: return deferred data in permission loader (#7635)

This commit is contained in:
Curry Yang 2024-07-15 18:25:53 +08:00 committed by GitHub
parent 570c1c0055
commit afb861b310
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 42 additions and 41 deletions

View File

@ -3,6 +3,7 @@ import React from 'react';
import { useFetcher, useParams, useRouteLoaderData } from 'react-router-dom'; import { useFetcher, useParams, useRouteLoaderData } from 'react-router-dom';
import { isRemoteProject } from '../../../models/project'; import { isRemoteProject } from '../../../models/project';
import { useLoaderDeferData } from '../../hooks/use-loader-defer-data';
import type { OrganizationFeatureLoaderData } from '../../routes/organization'; import type { OrganizationFeatureLoaderData } from '../../routes/organization';
import { useRootLoaderData } from '../../routes/root'; import { useRootLoaderData } from '../../routes/root';
import type { WorkspaceLoaderData } from '../../routes/workspace'; import type { WorkspaceLoaderData } from '../../routes/workspace';
@ -30,11 +31,11 @@ export const WorkspaceSyncDropdown: FC = () => {
} }
}, [organizationId, permissionsFetcher]); }, [organizationId, permissionsFetcher]);
const { features } = permissionsFetcher.data || { const { featuresPromise } = permissionsFetcher.data || {};
features: { const [features = {
gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, gitSync: { enabled: false, reason: 'Insomnia API unreachable' },
}, }] = useLoaderDeferData(featuresPromise);
};
if (!userSession.id) { if (!userSession.id) {
return null; return null;
} }

View File

@ -7,6 +7,7 @@ import { docsTemplateTags } from '../../../common/documentation';
import { debounce } from '../../../common/misc'; import { debounce } from '../../../common/misc';
import type { Environment } from '../../../models/environment'; import type { Environment } from '../../../models/environment';
import { isRemoteProject } from '../../../models/project'; import { isRemoteProject } from '../../../models/project';
import { useLoaderDeferData } from '../../hooks/use-loader-defer-data';
import type { OrganizationFeatureLoaderData } from '../../routes/organization'; import type { OrganizationFeatureLoaderData } from '../../routes/organization';
import type { WorkspaceLoaderData } from '../../routes/workspace'; import type { WorkspaceLoaderData } from '../../routes/workspace';
import { EditableInput } from '../editable-input'; import { EditableInput } from '../editable-input';
@ -31,11 +32,11 @@ export const WorkspaceEnvironmentsEditModal = ({ onClose }: {
} }
}, [organizationId, permissionsFetcher]); }, [organizationId, permissionsFetcher]);
const { features } = permissionsFetcher.data || { const { featuresPromise } = permissionsFetcher.data || {};
features: { const [features = {
gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, gitSync: { enabled: false, reason: 'Insomnia API unreachable' },
}, }] = useLoaderDeferData(featuresPromise);
};
const createEnvironmentFetcher = useFetcher(); const createEnvironmentFetcher = useFetcher();
const deleteEnvironmentFetcher = useFetcher(); const deleteEnvironmentFetcher = useFetcher();
const updateEnvironmentFetcher = useFetcher(); const updateEnvironmentFetcher = useFetcher();

View File

@ -25,7 +25,7 @@ export const useLoaderDeferData = <T>(deferedDataPromise?: Promise<T>, keepStale
setData(data); setData(data);
} catch (err) { } catch (err) {
setError(err); setError(err);
console.log('Failed to load defered data', err); console.warn('Failed to load defered data', err);
} }
})(); })();
}, [deferedDataPromise, keepStaleDataKey]); }, [deferedDataPromise, keepStaleDataKey]);

View File

@ -15,6 +15,7 @@ import { EnvironmentEditor, type EnvironmentEditorHandle, type EnvironmentInfo }
import { Icon } from '../components/icon'; import { Icon } from '../components/icon';
import { useDocBodyKeyboardShortcuts } from '../components/keydown-binder'; import { useDocBodyKeyboardShortcuts } from '../components/keydown-binder';
import { showAlert } from '../components/modals'; import { showAlert } from '../components/modals';
import { useLoaderDeferData } from '../hooks/use-loader-defer-data';
import type { OrganizationFeatureLoaderData } from './organization'; import type { OrganizationFeatureLoaderData } from './organization';
import type { WorkspaceLoaderData } from './workspace'; import type { WorkspaceLoaderData } from './workspace';
@ -34,11 +35,10 @@ const Environments = () => {
} }
}, [organizationId, permissionsFetcher]); }, [organizationId, permissionsFetcher]);
const { features } = permissionsFetcher.data || { const { featuresPromise } = permissionsFetcher.data || {};
features: { const [features = {
gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, gitSync: { enabled: false, reason: 'Insomnia API unreachable' },
}, }] = useLoaderDeferData(featuresPromise);
};
const createEnvironmentFetcher = useFetcher(); const createEnvironmentFetcher = useFetcher();
const deleteEnvironmentFetcher = useFetcher(); const deleteEnvironmentFetcher = useFetcher();

View File

@ -312,9 +312,9 @@ export interface StorageRule {
} }
export interface OrganizationFeatureLoaderData { export interface OrganizationFeatureLoaderData {
features: FeatureList; featuresPromise: Promise<FeatureList>;
billing: Billing; billingPromise: Promise<Billing>;
storage: 'cloud_plus_local' | 'cloud_only' | 'local_only'; storagePromise: Promise<'cloud_plus_local' | 'cloud_only' | 'local_only'>;
} }
export const organizationPermissionsLoader: LoaderFunction = async ({ params }): Promise<OrganizationFeatureLoaderData> => { export const organizationPermissionsLoader: LoaderFunction = async ({ params }): Promise<OrganizationFeatureLoaderData> => {
@ -334,9 +334,9 @@ export const organizationPermissionsLoader: LoaderFunction = async ({ params }):
if (isScratchpadOrganizationId(organizationId)) { if (isScratchpadOrganizationId(organizationId)) {
return { return {
features: fallbackFeatures, featuresPromise: Promise.resolve(fallbackFeatures),
billing: fallbackBilling, billingPromise: Promise.resolve(fallbackBilling),
storage: fallbackStorage, storagePromise: Promise.resolve(fallbackStorage),
}; };
} }
@ -348,28 +348,27 @@ export const organizationPermissionsLoader: LoaderFunction = async ({ params }):
} }
try { try {
const response = await insomniaFetch<{ features: FeatureList; billing: Billing } | undefined>({ const featuresResponse = insomniaFetch<{ features: FeatureList; billing: Billing } | undefined>({
method: 'GET', method: 'GET',
path: `/v1/organizations/${organizationId}/features`, path: `/v1/organizations/${organizationId}/features`,
sessionId, sessionId,
}); });
const ruleResponse = await insomniaFetch<StorageRule | undefined>({ const ruleResponse = insomniaFetch<StorageRule | undefined>({
method: 'GET', method: 'GET',
path: `/v1/organizations/${organizationId}/storage-rule`, path: `/v1/organizations/${organizationId}/storage-rule`,
sessionId, sessionId,
}); });
const storage = ruleResponse?.storage || fallbackStorage;
return { return {
features: response?.features || fallbackFeatures, featuresPromise: featuresResponse.then(res => res?.features || fallbackFeatures),
billing: response?.billing || fallbackBilling, billingPromise: featuresResponse.then(res => res?.billing || fallbackBilling),
storage, storagePromise: ruleResponse.then(res => res?.storage || fallbackStorage),
}; };
} catch (err) { } catch (err) {
return { return {
features: fallbackFeatures, featuresPromise: Promise.resolve(fallbackFeatures),
billing: fallbackBilling, billingPromise: Promise.resolve(fallbackBilling),
storage: fallbackStorage, storagePromise: Promise.resolve(fallbackStorage),
}; };
} }
}; };

View File

@ -612,16 +612,16 @@ const ProjectRoute: FC = () => {
}, [organizationId, permissionsFetcher.load]); }, [organizationId, permissionsFetcher.load]);
const { currentPlan } = useRouteLoaderData('/organization') as OrganizationLoaderData; const { currentPlan } = useRouteLoaderData('/organization') as OrganizationLoaderData;
const { features, billing, storage } = permissionsFetcher.data || {
features: { const { featuresPromise, billingPromise, storagePromise } = permissionsFetcher.data || {};
gitSync: { enabled: false, reason: 'Insomnia API unreachable' }, const [features = {
orgBasicRbac: { enabled: false, reason: 'Insomnia API unreachable' }, gitSync: { enabled: false, reason: 'Insomnia API unreachable' },
}, orgBasicRbac: { enabled: false, reason: 'Insomnia API unreachable' },
billing: { }] = useLoaderDeferData(featuresPromise);
isActive: true, const [billing = {
}, isActive: true,
storage: 'cloud_plus_local', }] = useLoaderDeferData(billingPromise);
}; const [storage = 'cloud_plus_local'] = useLoaderDeferData(storagePromise);
const [projectListFilter, setProjectListFilter] = useLocalStorage(`${organizationId}:project-list-filter`, ''); const [projectListFilter, setProjectListFilter] = useLocalStorage(`${organizationId}:project-list-filter`, '');
const [workspaceListFilter, setWorkspaceListFilter] = useLocalStorage(`${projectId}:workspace-list-filter`, ''); const [workspaceListFilter, setWorkspaceListFilter] = useLocalStorage(`${projectId}:workspace-list-filter`, '');
const [workspaceListScope, setWorkspaceListScope] = useLocalStorage(`${projectId}:workspace-list-scope`, 'all'); const [workspaceListScope, setWorkspaceListScope] = useLocalStorage(`${projectId}:workspace-list-scope`, 'all');