diff --git a/.cspell.json b/.cspell.json index 80e1fa3af0..289783a6ff 100644 --- a/.cspell.json +++ b/.cspell.json @@ -31,7 +31,8 @@ "wsproxy", "ahooks", "lucide", - "Signout" + "Signout", + "Talkativot" ], "flagWords": [ "데이터레이크", diff --git a/react/src/components/ServiceLauncherPageContent.tsx b/react/src/components/ServiceLauncherPageContent.tsx index 12444bc68f..3ebab9c660 100644 --- a/react/src/components/ServiceLauncherPageContent.tsx +++ b/react/src/components/ServiceLauncherPageContent.tsx @@ -88,7 +88,8 @@ interface ServiceCreateConfigType { } export interface ServiceCreateType { name: string; - desired_session_count: number; + desired_session_count?: number; + replicas?: number; image: string; runtime_variant: string; architecture: string; @@ -106,7 +107,7 @@ export interface ServiceCreateType { interface ServiceLauncherInput extends ImageEnvironmentFormInput { serviceName: string; vFolderID: string; - desiredRoutingCount: number; + replicas: number; openToPublic: boolean; modelMountDestination: string; modelDefinitionPath: string; @@ -153,7 +154,8 @@ const ServiceLauncherPageContent: React.FC = ({ graphql` fragment ServiceLauncherPageContentFragment on Endpoint { endpoint_id - desired_session_count + desired_session_count @deprecatedSince(version: "24.12.0") + replicas @since(version: "24.12.0") resource_group resource_slots resource_opts @@ -264,7 +266,7 @@ const ServiceLauncherPageContent: React.FC = ({ const legacyMutationToUpdateService = useTanMutation({ mutationFn: (values: ServiceLauncherFormValue) => { const body = { - to: values.desiredRoutingCount, + to: values.replicas, }; return baiSignedRequestWithPromise({ method: 'POST', @@ -289,7 +291,8 @@ const ServiceLauncherPageContent: React.FC = ({ } const body: ServiceCreateType = { name: values.serviceName, - desired_session_count: values.desiredRoutingCount, + // REST API does not support `replicas` field. To use `replicas` field, we need `create_endpoint` mutation. + desired_session_count: values.replicas, ...getImageInfoFromInputInCreating( checkManualImageAllowed( baiClient._config.allow_manual_image_name_for_session, @@ -407,7 +410,8 @@ const ServiceLauncherPageContent: React.FC = ({ msg endpoint { endpoint_id - desired_session_count + desired_session_count @deprecatedSince(version: "24.12.0") + replicas @since(version: "24.12.0") resource_group resource_slots resource_opts @@ -500,7 +504,11 @@ const ServiceLauncherPageContent: React.FC = ({ ? 'SINGLE_NODE' : 'MULTI_NODE', cluster_size: values.cluster_size, - desired_session_count: values.desiredRoutingCount, + ...(baiClient.supports('replicas') + ? { replicas: values.replicas } + : { + desired_session_count: values.replicas, + }), ...getImageInfoFromInputInEditing( checkManualImageAllowed( baiClient._config.allow_manual_image_name_for_session, @@ -643,7 +651,7 @@ const ServiceLauncherPageContent: React.FC = ({ serviceName: endpoint?.name, resourceGroup: endpoint?.resource_group, allocationPreset: 'custom', - desiredRoutingCount: endpoint?.desired_session_count ?? 1, + replicas: endpoint?.replicas ?? endpoint?.desired_session_count ?? 1, // FIXME: memory doesn't applied to resource allocation resource: { cpu: parseInt(JSON.parse(endpoint?.resource_slots || '{}')?.cpu), @@ -692,7 +700,7 @@ const ServiceLauncherPageContent: React.FC = ({ // TODO: set mounts alias map according to extra_mounts if possible } : { - desiredRoutingCount: 1, + replicas: 1, runtimeVariant: 'custom', ...RESOURCE_ALLOCATION_INITIAL_FORM_VALUES, ...(baiClient._config?.default_session_environment && { @@ -899,8 +907,8 @@ const ServiceLauncherPageContent: React.FC = ({ )} = ({ const image: string = `${values.environments.image?.registry}/${values.environments.image?.name}:${values.environments.image?.tag}`; const body: ServiceCreateType = { name: values.serviceName, - desired_session_count: values.desiredRoutingCount, + ...(baiClient.supports('replicas') + ? { replicas: values.replicas } + : { + desired_session_count: values.replicas, + }), image: image, runtime_variant: values.runtimeVariant, architecture: values.environments.image?.architecture as string, diff --git a/react/src/pages/EndpointDetailPage.tsx b/react/src/pages/EndpointDetailPage.tsx index 876ffde2bf..692b9e9068 100644 --- a/react/src/pages/EndpointDetailPage.tsx +++ b/react/src/pages/EndpointDetailPage.tsx @@ -18,6 +18,7 @@ import { useWebUINavigate, } from '../hooks'; import { useCurrentUserInfo } from '../hooks/backendai'; +import { useBAIPaginationOptionState } from '../hooks/reactPaginationQueryOptions'; import { useTanMutation } from '../hooks/reactQueryAlias'; import { isDestroyingStatus } from './EndpointListPage'; import { @@ -68,7 +69,8 @@ interface RoutingInfo { export interface ModelServiceInfo { endpoint_id: string; name: string; - desired_session_count: number; + desired_session_count?: number; + replicas?: number; active_routes: RoutingInfo[]; service_endpoint: string; is_public: boolean; @@ -91,12 +93,14 @@ const dayDiff = (a: any, b: any) => { const EndpointDetailPage: React.FC = () => { const { t } = useTranslation(); const { token } = theme.useToken(); - const baiClient = useSuspendedBackendaiClient(); - const navigate = useNavigate(); + const { message } = App.useApp(); + const { baiPaginationOption } = useBAIPaginationOptionState({ + current: 1, + pageSize: 100, + }); const { serviceId } = useParams<{ serviceId: string; }>(); - const [fetchKey, updateFetchKey] = useUpdatableState('initial-fetch'); const [isPendingRefetch, startRefetchTransition] = useTransition(); const [isPendingClearError, startClearErrorTransition] = useTransition(); @@ -107,14 +111,8 @@ const EndpointDetailPage: React.FC = () => { const [openChatModal, setOpenChatModal] = useState(false); const [currentUser] = useCurrentUserInfo(); // const curProject = useCurrentProjectValue(); - const [paginationState] = useState<{ - current: number; - pageSize: number; - }>({ - current: 1, - pageSize: 100, - }); - const { message } = App.useApp(); + const baiClient = useSuspendedBackendaiClient(); + const navigate = useNavigate(); const webuiNavigate = useWebUINavigate(); const { open } = useFolderExplorerOpener(); const [selectedSessionId, setSelectedSessionId] = useState(); @@ -151,7 +149,8 @@ const EndpointDetailPage: React.FC = () => { size_bytes supported_accelerators } - desired_session_count + desired_session_count @deprecatedSince(version: "24.12.0") + replicas @since(version: "24.12.0") url open_to_public errors { @@ -207,9 +206,8 @@ const EndpointDetailPage: React.FC = () => { } `, { - tokenListOffset: - (paginationState.current - 1) * paginationState.pageSize, - tokenListLimit: paginationState.pageSize, + tokenListOffset: baiPaginationOption.offset, + tokenListLimit: baiPaginationOption.limit, endpointId: serviceId || '', }, { @@ -298,7 +296,7 @@ const EndpointDetailPage: React.FC = () => { }, { label: t('modelService.DesiredSessionCount'), - children: endpoint?.desired_session_count, + children: endpoint?.desired_session_count ?? endpoint?.replicas, }, { label: t('modelService.ServiceEndpoint'), @@ -481,7 +479,7 @@ const EndpointDetailPage: React.FC = () => { loading={isPendingRefetch} icon={} disabled={isDestroyingStatus( - endpoint?.desired_session_count, + endpoint?.desired_session_count ?? endpoint?.replicas, endpoint?.status, )} onClick={() => { @@ -502,7 +500,7 @@ const EndpointDetailPage: React.FC = () => { icon={} disabled={ isDestroyingStatus( - endpoint?.desired_session_count, + endpoint?.desired_session_count ?? endpoint?.replicas, endpoint?.status, ) || (!!endpoint?.created_user_email && @@ -532,7 +530,7 @@ const EndpointDetailPage: React.FC = () => { type="primary" icon={} disabled={isDestroyingStatus( - endpoint?.desired_session_count, + endpoint?.desired_session_count ?? endpoint?.replicas, endpoint?.status, )} onClick={() => { @@ -562,14 +560,14 @@ const EndpointDetailPage: React.FC = () => { fixed: 'left', render: (text, row) => ( - {row.token} + {row?.token} ), }, { title: 'Status', render: (text, row) => { - const isExpired = dayjs.utc(row.valid_until).isBefore(); + const isExpired = dayjs.utc(row?.valid_until).isBefore(); return ( {isExpired ? 'Expired' : 'Valid'} @@ -585,7 +583,7 @@ const EndpointDetailPage: React.FC = () => { { // FIXME: temporally parse UTC and change to timezone (timezone need to be added in server side) row.valid_until - ? dayjs.utc(row.valid_until).tz().format('ll LTS') + ? dayjs.utc(row?.valid_until).tz().format('ll LTS') : '-' } @@ -598,7 +596,7 @@ const EndpointDetailPage: React.FC = () => { title: 'Created at', dataIndex: 'created_at', render: (text, row) => ( - {dayjs(row.created_at).format('ll LT')} + {dayjs(row?.created_at).format('ll LT')} ), defaultSortOrder: 'descend', sortDirections: ['descend', 'ascend', 'descend'], @@ -618,7 +616,7 @@ const EndpointDetailPage: React.FC = () => { icon={} loading={mutationToSyncRoutes.isPending} disabled={isDestroyingStatus( - endpoint?.desired_session_count, + endpoint?.desired_session_count ?? endpoint?.replicas, endpoint?.status, )} onClick={() => { @@ -674,20 +672,20 @@ const EndpointDetailPage: React.FC = () => { row.status && ( <> - {row.status.toUpperCase()} + {row?.status.toUpperCase()} - {row.status === 'FAILED_TO_START' && row.session && ( + {row?.status === 'FAILED_TO_START' && row?.session && (