Skip to content

Commit

Permalink
Reduce the number of requests for task details (cvat-ai#7167)
Browse files Browse the repository at this point in the history
  • Loading branch information
Marishka17 committed Nov 29, 2023
1 parent 946fb90 commit cc10cb9
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 97 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Reduce the number of requests to the server for task details
(<https://github.com/opencv/cvat/pull/7167>)
2 changes: 1 addition & 1 deletion cvat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-core",
"version": "12.1.0",
"version": "12.1.1",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
"scripts": {
Expand Down
10 changes: 8 additions & 2 deletions cvat-core/src/api-implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ export default function implementAPI(cvat) {
sort: isString,
search: isString,
jobID: isInteger,
taskID: isInteger,
type: isString,
});

checkExclusiveFields(query, ['jobID', 'filter', 'search'], ['page', 'sort']);
Expand All @@ -198,12 +200,16 @@ export default function implementAPI(cvat) {
return [];
}

const searchParams = {};
const searchParams: Record<string, string> = {};

for (const key of Object.keys(query)) {
if (['page', 'sort', 'search', 'filter', 'task_id'].includes(key)) {
if (['page', 'sort', 'search', 'filter', 'type'].includes(key)) {
searchParams[key] = query[key];
}
}
if ('taskID' in query) {
searchParams.task_id = query.taskID;
}

const jobsData = await serverProxy.jobs.get(searchParams);
const jobs = jobsData.results.map((jobData) => new Job(jobData));
Expand Down
24 changes: 12 additions & 12 deletions cvat-core/src/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ export default class Project {
.map((labelData) => new Label(labelData)).filter((label) => !label.hasParent);
}

data.source_storage = new Storage({
location: initialData.source_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.source_storage?.cloud_storage_id,
});

data.target_storage = new Storage({
location: initialData.target_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.target_storage?.cloud_storage_id,
});

Object.defineProperties(
this,
Object.freeze({
Expand Down Expand Up @@ -173,20 +183,10 @@ export default class Project {
get: () => [...data.task_subsets],
},
sourceStorage: {
get: () => (
new Storage({
location: data.source_storage?.location || StorageLocation.LOCAL,
cloudStorageId: data.source_storage?.cloud_storage_id,
})
),
get: () => data.source_storage,
},
targetStorage: {
get: () => (
new Storage({
location: data.target_storage?.location || StorageLocation.LOCAL,
cloudStorageId: data.target_storage?.cloud_storage_id,
})
),
get: () => data.target_storage,
},
_internalData: {
get: () => data,
Expand Down
19 changes: 14 additions & 5 deletions cvat-core/src/server-response-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import {
ChunkType,
DimensionType, JobStage, JobState, JobType, ProjectStatus,
ShareFileType, TaskMode, TaskStatus,
ShareFileType, TaskMode, TaskStatus, StorageLocation,
} from 'enums';

export interface SerializedAnnotationImporter {
Expand Down Expand Up @@ -46,6 +46,12 @@ export interface SerializedUser {
email_verification_required: boolean;
}

interface SerializedStorage {
id: number;
location: StorageLocation;
cloud_storage_id: number | null;
}

export interface SerializedProject {
assignee: SerializedUser | null;
id: number;
Expand All @@ -57,8 +63,8 @@ export interface SerializedProject {
organization: number | null;
guide_id: number | null;
owner: SerializedUser;
source_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
target_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
source_storage: SerializedStorage | null;
target_storage: SerializedStorage | null;
url: string;
tasks: { count: number; url: string; };
task_subsets: string[];
Expand All @@ -68,6 +74,7 @@ export interface SerializedProject {
export type TasksFilter = ProjectsFilter & { ordering?: string; }; // TODO: Need to clarify how "ordering" is used
export type JobsFilter = ProjectsFilter & {
task_id?: number;
type?: JobType;
};

export interface SerializedTask {
Expand All @@ -92,8 +99,8 @@ export interface SerializedTask {
guide_id: number | null;
segment_size: number;
size: number;
source_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
target_storage: { id: number; location: 'local' | 'cloud'; cloud_storage_id: null };
source_storage: SerializedStorage | null;
target_storage: SerializedStorage | null;
status: TaskStatus;
subset: string;
updated_date: string;
Expand Down Expand Up @@ -122,6 +129,8 @@ export interface SerializedJob {
updated_date: string;
created_date: string;
url: string;
source_storage: SerializedStorage | null;
target_storage: SerializedStorage | null;
}

export type AttrInputType = 'select' | 'radio' | 'checkbox' | 'number' | 'text';
Expand Down
46 changes: 34 additions & 12 deletions cvat-core/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ export class Job extends Session {
public readonly frameSelectionMethod: JobType;
public readonly createdDate: string;
public readonly updatedDate: string;
public readonly sourceStorage: Storage;
public readonly targetStorage: Storage;

public annotations: {
get: CallableFunction;
Expand Down Expand Up @@ -425,6 +427,8 @@ export class Job extends Session {
mode: undefined,
created_date: undefined,
updated_date: undefined,
source_storage: undefined,
target_storage: undefined,
};

const updateTrigger = new FieldUpdateTrigger();
Expand All @@ -450,6 +454,16 @@ export class Job extends Session {
}).filter((label) => !label.hasParent);
}

data.source_storage = new Storage({
location: initialData.source_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.source_storage?.cloud_storage_id,
});

data.target_storage = new Storage({
location: initialData.target_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.target_storage?.cloud_storage_id,
});

Object.defineProperties(
this,
Object.freeze({
Expand Down Expand Up @@ -567,6 +581,12 @@ export class Job extends Session {
updatedDate: {
get: () => data.updated_date,
},
sourceStorage: {
get: () => data.source_storage,
},
targetStorage: {
get: () => data.target_storage,
},
_updateTrigger: {
get: () => updateTrigger,
},
Expand Down Expand Up @@ -816,6 +836,16 @@ export class Task extends Session {
.map((labelData) => new Label(labelData)).filter((label) => !label.hasParent);
}

data.source_storage = new Storage({
location: initialData.source_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.source_storage?.cloud_storage_id,
});

data.target_storage = new Storage({
location: initialData.target_storage?.location || StorageLocation.LOCAL,
cloudStorageId: initialData.target_storage?.cloud_storage_id,
});

if (Array.isArray(initialData.jobs)) {
for (const job of initialData.jobs) {
const jobInstance = new Job({
Expand All @@ -842,6 +872,8 @@ export class Task extends Session {
dimension: data.dimension,
data_compressed_chunk_type: data.data_compressed_chunk_type,
data_chunk_size: data.data_chunk_size,
target_storage: initialData.target_storage,
source_storage: initialData.source_storage,
});
data.jobs.push(jobInstance);
}
Expand Down Expand Up @@ -1086,20 +1118,10 @@ export class Task extends Session {
get: () => data.organization,
},
sourceStorage: {
get: () => (
new Storage({
location: data.source_storage?.location || StorageLocation.LOCAL,
cloudStorageId: data.source_storage?.cloud_storage_id,
})
),
get: () => data.source_storage,
},
targetStorage: {
get: () => (
new Storage({
location: data.target_storage?.location || StorageLocation.LOCAL,
cloudStorageId: data.target_storage?.cloud_storage_id,
})
),
get: () => data.target_storage,
},
progress: {
get: () => data.progress,
Expand Down
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.59.0",
"version": "1.59.1",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
5 changes: 2 additions & 3 deletions cvat-ui/src/actions/annotation-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -912,11 +912,10 @@ export function getJobAsync(
);

const [job] = await cvat.jobs.get({ jobID: jid });
let gtJob = null;
let gtJob: Job | null = null;
if (job.type === JobType.ANNOTATION) {
try {
const [task] = await cvat.tasks.get({ id: tid });
[gtJob] = task.jobs.filter((_job: Job) => _job.type === JobType.GROUND_TRUTH);
[gtJob] = await cvat.jobs.get({ taskID: tid, type: JobType.GROUND_TRUTH });
// gtJob is not available for workers
// eslint-disable-next-line no-empty
} catch (e) { }
Expand Down
4 changes: 2 additions & 2 deletions cvat-ui/src/components/export-backup/export-backup-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ function ExportBackupModal(): JSX.Element {

useEffect(() => {
if (instance) {
setDefaultStorageLocation(instance.targetStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(instance.targetStorage?.cloudStorageId || null);
setDefaultStorageLocation(instance.targetStorage.location);
setDefaultStorageCloudId(instance.targetStorage.cloudStorageId);
}
}, [instance]);

Expand Down
28 changes: 3 additions & 25 deletions cvat-ui/src/components/export-dataset/export-dataset-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,9 @@ import TargetStorageField from 'components/storage/target-storage-field';
import { CombinedState, StorageLocation } from 'reducers';
import { exportActions, exportDatasetAsync } from 'actions/export-actions';
import {
Dumper,
getCore, Job, Project, Storage, StorageData, Task,
Dumper, Job, Project, Storage, StorageData, Task,
} from 'cvat-core-wrapper';

const core = getCore();

type FormValues = {
selectedFormat: string | undefined;
saveImages: boolean;
Expand Down Expand Up @@ -82,27 +79,8 @@ function ExportDatasetModal(props: StateToProps): JSX.Element {

useEffect(() => {
if (instance) {
if (instance instanceof Project || instance instanceof Task) {
setDefaultStorageLocation(instance.targetStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(instance.targetStorage?.cloudStorageId);
} else {
core.tasks.get({ id: instance.taskId })
.then((response: any) => {
if (response.length) {
const [taskInstance] = response;
setDefaultStorageLocation(taskInstance.targetStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(taskInstance.targetStorage?.cloudStorageId);
}
})
.catch((error: Error) => {
if ((error as any).code !== 403) {
Notification.error({
message: `Could not fetch the task ${instance.taskId}`,
description: error.toString(),
});
}
});
}
setDefaultStorageLocation(instance.targetStorage.location);
setDefaultStorageCloudId(instance.targetStorage.cloudStorageId);
}
}, [instance]);

Expand Down
38 changes: 12 additions & 26 deletions cvat-ui/src/components/import-dataset/import-dataset-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,35 +103,21 @@ function ImportDatasetModal(props: StateToProps): JSX.Element {
} as UploadParams);
}, [resource, defaultStorageLocation, defaultStorageCloudId]);

const isProject = useCallback((): boolean => instance instanceof core.classes.Project, [instance]);
const isTask = useCallback((): boolean => instance instanceof core.classes.Task, [instance]);

useEffect(() => {
if (instance) {
if (instance instanceof core.classes.Project || instance instanceof core.classes.Task) {
setDefaultStorageLocation(instance.sourceStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(instance.sourceStorage?.cloudStorageId || null);
if (instance instanceof core.classes.Project) {
setInstanceType(`project #${instance.id}`);
} else {
setInstanceType(`task #${instance.id}`);
}
} else if (instance instanceof core.classes.Job) {
core.tasks.get({ id: instance.taskId })
.then((response: any) => {
if (response.length) {
const [taskInstance] = response;
setDefaultStorageLocation(taskInstance.sourceStorage?.location || StorageLocation.LOCAL);
setDefaultStorageCloudId(taskInstance.sourceStorage?.cloudStorageId || null);
}
})
.catch((error: Error) => {
if ((error as any).code !== 403) {
Notification.error({
message: `Could not get task instance ${instance.taskId}`,
description: error.toString(),
});
}
});
setInstanceType(`job #${instance.id}`);
setDefaultStorageLocation(instance.sourceStorage.location);
setDefaultStorageCloudId(instance.sourceStorage.cloudStorageId);
let type: 'project' | 'task' | 'job' = 'job';

if (isProject()) {
type = 'project';
} else if (isTask()) {
type = 'task';
}
setInstanceType(`${type} #${instance.id}`);
}
}, [instance, resource]);

Expand Down
6 changes: 6 additions & 0 deletions cvat/apps/engine/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,12 @@ class Job(models.Model):
type = models.CharField(max_length=32, choices=JobType.choices(),
default=JobType.ANNOTATION)

def get_target_storage(self) -> Optional[Storage]:
return self.segment.task.target_storage

def get_source_storage(self) -> Optional[Storage]:
return self.segment.task.source_storage

def get_dirname(self):
return os.path.join(settings.JOBS_ROOT, str(self.id))

Expand Down
Loading

0 comments on commit cc10cb9

Please sign in to comment.