Debug health check (#5587)

main
Andrey Zhavoronkov 3 years ago committed by GitHub
parent 8f71d90af4
commit 3fa6f35031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,8 +4,8 @@ ARG http_proxy
ARG https_proxy
ARG no_proxy
ARG socks_proxy
ARG PUBLIC_INSTANCE
ARG WA_PAGE_VIEW_HIT
ARG UI_APP_CONFIG
ENV TERM=xterm \
http_proxy=${http_proxy} \
@ -34,7 +34,7 @@ COPY cvat-core/ /tmp/cvat-core/
COPY cvat-canvas3d/ /tmp/cvat-canvas3d/
COPY cvat-canvas/ /tmp/cvat-canvas/
COPY cvat-ui/ /tmp/cvat-ui/
RUN yarn run build:cvat-ui
RUN UI_APP_CONFIG="${UI_APP_CONFIG}" yarn run build:cvat-ui
FROM nginx:mainline-alpine
# Replace default.conf configuration to remove unnecessary rules

@ -509,13 +509,32 @@ async function healthCheck(maxRetries, checkPeriod, requestTimeout, progressCall
timeout: requestTimeout,
})
.then((response) => response.data)
.catch((errorData) => {
if (maxRetries > 0) {
.catch((error) => {
let isHealthy = true;
let data;
if (typeof error?.response?.data === 'object') {
data = error.response.data;
// Temporary workaround: ignore errors with media cache for debugging purposes only
for (const checkName in data) {
if (Object.prototype.hasOwnProperty.call(data, checkName) &&
checkName !== 'Cache backend: media' &&
data[checkName] !== 'working') {
isHealthy = false;
}
}
} else {
isHealthy = false;
}
if (!isHealthy && maxRetries > 0) {
return new Promise((resolve) => setTimeout(resolve, checkPeriod))
.then(() => healthCheck(maxRetries - 1, checkPeriod,
requestTimeout, progressCallback, attempt + 1));
}
throw generateError(errorData);
if (isHealthy) {
return data;
}
throw generateError(error);
});
}

@ -11,7 +11,7 @@ import Input from 'antd/lib/input';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import consts from 'consts';
import config from 'config';
interface InputElementParameters {
clientID: number;
@ -51,7 +51,7 @@ function renderInputElement(parameters: InputElementParameters): JSX.Element {
{values.map(
(value: string): JSX.Element => (
<Select.Option key={value} value={value}>
{value === consts.UNDEFINED_ATTRIBUTE_VALUE ? consts.NO_BREAK_SPACE : value}
{value === config.UNDEFINED_ATTRIBUTE_VALUE ? config.NO_BREAK_SPACE : value}
</Select.Option>
),
)}
@ -68,7 +68,7 @@ function renderInputElement(parameters: InputElementParameters): JSX.Element {
{values.map(
(value: string): JSX.Element => (
<Radio style={{ display: 'block' }} key={value} value={value}>
{value === consts.UNDEFINED_ATTRIBUTE_VALUE ? consts.NO_BREAK_SPACE : value}
{value === config.UNDEFINED_ATTRIBUTE_VALUE ? config.NO_BREAK_SPACE : value}
</Radio>
),
)}
@ -185,7 +185,7 @@ function renderList(parameters: ListParameters): JSX.Element | null {
[key: string]: (keyEvent?: KeyboardEvent) => void;
} = {};
const filteredValues = values.filter((value: string): boolean => value !== consts.UNDEFINED_ATTRIBUTE_VALUE);
const filteredValues = values.filter((value: string): boolean => value !== config.UNDEFINED_ATTRIBUTE_VALUE);
filteredValues.slice(0, 10).forEach((value: string, index: number): void => {
const key = `SET_${index}_VALUE`;
keyMap[key] = {

@ -21,7 +21,7 @@ import {
ReloadOutlined,
} from '@ant-design/icons';
import consts from 'consts';
import config from 'config';
import { DimensionType, CombinedState } from 'reducers';
import CanvasWrapperComponent from 'components/annotation-page/canvas/views/canvas2d/canvas-wrapper';
import CanvasWrapper3DComponent, {
@ -72,7 +72,7 @@ const fitLayout = (type: DimensionType, layoutConfig: ItemLayout[]): ItemLayout[
const relatedViews = layoutConfig
.filter((item: ItemLayout) => item.viewType === ViewType.RELATED_IMAGE);
const relatedViewsCols = relatedViews.length > 6 ? 2 : 1;
const height = Math.floor(consts.CANVAS_WORKSPACE_ROWS / (relatedViews.length / relatedViewsCols));
const height = Math.floor(config.CANVAS_WORKSPACE_ROWS / (relatedViews.length / relatedViewsCols));
relatedViews.forEach((view: ItemLayout, i: number) => {
updatedLayout.push({
...view,
@ -83,7 +83,7 @@ const fitLayout = (type: DimensionType, layoutConfig: ItemLayout[]): ItemLayout[
});
});
let widthAvail = consts.CANVAS_WORKSPACE_COLS;
let widthAvail = config.CANVAS_WORKSPACE_COLS;
if (updatedLayout.length > 0) {
widthAvail -= updatedLayout[0].w * relatedViewsCols;
}
@ -96,7 +96,7 @@ const fitLayout = (type: DimensionType, layoutConfig: ItemLayout[]): ItemLayout[
x: 0,
y: 0,
w: widthAvail,
h: consts.CANVAS_WORKSPACE_ROWS,
h: config.CANVAS_WORKSPACE_ROWS,
});
} else {
const canvas = layoutConfig
@ -113,25 +113,25 @@ const fitLayout = (type: DimensionType, layoutConfig: ItemLayout[]): ItemLayout[
x: 0,
y: 0,
w: widthAvail,
h: consts.CANVAS_WORKSPACE_ROWS - helpfulCanvasViewHeight,
h: config.CANVAS_WORKSPACE_ROWS - helpfulCanvasViewHeight,
}, {
...top,
x: 0,
y: consts.CANVAS_WORKSPACE_ROWS,
y: config.CANVAS_WORKSPACE_ROWS,
w: Math.ceil(widthAvail / 3),
h: helpfulCanvasViewHeight,
},
{
...side,
x: Math.ceil(widthAvail / 3),
y: consts.CANVAS_WORKSPACE_ROWS,
y: config.CANVAS_WORKSPACE_ROWS,
w: Math.ceil(widthAvail / 3),
h: helpfulCanvasViewHeight,
},
{
...front,
x: Math.ceil(widthAvail / 3) * 2,
y: consts.CANVAS_WORKSPACE_ROWS,
y: config.CANVAS_WORKSPACE_ROWS,
w: Math.floor(widthAvail / 3),
h: helpfulCanvasViewHeight,
});
@ -152,8 +152,8 @@ function CanvasLayout({ type }: { type?: DimensionType }): JSX.Element {
containerHeight = window.innerHeight - container.getBoundingClientRect().bottom;
// https://github.com/react-grid-layout/react-grid-layout/issues/628#issuecomment-1228453084
return Math.floor(
(containerHeight - consts.CANVAS_WORKSPACE_MARGIN * (consts.CANVAS_WORKSPACE_ROWS)) /
consts.CANVAS_WORKSPACE_ROWS,
(containerHeight - config.CANVAS_WORKSPACE_MARGIN * (config.CANVAS_WORKSPACE_ROWS)) /
config.CANVAS_WORKSPACE_ROWS,
);
}
@ -214,11 +214,11 @@ function CanvasLayout({ type }: { type?: DimensionType }): JSX.Element {
<Layout.Content>
{ !!rowHeight && (
<ReactGridLayout
cols={consts.CANVAS_WORKSPACE_COLS}
maxRows={consts.CANVAS_WORKSPACE_ROWS}
cols={config.CANVAS_WORKSPACE_COLS}
maxRows={config.CANVAS_WORKSPACE_ROWS}
style={{ background: canvasBackgroundColor }}
containerPadding={[consts.CANVAS_WORKSPACE_PADDING, consts.CANVAS_WORKSPACE_PADDING]}
margin={[consts.CANVAS_WORKSPACE_MARGIN, consts.CANVAS_WORKSPACE_MARGIN]}
containerPadding={[config.CANVAS_WORKSPACE_PADDING, config.CANVAS_WORKSPACE_PADDING]}
margin={[config.CANVAS_WORKSPACE_MARGIN, config.CANVAS_WORKSPACE_MARGIN]}
className='cvat-canvas-grid-root'
rowHeight={rowHeight}
layout={layout}

@ -13,7 +13,7 @@ import ObjectItemElementComponent from 'components/annotation-page/standard-work
import ObjectItemContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/object-item';
import { ShapeType, Workspace } from 'reducers';
import { rotatePoint } from 'utils/math';
import consts from 'consts';
import config from 'config';
interface Props {
readonly: boolean;
@ -141,9 +141,9 @@ export default function CanvasContextMenu(props: Props): JSX.Element | null {
if (param.key === ReviewContextMenuKeys.OPEN_ISSUE) {
onStartIssue(points);
} else if (param.key === ReviewContextMenuKeys.QUICK_ISSUE_POSITION) {
openIssue(points, consts.QUICK_ISSUE_INCORRECT_POSITION_TEXT);
openIssue(points, config.QUICK_ISSUE_INCORRECT_POSITION_TEXT);
} else if (param.key === ReviewContextMenuKeys.QUICK_ISSUE_ATTRIBUTE) {
openIssue(points, consts.QUICK_ISSUE_INCORRECT_ATTRIBUTE_TEXT);
openIssue(points, config.QUICK_ISSUE_INCORRECT_ATTRIBUTE_TEXT);
} else if (
param.keyPath.length === 2 &&
param.keyPath[1] === ReviewContextMenuKeys.QUICK_ISSUE_FROM_LATEST

@ -18,7 +18,7 @@ import { LogType } from 'cvat-logger';
import { Canvas } from 'cvat-canvas-wrapper';
import { Canvas3d } from 'cvat-canvas3d-wrapper';
import { getCore } from 'cvat-core-wrapper';
import consts from 'consts';
import config from 'config';
import CVATTooltip from 'components/common/cvat-tooltip';
import FrameTags from 'components/annotation-page/tag-annotation-workspace/frame-tags';
import {
@ -369,7 +369,7 @@ class CanvasWrapperComponent extends React.PureComponent<Props> {
canvasInstance.configure({
forceDisableEditing: workspace === Workspace.REVIEW_WORKSPACE,
undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE,
undefinedAttrValue: config.UNDEFINED_ATTRIBUTE_VALUE,
displayAllText: showObjectsTextAlways,
autoborders: automaticBordering,
showProjections,
@ -442,7 +442,7 @@ class CanvasWrapperComponent extends React.PureComponent<Props> {
prevProps.outlined !== outlined
) {
canvasInstance.configure({
undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE,
undefinedAttrValue: config.UNDEFINED_ATTRIBUTE_VALUE,
displayAllText: showObjectsTextAlways,
autoborders: automaticBordering,
showProjections,

@ -11,7 +11,7 @@ import Input from 'antd/lib/input';
import InputNumber from 'antd/lib/input-number';
import Text from 'antd/lib/typography/Text';
import consts from 'consts';
import config from 'config';
import { clamp } from 'utils/math';
interface Props {
@ -84,7 +84,7 @@ function ItemAttributeComponent(props: Props): JSX.Element {
{attrValues.map(
(value: string): JSX.Element => (
<Radio key={value} value={value}>
{value === consts.UNDEFINED_ATTRIBUTE_VALUE ? consts.NO_BREAK_SPACE : value}
{value === config.UNDEFINED_ATTRIBUTE_VALUE ? config.NO_BREAK_SPACE : value}
</Radio>
),
)}
@ -113,7 +113,7 @@ function ItemAttributeComponent(props: Props): JSX.Element {
{attrValues.map(
(value: string): JSX.Element => (
<Select.Option key={value} value={value}>
{value === consts.UNDEFINED_ATTRIBUTE_VALUE ? consts.NO_BREAK_SPACE : value}
{value === config.UNDEFINED_ATTRIBUTE_VALUE ? config.NO_BREAK_SPACE : value}
</Select.Option>
),
)}

@ -9,7 +9,7 @@ import { CombinedState, ObjectType } from 'reducers';
import Text from 'antd/lib/typography/Text';
import Modal from 'antd/lib/modal';
import consts from 'consts';
import config from 'config';
import { removeObjectAsync, removeObject as removeObjectAction } from 'actions/annotation-actions';
export default function RemoveConfirmComponent(): JSX.Element | null {
@ -48,7 +48,7 @@ export default function RemoveConfirmComponent(): JSX.Element | null {
</Text>
<div className='cvat-remove-object-confirm-wrapper'>
{/* eslint-disable-next-line */}
<img src={consts.OUTSIDE_PIC_URL} />
<img src={config.OUTSIDE_PIC_URL} />
</div>
</>
);

@ -1,9 +1,11 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import config from 'config';
import Location from './location';
import consts from '../../consts';
interface Props {
selectedRegion: any;
@ -22,7 +24,7 @@ export default function GCSLocation(props: Props): JSX.Element {
selectedRegion={selectedRegion}
onSelectRegion={onSelectRegion}
internalCommonProps={internalCommonProps}
values={consts.DEFAULT_GOOGLE_CLOUD_STORAGE_LOCATIONS}
values={config.DEFAULT_GOOGLE_CLOUD_STORAGE_LOCATIONS}
name='location'
label='Location'
href='https://cloud.google.com/storage/docs/locations#available-locations'

@ -12,7 +12,7 @@ import Input from 'antd/lib/input';
import Row from 'antd/lib/row';
import notification from 'antd/lib/notification';
import Tooltip from 'antd/lib/tooltip';
import consts from 'consts';
import config from 'config';
interface Props {
form: any;
@ -24,7 +24,7 @@ export default function ManifestsManager(props: Props): JSX.Element {
const { form, manifestNames, setManifestNames } = props;
const maxManifestsCount = useRef(5);
const [limitingAddingManifestNotification, setLimitingAddingManifestNotification] = useState(false);
const { DATASET_MANIFEST_GUIDE_URL } = consts;
const { DATASET_MANIFEST_GUIDE_URL } = config;
const updateManifestFields = (): void => {
const newManifestFormItems = manifestNames.map((name, idx) => ({

@ -1,9 +1,11 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import config from 'config';
import Location from './location';
import consts from '../../consts';
interface Props {
selectedRegion: any;
@ -22,7 +24,7 @@ export default function S3Region(props: Props): JSX.Element {
selectedRegion={selectedRegion}
onSelectRegion={onSelectRegion}
internalCommonProps={internalCommonProps}
values={consts.DEFAULT_AWS_S3_REGIONS}
values={config.DEFAULT_AWS_S3_REGIONS}
name='region'
label='Region'
href='https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions'

@ -5,7 +5,7 @@
import React, { useEffect, useState } from 'react';
import Autocomplete from 'antd/lib/auto-complete';
import consts from 'consts';
import config from 'config';
import { getCore } from 'cvat-core-wrapper';
const core = getCore();
@ -38,7 +38,7 @@ export default function ProjectSubsetField(props: Props): JSX.Element {
setInternalSubsets(
new Set([
...(internalValue ? [internalValue] : []),
...consts.DEFAULT_PROJECT_SUBSETS,
...config.DEFAULT_PROJECT_SUBSETS,
...project.subsets,
]),
);
@ -48,7 +48,7 @@ export default function ProjectSubsetField(props: Props): JSX.Element {
setInternalSubsets(
new Set([
...(internalValue ? [internalValue] : []),
...consts.DEFAULT_PROJECT_SUBSETS,
...config.DEFAULT_PROJECT_SUBSETS,
...(projectSubsets || []),
]),
);

@ -68,7 +68,7 @@ import showPlatformNotification, {
showUnsupportedNotification,
} from 'utils/platform-checker';
import '../styles.scss';
import consts from 'consts';
import appConfig from 'config';
import EmailConfirmationPage from './email-confirmation-pages/email-confirmed';
import EmailVerificationSentPage from './email-confirmation-pages/email-verification-sent';
import IncorrectEmailConfirmationPage from './email-confirmation-pages/incorrect-email-confirmation';
@ -140,10 +140,10 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
});
const {
HEALH_CHECK_RETRIES, HEALTH_CHECK_PERIOD, HEALTH_CHECK_REQUEST_TIMEOUT, UPGRADE_GUIDE_URL,
} = consts;
HEALTH_CHECK_RETRIES, HEALTH_CHECK_PERIOD, HEALTH_CHECK_REQUEST_TIMEOUT, SERVER_UNAVAILABLE_COMPONENT,
} = appConfig;
core.server.healthCheck(
HEALH_CHECK_RETRIES,
HEALTH_CHECK_RETRIES,
HEALTH_CHECK_PERIOD,
HEALTH_CHECK_REQUEST_TIMEOUT,
).then(() => {
@ -157,26 +157,15 @@ class CVATApplication extends React.PureComponent<CVATAppProps & RouteComponentP
healthIinitialized: true,
backendIsHealthy: false,
});
Modal.error({
title: 'Cannot connect to the server',
className: 'cvat-modal-cannot-connect-server',
closable: false,
content: (
content:
<Text>
Make sure the CVAT backend and all necessary services
(Database, Redis and Open Policy Agent) are running and avaliable.
If you upgraded from version 2.2.0 or earlier, manual actions may be needed, see the&nbsp;
<a
target='_blank'
rel='noopener noreferrer'
href={UPGRADE_GUIDE_URL}
>
Upgrade Guide
</a>
.
</Text>
),
{SERVER_UNAVAILABLE_COMPONENT}
</Text>,
});
});

@ -30,10 +30,10 @@ import {
LinkedinIcon,
} from 'react-share';
import consts from 'consts';
import config from 'config';
function renderContent(): JSX.Element {
const { GITHUB_URL, GITHUB_IMAGE_URL, DISCORD_URL } = consts;
const { GITHUB_URL, GITHUB_IMAGE_URL, DISCORD_URL } = config;
return (
<>

@ -17,7 +17,7 @@ import { FormInstance } from 'antd/lib/form';
// eslint-disable-next-line import/no-extraneous-dependencies
import { EventDataNode } from 'rc-tree/lib/interface';
import consts from 'consts';
import config from 'config';
import { CloudStorage } from 'reducers';
import CloudStorageTab from './cloud-storages-tab';
import LocalFiles from './local-files';
@ -155,7 +155,7 @@ export class FileManager extends React.PureComponent<Props, State> {
}));
}
const { SHARE_MOUNT_GUIDE_URL } = consts;
const { SHARE_MOUNT_GUIDE_URL } = config;
const { treeData, onUploadShareFiles, onLoadData } = this.props;
const { expandedKeys, files } = this.state;

@ -18,7 +18,7 @@ import { resetAfterErrorAsync } from 'actions/boundaries-actions';
import { CombinedState } from 'reducers';
import logger, { LogType } from 'cvat-logger';
import CVATTooltip from 'components/common/cvat-tooltip';
import consts from 'consts';
import config from 'config';
interface OwnProps {
children: JSX.Element;
@ -166,7 +166,7 @@ class GlobalErrorBoundary extends React.PureComponent<Props, State> {
</li>
<li>
Notify an administrator or submit the issue directly on
<a href={consts.GITHUB_URL}> GitHub. </a>
<a href={config.GITHUB_URL}> GitHub. </a>
Please, provide also:
<ul>
<li>Steps to reproduce the issue</li>

@ -31,7 +31,7 @@ import Text from 'antd/lib/typography/Text';
import Select from 'antd/lib/select';
import { getCore } from 'cvat-core-wrapper';
import consts from 'consts';
import config from 'config';
import { CVATLogo } from 'icons';
import ChangePasswordDialog from 'components/change-password-modal/change-password-modal';
@ -164,7 +164,7 @@ function HeaderContainer(props: Props): JSX.Element {
const {
CHANGELOG_URL, LICENSE_URL, GITTER_URL, GITHUB_URL, GUIDE_URL, DISCORD_URL,
} = consts;
} = config;
const history = useHistory();
const location = useLocation();

@ -17,7 +17,7 @@ import { CompactPicker } from 'react-color';
import { clamp } from 'utils/math';
import { BackJumpIcon, ForwardJumpIcon } from 'icons';
import { FrameSpeed } from 'reducers';
import consts from 'consts';
import config from 'config';
interface Props {
frameStep: number;
@ -134,7 +134,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
<Popover
content={(
<CompactPicker
colors={consts.CANVAS_BACKGROUND_COLORS}
colors={config.CANVAS_BACKGROUND_COLORS}
color={canvasBackgroundColor}
onChange={(e) => onChangeCanvasBackgroundColor(e.hex)}
/>

@ -7,7 +7,7 @@ import { DeleteOutlined, EditOutlined } from '@ant-design/icons';
import Text from 'antd/lib/typography/Text';
import CVATTooltip from 'components/common/cvat-tooltip';
import consts from 'consts';
import config from 'config';
import { LabelOptColor } from './common';
interface ConstructorViewerItemProps {
@ -22,7 +22,7 @@ export default function ConstructorViewerItem(props: ConstructorViewerItemProps)
color, label, onUpdate, onDelete,
} = props;
const backgroundColor = color || consts.NEW_LABEL_COLOR;
const backgroundColor = color || config.NEW_LABEL_COLOR;
let textColor = '#ffffff';
try {
// convert color to grayscale and from the result get better text color

@ -19,7 +19,7 @@ import CVATTooltip from 'components/common/cvat-tooltip';
import ColorPicker from 'components/annotation-page/standard-workspace/objects-side-bar/color-picker';
import { ColorizeIcon } from 'icons';
import patterns from 'utils/validation-patterns';
import consts from 'consts';
import config from 'config';
import {
equalArrayHead, idGenerator, LabelOptColor, SkeletonConfiguration,
} from './common';
@ -544,7 +544,7 @@ export default class LabelForm extends React.Component<Props> {
<Button type='default' className='cvat-change-task-label-color-button'>
<Badge
className='cvat-change-task-label-color-badge'
color={this.formRef.current?.getFieldValue('color') || consts.NEW_LABEL_COLOR}
color={this.formRef.current?.getFieldValue('color') || config.NEW_LABEL_COLOR}
text={<Icon component={ColorizeIcon} />}
/>
</Button>

@ -16,7 +16,7 @@ import GlobalHotKeys from 'utils/mousetrap-react';
import CVATTooltip from 'components/common/cvat-tooltip';
import ShortcutsContext from 'components/shortcuts.context';
import { ShapeType } from 'cvat-core-wrapper';
import consts from 'consts';
import config from 'config';
import {
idGenerator, LabelOptColor, SkeletonConfiguration, toSVGCoord,
} from './common';
@ -429,7 +429,7 @@ export default class SkeletonConfigurator extends React.PureComponent<Props, Sta
setAttributes(circle, {
r: 1.5,
stroke: 'black',
fill: consts.NEW_LABEL_COLOR,
fill: config.NEW_LABEL_COLOR,
cx: x,
cy: y,
'stroke-width': 0.1,

@ -19,7 +19,7 @@ import { Model, ModelAttribute, StringObject } from 'reducers';
import CVATTooltip from 'components/common/cvat-tooltip';
import { Label as LabelInterface } from 'components/labels-editor/common';
import { clamp } from 'utils/math';
import consts from 'consts';
import config from 'config';
import { DimensionType } from '../../reducers';
interface Props {
@ -265,7 +265,7 @@ function DetectorRunner(props: Props): JSX.Element {
.find((_label: LabelInterface): boolean => (
_label.name === mapping[modelLabel].name)) as LabelInterface;
const color = label ? label.color : consts.NEW_LABEL_COLOR;
const color = label ? label.color : config.NEW_LABEL_COLOR;
const notMatchedModelAttributes = model.attributes[modelLabel]
.filter((_attribute: ModelAttribute): boolean => (
!(_attribute.name in (mapping[modelLabel].attributes || {}))
@ -292,7 +292,7 @@ function DetectorRunner(props: Props): JSX.Element {
Object.keys(mapping[modelLabel].attributes || {})
.map((mappedModelAttr: string) => (
renderMappingRow(
consts.NEW_LABEL_COLOR,
config.NEW_LABEL_COLOR,
mappedModelAttr,
mapping[modelLabel].attributes[mappedModelAttr],
'Remove the mapped attribute',

@ -7,7 +7,7 @@ import Text from 'antd/lib/typography/Text';
import { Row, Col } from 'antd/lib/grid';
import Empty from 'antd/lib/empty';
import consts from 'consts';
import config from 'config';
export default function EmptyListComponent(): JSX.Element {
return (
@ -28,7 +28,7 @@ export default function EmptyListComponent(): JSX.Element {
<Row justify='center' align='middle'>
<Col>
<Text type='secondary'>deploy a model with </Text>
<a href={`${consts.NUCLIO_GUIDE}`}>nuclio</a>
<a href={`${config.NUCLIO_GUIDE}`}>nuclio</a>
</Col>
</Row>
</div>

@ -1,8 +1,10 @@
// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corp
// Copyright (C) 2022-2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
const UNDEFINED_ATTRIBUTE_VALUE = '__undefined__';
const NO_BREAK_SPACE = '\u00a0';
const CHANGELOG_URL = 'https://github.com/opencv/cvat/blob/develop/CHANGELOG.md';
@ -49,6 +51,23 @@ const DEFAULT_AWS_S3_REGIONS: string[][] = [
['sa-east-1', 'South America (São Paulo)'],
];
const SERVER_UNAVAILABLE_COMPONENT = (
<>
Make sure the CVAT backend and all necessary services
(Database, Redis and Open Policy Agent) are running and avaliable.
If you upgraded from version 2.2.0 or earlier, manual actions may be needed,
see the&nbsp;
<a
target='_blank'
rel='noopener noreferrer'
href={UPGRADE_GUIDE_URL}
>
Upgrade Guide
</a>
.
</>
);
const DEFAULT_GOOGLE_CLOUD_STORAGE_LOCATIONS: string[][] = [
['NORTHAMERICA-NORTHEAST1', 'Montréal'],
['NORTHAMERICA-NORTHEAST2', 'Toronto'],
@ -88,7 +107,7 @@ const DEFAULT_GOOGLE_CLOUD_STORAGE_LOCATIONS: string[][] = [
['NAM4', 'US-CENTRAL1 and US-EAST1'],
];
const HEALH_CHECK_RETRIES = 10;
const HEALTH_CHECK_RETRIES = 10;
const HEALTH_CHECK_PERIOD = 3000; // ms
const HEALTH_CHECK_REQUEST_TIMEOUT = 5000; // ms
@ -115,9 +134,10 @@ export default {
DEFAULT_GOOGLE_CLOUD_STORAGE_LOCATIONS,
OUTSIDE_PIC_URL,
DATASET_MANIFEST_GUIDE_URL,
HEALH_CHECK_RETRIES,
HEALTH_CHECK_RETRIES,
HEALTH_CHECK_PERIOD,
HEALTH_CHECK_REQUEST_TIMEOUT,
SERVER_UNAVAILABLE_COMPONENT,
CANVAS_WORKSPACE_ROWS,
CANVAS_WORKSPACE_COLS,
CANVAS_WORKSPACE_MARGIN,

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import consts from 'consts';
import config from 'config';
import { AnnotationActionTypes } from 'actions/annotation-actions';
import { ReviewActionTypes } from 'actions/review-actions';
import { AuthActionTypes } from 'actions/auth-actions';
@ -103,12 +103,12 @@ export default function (state: ReviewState = defaultState, action: any): Review
new Set(
[...state.latestComments, issue.comments[0].message].filter(
(message: string): boolean => ![
consts.QUICK_ISSUE_INCORRECT_POSITION_TEXT,
consts.QUICK_ISSUE_INCORRECT_ATTRIBUTE_TEXT,
config.QUICK_ISSUE_INCORRECT_POSITION_TEXT,
config.QUICK_ISSUE_INCORRECT_ATTRIBUTE_TEXT,
].includes(message),
),
),
).slice(-consts.LATEST_COMMENTS_SHOWN_QUICK_ISSUE),
).slice(-config.LATEST_COMMENTS_SHOWN_QUICK_ISSUE),
frameIssues,
issues,
newIssuePosition: null,

@ -1,4 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2023 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
@ -8,11 +9,17 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = (env) => ({
module.exports = (env) => {
console.log()
const defaultAppConfig = path.join(__dirname, 'src/config.tsx');
const appConfigFile = process.env.UI_APP_CONFIG ? process.env.UI_APP_CONFIG : defaultAppConfig;
console.log('Application config file is: ', appConfigFile);
return {
target: 'web',
mode: 'production',
devtool: 'source-map',
@ -49,10 +56,14 @@ module.exports = (env) => ({
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
plugins: [new TsconfigPathsPlugin({ configFile: './tsconfig.json' })],
fallback: {
fs: false,
},
alias: {
config$: appConfigFile,
},
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
},
module: {
rules: [
@ -157,4 +168,5 @@ module.exports = (env) => ({
],
}),
],
});
}
};

@ -11,7 +11,7 @@ from tempfile import NamedTemporaryFile
import cv2
import pytz
from django.core.cache import cache
from django.core.cache import caches
from django.conf import settings
from rest_framework.exceptions import ValidationError, NotFound
@ -31,14 +31,14 @@ from utils.dataset_manifest import ImageManifestManager
class MediaCache:
def __init__(self, dimension=DimensionType.DIM_2D):
self._dimension = dimension
self._cache = caches['media']
@staticmethod
def _get_or_set_cache_item(key, create_function):
item = cache.get(key)
def _get_or_set_cache_item(self, key, create_function):
item = self._cache.get(key)
if not item:
item = create_function()
if item[0]:
cache.set(key, item)
self._cache.set(key, item)
return item

@ -3,6 +3,7 @@
# SPDX-License-Identifier: MIT
from django.apps import AppConfig
from django.conf import settings
from health_check.plugins import plugin_dir
@ -10,5 +11,8 @@ class HealthConfig(AppConfig):
name = 'cvat.apps.health'
def ready(self):
from .backends import OPAHealthCheck
from .backends import OPAHealthCheck, CustomCacheBackend
plugin_dir.register(OPAHealthCheck)
for backend in settings.CACHES:
plugin_dir.register(CustomCacheBackend, backend=backend)

@ -3,11 +3,14 @@
# SPDX-License-Identifier: MIT
import requests
import sqlite3
from health_check.backends import BaseHealthCheckBackend
from health_check.exceptions import HealthCheckException
from health_check.exceptions import ServiceReturnedUnexpectedResult, ServiceUnavailable
from django.conf import settings
from django.core.cache import CacheKeyWarning, caches
class OPAHealthCheck(BaseHealthCheckBackend):
critical_service = True
@ -22,3 +25,27 @@ class OPAHealthCheck(BaseHealthCheckBackend):
def identifier(self):
return self.__class__.__name__
class CustomCacheBackend(BaseHealthCheckBackend):
def __init__(self, backend="default"):
super().__init__()
self.backend = backend
def identifier(self):
return f"Cache backend: {self.backend}"
def check_status(self):
try:
cache = caches[self.backend]
cache.set("djangohealtcheck_test", "itworks")
if not cache.get("djangohealtcheck_test") == "itworks":
raise ServiceUnavailable("Cache key does not match")
except CacheKeyWarning as e:
self.add_error(ServiceReturnedUnexpectedResult("Cache key warning"), e)
except ValueError as e:
self.add_error(ServiceReturnedUnexpectedResult("ValueError"), e)
except ConnectionError as e:
self.add_error(ServiceReturnedUnexpectedResult("Connection Error"), e)
except sqlite3.DatabaseError as e:
raise ServiceUnavailable("Cache error: {}".format(str(e)))

@ -127,7 +127,6 @@ INSTALLED_APPS = [
'dj_rest_auth.registration',
'health_check',
'health_check.db',
'health_check.cache',
'health_check.contrib.migrations',
'health_check.contrib.psutil',
'cvat.apps.iam',
@ -513,6 +512,9 @@ RESTRICTIONS = {
# http://www.grantjenks.com/docs/diskcache/tutorial.html#djangocache
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
},
'media' : {
'BACKEND' : 'diskcache.DjangoCache',
'LOCATION' : CACHE_ROOT,
'TIMEOUT' : None,

@ -79,7 +79,6 @@
"style-loader": "^1.0.0",
"stylelint": "^13.6.1",
"stylelint-config-standard": "^20.0.0",
"tsconfig-paths-webpack-plugin": "^3.2.0",
"typescript": "^3.7.3",
"vfile-reporter-json": "^2.0.2",
"webpack": "^5.72.1",

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save