diff --git a/changelog.d/20241206_153723_sekachev.bs_fixed_issue.md b/changelog.d/20241206_153723_sekachev.bs_fixed_issue.md new file mode 100644 index 000000000000..badf4b20aac4 --- /dev/null +++ b/changelog.d/20241206_153723_sekachev.bs_fixed_issue.md @@ -0,0 +1,4 @@ +### Fixed + +- Fixed issue: Cannot read properties of undefined (reading 'getUpdated') + () diff --git a/cvat-core/package.json b/cvat-core/package.json index 6b9039673812..8e27f80f0b98 100644 --- a/cvat-core/package.json +++ b/cvat-core/package.json @@ -1,6 +1,6 @@ { "name": "cvat-core", - "version": "15.3.0", + "version": "15.3.1", "type": "module", "description": "Part of Computer Vision Tool which presents an interface for client-side integration", "main": "src/api.ts", diff --git a/cvat-core/src/frames.ts b/cvat-core/src/frames.ts index dfdd35684178..3305edfc5aab 100644 --- a/cvat-core/src/frames.ts +++ b/cvat-core/src/frames.ts @@ -536,41 +536,55 @@ Object.defineProperty(FrameData.prototype.data, 'implementation', { writable: false, }); -export async function getFramesMeta(type: 'job' | 'task', id: number, forceReload = false): Promise { +export function getFramesMeta(type: 'job' | 'task', id: number, forceReload = false): Promise { if (type === 'task') { // we do not cache task meta currently. So, each new call will results to the server request - const result = await serverProxy.frames.getMeta('task', id); - return new FramesMetaData({ - ...result, - deleted_frames: Object.fromEntries(result.deleted_frames.map((_frame) => [_frame, true])), - }); + return serverProxy.frames.getMeta('task', id).then((serialized) => ( + new FramesMetaData({ + ...serialized, + deleted_frames: Object.fromEntries(serialized.deleted_frames.map((_frame) => [_frame, true])), + }) + )); } + if (!(id in frameMetaCache) || forceReload) { - frameMetaCache[id] = serverProxy.frames.getMeta('job', id) - .then((serverMeta) => new FramesMetaData({ - ...serverMeta, - deleted_frames: Object.fromEntries(serverMeta.deleted_frames.map((_frame) => [_frame, true])), - })) - .catch((error) => { + const previousCache = frameMetaCache[id]; + frameMetaCache[id] = new Promise((resolve, reject) => { + serverProxy.frames.getMeta('job', id).then((serialized) => { + const framesMetaData = new FramesMetaData({ + ...serialized, + deleted_frames: Object.fromEntries(serialized.deleted_frames.map((_frame) => [_frame, true])), + }); + resolve(framesMetaData); + }).catch((error: unknown) => { delete frameMetaCache[id]; - throw error; + if (previousCache instanceof Promise) { + frameMetaCache[id] = previousCache; + } + reject(error); }); + }); } + return frameMetaCache[id]; } -async function saveJobMeta(meta: FramesMetaData, jobID: number): Promise { - frameMetaCache[jobID] = serverProxy.frames.saveMeta('job', jobID, { - deleted_frames: Object.keys(meta.deletedFrames).map((frame) => +frame), - }) - .then((serverMeta) => new FramesMetaData({ - ...serverMeta, - deleted_frames: Object.fromEntries(serverMeta.deleted_frames.map((_frame) => [_frame, true])), - })) - .catch((error) => { - delete frameMetaCache[jobID]; - throw error; +function saveJobMeta(meta: FramesMetaData, jobID: number): Promise { + frameMetaCache[jobID] = new Promise((resolve, reject) => { + serverProxy.frames.saveMeta('job', jobID, { + deleted_frames: Object.keys(meta.deletedFrames).map((frame) => +frame), + }).then((serverMeta) => { + const updatedMetaData = new FramesMetaData({ + ...serverMeta, + deleted_frames: Object.fromEntries(serverMeta.deleted_frames.map((_frame) => [_frame, true])), + }); + resolve(updatedMetaData); + }).catch((error) => { + frameMetaCache[jobID] = Promise.resolve(meta); + reject(error); }); + }); + return frameMetaCache[jobID]; } @@ -834,7 +848,7 @@ export async function patchMeta(jobID: number): Promise { const updatedFields = meta.getUpdated(); if (Object.keys(updatedFields).length) { - frameMetaCache[jobID] = saveJobMeta(meta, jobID); + await saveJobMeta(meta, jobID); } const newMeta = await frameMetaCache[jobID]; return newMeta;