Skip to content

Commit

Permalink
Reduced number of requests from client to server (#7446)
Browse files Browse the repository at this point in the history
  • Loading branch information
bsekachev committed Feb 8, 2024
1 parent 22d4e04 commit 9f517d1
Show file tree
Hide file tree
Showing 15 changed files with 254 additions and 176 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Changed

- Reduced number of server requests, made by clients
(<https://github.com/opencv/cvat/pull/7446>)
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": "14.1.0",
"version": "14.1.1",
"type": "module",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "src/api.ts",
Expand Down
90 changes: 48 additions & 42 deletions cvat-core/src/annotations-saver.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -362,56 +362,62 @@ export default class AnnotationsSaver {

const { created, updated, deleted } = this._split(exported);

onUpdate('Updated objects are being saved on the server');
const updatedIndexes = this._extractClientIDs(updated);
let requestBody = { ...updated, version: this.version };
let updatedData = null;
try {
updatedData = await this._update(requestBody);
} catch (error: unknown) {
updatedData = await retryIf504Status(error, requestBody, 'update');
}
if (updated.shapes.length || updated.tags.length || updated.tracks.length) {
onUpdate('Updated objects are being saved on the server');
const updatedIndexes = this._extractClientIDs(updated);
const requestBody = { ...updated, version: this.version };
let updatedData = null;
try {
updatedData = await this._update(requestBody);
} catch (error: unknown) {
updatedData = await retryIf504Status(error, requestBody, 'update');
}

this.version = updatedData.version;
this._updateCreatedObjects(updatedData, updatedIndexes);
for (const type of Object.keys(this.initialObjects)) {
for (const object of updatedData[type]) {
this.initialObjects[type][object.id] = object;
this.version = updatedData.version;
this._updateCreatedObjects(updatedData, updatedIndexes);
for (const type of Object.keys(this.initialObjects)) {
for (const object of updatedData[type]) {
this.initialObjects[type][object.id] = object;
}
}
}

onUpdate('Deleted objects are being deleted from the server');
this._extractClientIDs(deleted);
requestBody = { ...deleted, version: this.version };
let deletedData = null;
try {
deletedData = await this._delete(requestBody);
} catch (error: unknown) {
deletedData = await retryIf504Status(error, requestBody, 'delete');
}
if (deleted.shapes.length || deleted.tags.length || deleted.tracks.length) {
onUpdate('Deleted objects are being deleted from the server');
this._extractClientIDs(deleted);
const requestBody = { ...deleted, version: this.version };
let deletedData = null;
try {
deletedData = await this._delete(requestBody);
} catch (error: unknown) {
deletedData = await retryIf504Status(error, requestBody, 'delete');
}

this.version = deletedData.version;
for (const type of Object.keys(this.initialObjects)) {
for (const object of deletedData[type]) {
delete this.initialObjects[type][object.id];
this.version = deletedData.version;
for (const type of Object.keys(this.initialObjects)) {
for (const object of deletedData[type]) {
delete this.initialObjects[type][object.id];
}
}
}

onUpdate('Created objects are being saved on the server');
const createdIndexes = this._extractClientIDs(created);
requestBody = { ...created, version: this.version };
let createdData = null;
try {
createdData = await this._create(requestBody);
} catch (error: unknown) {
createdData = await retryIf504Status(error, requestBody, 'create');
}
if (created.shapes.length || created.tags.length || created.tracks.length) {
onUpdate('Created objects are being saved on the server');
const createdIndexes = this._extractClientIDs(created);
const requestBody = { ...created, version: this.version };
let createdData = null;
try {
createdData = await this._create(requestBody);
} catch (error: unknown) {
createdData = await retryIf504Status(error, requestBody, 'create');
}

this.version = createdData.version;
this._updateCreatedObjects(createdData, createdIndexes);
for (const type of Object.keys(this.initialObjects)) {
for (const object of createdData[type]) {
this.initialObjects[type][object.id] = object;
this.version = createdData.version;
this._updateCreatedObjects(createdData, createdIndexes);
for (const type of Object.keys(this.initialObjects)) {
for (const object of createdData[type]) {
this.initialObjects[type][object.id] = object;
}
}
}
}
Expand Down
23 changes: 10 additions & 13 deletions cvat-core/src/logger-storage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -169,15 +169,6 @@ Object.defineProperties(LoggerStorage.prototype.log, {
}
};

if (log.scope === LogType.exception) {
await serverProxy.events.save({
events: [log.dump()],
timestamp: new Date().toISOString(),
});

return log;
}

if (wait) {
log.onClose(pushEvent);
} else {
Expand All @@ -199,10 +190,9 @@ Object.defineProperties(LoggerStorage.prototype.save, {
}

while (this.saving) {
await sleep(100);
await sleep(1000);
}

const collectionToSend = [...this.collection];
const logPayload: any = {
client_id: this.clientID,
};
Expand All @@ -211,16 +201,23 @@ Object.defineProperties(LoggerStorage.prototype.save, {
logPayload.is_active = this.isActiveChecker();
}

const collectionToSend = [...this.collection];
try {
this.saving = true;
this.collection = [];
await serverProxy.events.save({
events: collectionToSend.map((log) => log.dump()),
timestamp: new Date().toISOString(),
});

for (const rule of Object.values<IgnoreRule>(this.ignoreRules)) {
rule.lastLog = null;
}
this.collection = [];
} catch (error: unknown) {
// if failed, put collection back
// potentially new events may be generated during saving
// that is why we add this.collection
this.collection = [...collectionToSend, ...this.collection];
} finally {
this.saving = false;
}
Expand Down
19 changes: 7 additions & 12 deletions cvat-core/src/session-implementation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -23,7 +23,6 @@ import {
decodePreview,
} from './frames';
import Issue from './issue';
import { Label } from './labels';
import { SerializedLabel, SerializedTask } from './server-response-types';
import { checkObjectType } from './common';
import {
Expand Down Expand Up @@ -421,19 +420,15 @@ export function implementTask(Task) {
taskData.assignee_id = taskData.assignee_id.id;
}

await Promise.all((taskData.labels || []).map((label: Label): Promise<unknown> => {
for await (const label of taskData.labels || []) {
if (label.deleted) {
return serverProxy.labels.delete(label.id);
await serverProxy.labels.delete(label.id);
} else if (label.patched) {
await serverProxy.labels.update(label.id, label.toJSON());
}
}

if (label.patched) {
return serverProxy.labels.update(label.id, label.toJSON());
}

return Promise.resolve();
}));

// leave only new labels to create them via project PATCH request
// leave only new labels to create them via task PATCH request
taskData.labels = (taskData.labels || [])
.filter((label: SerializedLabel) => !Number.isInteger(label.id)).map((el) => el.toJSON());
if (!taskData.labels.length) {
Expand Down
17 changes: 9 additions & 8 deletions cvat-core/tests/api/tasks.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -254,17 +254,18 @@ describe('Feature: delete a task', () => {

describe('Feature: delete a label', () => {
test('delete a label', async () => {
let result = await cvat.tasks.get({
const [task] = await cvat.tasks.get({
id: 100,
});

const labelsLength = result[0].labels.length;
const deletedLabels = result[0].labels.filter((el) => el.name !== 'person');
result[0].labels = deletedLabels;
result[0].save();
result = await cvat.tasks.get({
const labelsLength = task.labels.length;
const deletedLabels = task.labels.filter((el) => el.name !== 'person');
task.labels = deletedLabels;
const updatedTask = await task.save();
const [newlyRequestTask] = await cvat.tasks.get({
id: 100,
});
expect(result[0].labels).toHaveLength(labelsLength - 1);
expect(updatedTask.labels).toHaveLength(labelsLength - 1);
expect(newlyRequestTask.labels).toHaveLength(labelsLength - 1);
});
});
Loading

0 comments on commit 9f517d1

Please sign in to comment.