mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
console: show total max connections
in pool settings fields for CE/EE/Cloud
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6080 GitOrigin-RevId: aafa8350f8d00d3f8ddb6e51964f06a25455aac5
This commit is contained in:
parent
06138634bc
commit
b60b38d70b
@ -1,11 +1,13 @@
|
||||
import React, { InputHTMLAttributes } from 'react';
|
||||
import { IconTooltip } from '@/new-components/Tooltip';
|
||||
import { FaExclamationTriangle } from 'react-icons/fa';
|
||||
|
||||
interface LabeledInputProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||
label: string;
|
||||
boldlabel?: boolean;
|
||||
tooltipText?: string;
|
||||
type?: string;
|
||||
icon?: boolean;
|
||||
}
|
||||
|
||||
export const LabeledInput: React.FC<LabeledInputProps> = props => (
|
||||
@ -17,6 +19,7 @@ export const LabeledInput: React.FC<LabeledInputProps> = props => (
|
||||
>
|
||||
{props?.boldlabel ? <b>{props.label}</b> : props.label}
|
||||
{props.tooltipText && <IconTooltip message={props.tooltipText} />}
|
||||
{props.icon && <FaExclamationTriangle className="text-blue-300 ml-xs" />}
|
||||
</label>
|
||||
<input
|
||||
type={props?.type ?? 'text'}
|
||||
|
@ -90,6 +90,7 @@ const ConnectDatabaseForm = (props: ConnectDatabaseFormProps) => {
|
||||
connectionTypeState,
|
||||
isReadReplica = false,
|
||||
title,
|
||||
isEditState,
|
||||
} = props;
|
||||
|
||||
const isDBSupported = (driver: Driver, connectionType: string) => {
|
||||
@ -385,6 +386,7 @@ const ConnectDatabaseForm = (props: ConnectDatabaseFormProps) => {
|
||||
<ConnectionSettingsForm
|
||||
connectionDBState={connectionDBState}
|
||||
connectionDBStateDispatch={connectionDBStateDispatch}
|
||||
isEditState={isEditState}
|
||||
/>
|
||||
{/*
|
||||
TODO: remove the edit state condition when the BE issue is solved
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import { useMetadata } from '@/features/MetadataAPI';
|
||||
import { isProConsole } from '@/utils/proConsole';
|
||||
import React, { Dispatch } from 'react';
|
||||
import { ConnectDBActions, ConnectDBState } from '../state';
|
||||
import { buildFormSettings } from './buildFormSettings';
|
||||
@ -11,15 +14,26 @@ import {
|
||||
PreparedStatements,
|
||||
Retries,
|
||||
SSLCertificates,
|
||||
CumulativeMaxConnections,
|
||||
} from './parts';
|
||||
|
||||
export interface ConnectionSettingsFormProps {
|
||||
connectionDBState: ConnectDBState;
|
||||
connectionDBStateDispatch: Dispatch<ConnectDBActions>;
|
||||
isEditState?: boolean;
|
||||
}
|
||||
|
||||
const ConnectionSettingsForm: React.FC<ConnectionSettingsFormProps> = props => {
|
||||
const { connectionDBState } = props;
|
||||
const { connectionDBState, isEditState } = props;
|
||||
|
||||
const { data: metadata } = useMetadata();
|
||||
|
||||
const currentDBState = metadata?.metadata?.sources.find(
|
||||
d => d.name === connectionDBState?.displayName
|
||||
);
|
||||
const isMaxConnectionSet =
|
||||
currentDBState?.configuration?.connection_info?.pool_settings
|
||||
?.max_connections;
|
||||
|
||||
const formSettings = React.useMemo(
|
||||
() => buildFormSettings(connectionDBState.dbType),
|
||||
@ -28,12 +42,29 @@ const ConnectionSettingsForm: React.FC<ConnectionSettingsFormProps> = props => {
|
||||
|
||||
if (!formSettings.connectionSettings) return null;
|
||||
|
||||
if (!isEditState) {
|
||||
return (
|
||||
<FormContainer>
|
||||
{!isProConsole(window.__env) && <MaxConnections {...props} />}
|
||||
{formSettings.cumulativeMaxConnections && (
|
||||
<CumulativeMaxConnections {...props} />
|
||||
)}
|
||||
<IdleTimeout {...props} />
|
||||
{formSettings.retries && <Retries {...props} />}
|
||||
{formSettings.pool_timeout && <PoolTimeout {...props} />}
|
||||
{formSettings.connection_lifetime && <ConnectionLifetime {...props} />}
|
||||
{formSettings.isolation_level && <IsolationLevel {...props} />}
|
||||
{formSettings.prepared_statements && <PreparedStatements {...props} />}
|
||||
{formSettings.ssl_certificates && <SSLCertificates {...props} />}
|
||||
</FormContainer>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<FormContainer>
|
||||
<MaxConnections {...props} />
|
||||
{/* {formSettings.cumulativeMaxConnections && (
|
||||
{isMaxConnectionSet && <MaxConnections {...props} />}
|
||||
{formSettings.cumulativeMaxConnections && (
|
||||
<CumulativeMaxConnections {...props} />
|
||||
)} */}
|
||||
)}
|
||||
<IdleTimeout {...props} />
|
||||
{formSettings.retries && <Retries {...props} />}
|
||||
{formSettings.pool_timeout && <PoolTimeout {...props} />}
|
||||
|
@ -1,30 +1,50 @@
|
||||
import React from 'react';
|
||||
import { LabeledInput } from '@/components/Common/LabeledInput';
|
||||
import { ConnectionSettingsFormProps } from '@/components/Services/Data/DataSources/ConnectionSettings/ConnectionSettingsForm';
|
||||
import React from 'react';
|
||||
import { IndicatorCard } from '@/new-components/IndicatorCard';
|
||||
import { FaExclamationTriangle } from 'react-icons/fa';
|
||||
import styles from '../../DataSources.module.scss';
|
||||
|
||||
export const CumulativeMaxConnections: React.VFC<ConnectionSettingsFormProps> =
|
||||
({ connectionDBState, connectionDBStateDispatch }) => (
|
||||
<div className={styles.connection_settings_input_layout}>
|
||||
<LabeledInput
|
||||
label="Cumulative Max Connections"
|
||||
tooltipText="Maximum number of database connections"
|
||||
type="number"
|
||||
className={`form-control ${styles.connnection_settings_form_input}`}
|
||||
placeholder="50"
|
||||
value={
|
||||
connectionDBState.connectionSettings?.cumulative_max_connections ||
|
||||
undefined
|
||||
}
|
||||
onChange={e =>
|
||||
connectionDBStateDispatch({
|
||||
type: 'UPDATE_CUMULATIVE_MAX_CONNECTIONS',
|
||||
data: e.target.value,
|
||||
})
|
||||
}
|
||||
min="0"
|
||||
boldlabel
|
||||
data-test="max-connections"
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<div className={styles.connection_settings_input_layout}>
|
||||
<LabeledInput
|
||||
label="Total Max Connections"
|
||||
tooltipText="Maximum number of database connections"
|
||||
type="number"
|
||||
className={`form-control ${styles.connnection_settings_form_input}`}
|
||||
placeholder="50"
|
||||
value={
|
||||
connectionDBState.connectionSettings?.total_max_connections ||
|
||||
undefined
|
||||
}
|
||||
onChange={e =>
|
||||
connectionDBStateDispatch({
|
||||
type: 'UPDATE_TOTAL_MAX_CONNECTIONS',
|
||||
data: e.target.value,
|
||||
})
|
||||
}
|
||||
min="0"
|
||||
boldlabel
|
||||
data-test="max-connections"
|
||||
icon={
|
||||
connectionDBState?.connectionSettings?.max_connections !== undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{connectionDBState?.connectionSettings?.max_connections && (
|
||||
<IndicatorCard status="info">
|
||||
<p className="font-bold">
|
||||
<FaExclamationTriangle className="text-blue-300 pb-1 mr-4 text-lg" />
|
||||
Set Total Max Connections
|
||||
</p>
|
||||
<p className="ml-lg">
|
||||
You have set <b>Max Connections Per Instance</b> which is not
|
||||
recommended for Hasura Cloud. Use <b>Total Max Connections</b>{' '}
|
||||
instead.
|
||||
</p>
|
||||
</IndicatorCard>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@ -9,7 +9,7 @@ export const MaxConnections: React.VFC<ConnectionSettingsFormProps> = ({
|
||||
}) => (
|
||||
<div className={styles.connection_settings_input_layout}>
|
||||
<LabeledInput
|
||||
label="Max Connections"
|
||||
label="Max Connections Per Instance"
|
||||
tooltipText="Maximum number of database connections per instance"
|
||||
type="number"
|
||||
className={`form-control ${styles.connnection_settings_form_input}`}
|
||||
|
@ -259,7 +259,7 @@ export type ConnectDBActions =
|
||||
| { type: 'UPDATE_DB_PASSWORD'; data: string }
|
||||
| { type: 'UPDATE_DB_DATABASE_NAME'; data: string }
|
||||
| { type: 'UPDATE_MAX_CONNECTIONS'; data: string }
|
||||
| { type: 'UPDATE_CUMULATIVE_MAX_CONNECTIONS'; data: string }
|
||||
| { type: 'UPDATE_TOTAL_MAX_CONNECTIONS'; data: string }
|
||||
| { type: 'UPDATE_RETRIES'; data: string }
|
||||
| { type: 'UPDATE_IDLE_TIMEOUT'; data: string }
|
||||
| { type: 'UPDATE_POOL_TIMEOUT'; data: string }
|
||||
@ -389,11 +389,12 @@ export const connectDBReducer = (
|
||||
max_connections: setNumberFromString(action.data),
|
||||
},
|
||||
};
|
||||
case 'UPDATE_CUMULATIVE_MAX_CONNECTIONS':
|
||||
case 'UPDATE_TOTAL_MAX_CONNECTIONS':
|
||||
return produce(state, (draft: ConnectDBState) => {
|
||||
draft.connectionSettings = state.connectionSettings ?? {};
|
||||
draft.connectionSettings.cumulative_max_connections =
|
||||
setNumberFromString(action.data);
|
||||
draft.connectionSettings.total_max_connections = setNumberFromString(
|
||||
action.data
|
||||
);
|
||||
});
|
||||
case 'UPDATE_RETRIES':
|
||||
return {
|
||||
@ -670,9 +671,9 @@ export const makeReadReplicaConnectionObject = (
|
||||
if (stateVal.connectionSettings?.max_connections) {
|
||||
pool_settings.max_connections = stateVal.connectionSettings.max_connections;
|
||||
}
|
||||
if (stateVal.connectionSettings?.cumulative_max_connections) {
|
||||
pool_settings.cumulative_max_connections =
|
||||
stateVal.connectionSettings.cumulative_max_connections;
|
||||
if (stateVal.connectionSettings?.total_max_connections) {
|
||||
pool_settings.total_max_connections =
|
||||
stateVal.connectionSettings.total_max_connections;
|
||||
}
|
||||
if (stateVal.connectionSettings?.idle_timeout) {
|
||||
pool_settings.idle_timeout = stateVal.connectionSettings.idle_timeout;
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-underscore-dangle */
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
@ -9,6 +10,7 @@ import {
|
||||
useIsFeatureFlagEnabled,
|
||||
} from '@/features/FeatureFlags';
|
||||
import { nativeDrivers } from '@/features/DataSource';
|
||||
import { isProConsole } from '@/utils/proConsole';
|
||||
import styles from './styles.module.scss';
|
||||
import { Dispatch, ReduxState } from '../../../../types';
|
||||
import BreadCrumb from '../../../Common/Layout/BreadCrumb/BreadCrumb';
|
||||
@ -61,7 +63,6 @@ const DatabaseListItem: React.FC<DatabaseListItemProps> = ({
|
||||
const [removing, setRemoving] = useState(false);
|
||||
const [showUrl, setShowUrl] = useState(false);
|
||||
const [dbVersion, setDbVersion] = useState('');
|
||||
|
||||
const fetchDBVersion = () => {
|
||||
const query = services[dataSource.driver].getDatabaseVersionSql ?? '';
|
||||
|
||||
@ -103,6 +104,7 @@ const DatabaseListItem: React.FC<DatabaseListItemProps> = ({
|
||||
dataSource.name,
|
||||
inconsistentObjects
|
||||
);
|
||||
|
||||
return (
|
||||
<tr data-test={dataSource.name}>
|
||||
<td className="px-sm py-xs align-top w-0 whitespace-nowrap">
|
||||
@ -128,29 +130,14 @@ const DatabaseListItem: React.FC<DatabaseListItemProps> = ({
|
||||
>
|
||||
Reload
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
className="mr-xs"
|
||||
onClick={() => {
|
||||
onEdit(dataSource.name);
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
isLoading={removing}
|
||||
loadingText="Removing..."
|
||||
className="text-red-600"
|
||||
onClick={() => {
|
||||
setRemoving(true);
|
||||
onRemove(dataSource.name, dataSource.driver, () =>
|
||||
setRemoving(false)
|
||||
);
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
{isProConsole(window.__env)
|
||||
? !dataSource?.connection_pool_settings?.total_max_connections && (
|
||||
<span className="bg-blue-100 font-bold rounded-lg pr-xs">
|
||||
<FaExclamationTriangle className="mr-0.5 pb-1 pl-1.5 text-lg" />
|
||||
Set Total Max Connections
|
||||
</span>
|
||||
)
|
||||
: null}
|
||||
</td>
|
||||
<td className="px-sm py-xs max-w-xs align-top">
|
||||
<CollapsibleToggle dataSource={dataSource} dbVersion={dbVersion} />
|
||||
@ -180,7 +167,30 @@ const DatabaseListItem: React.FC<DatabaseListItemProps> = ({
|
||||
onClick={() => setShowUrl(true)}
|
||||
>
|
||||
<FaEye aria-hidden="true" />
|
||||
<div className="ml-xs">Show Connection String</div>
|
||||
<div className="ml-xs mr-4">Show Connection String</div>
|
||||
<Button
|
||||
size="sm"
|
||||
className="mr-xs"
|
||||
onClick={() => {
|
||||
onEdit(dataSource.name);
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
isLoading={removing}
|
||||
loadingText="Removing..."
|
||||
className="text-red-600"
|
||||
onClick={() => {
|
||||
setRemoving(true);
|
||||
onRemove(dataSource.name, dataSource.driver, () =>
|
||||
setRemoving(false)
|
||||
);
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</span>
|
||||
)}
|
||||
{showUrl && (
|
||||
|
@ -1069,7 +1069,7 @@ export interface SSLConfigOptions {
|
||||
|
||||
export interface ConnectionPoolSettings {
|
||||
max_connections?: number;
|
||||
cumulative_max_connections?: number;
|
||||
total_max_connections?: number;
|
||||
idle_timeout?: number;
|
||||
retries?: number;
|
||||
pool_timeout?: number;
|
||||
|
Loading…
Reference in New Issue
Block a user