[bug] Skip storing forgotten file and show error if callbackUrl is empty

This commit is contained in:
Sergey Konovalov
2025-06-15 16:58:04 +03:00
parent 67ba755e11
commit a792372686
4 changed files with 40 additions and 8 deletions

View File

@ -53,6 +53,8 @@ Context.prototype.init = function(tenant, docId, userId, opt_shardKey, opt_WopiS
this.config = null;
this.secret = null;
this.license = null;
//cache
this.taskResultCache = null;
};
Context.prototype.initDefault = function() {
this.init(tenantManager.getDefautTenant(), constants.DEFAULT_DOC_ID, constants.DEFAULT_USER_ID, undefined);

View File

@ -962,9 +962,21 @@ async function applyForceSaveCache(ctx, docId, forceSave, type, opt_userConnecti
res.notModified = true;
}
} else if (!forceSave.started) {
res.startedForceSave = await editorData.checkAndStartForceSave(ctx, docId);
res.ok = !!res.startedForceSave;
return res;
const isTypeToSendFile = commonDefines.c_oAscForceSaveTypes.Command === type ||
commonDefines.c_oAscForceSaveTypes.Button === type ||
commonDefines.c_oAscForceSaveTypes.Timeout === type ||
commonDefines.c_oAscForceSaveTypes.Form === type;
if (isTypeToSendFile) {
const selectRes = await taskResult.selectWithCache(ctx, docId);
if (selectRes.length > 0 && !selectRes[0].callback) {
ctx.logger.debug('applyForceSaveCache empty callback: %s', docId);
res.notModified = true;
return res;
}
}
res.startedForceSave = await editorData.checkAndStartForceSave(ctx, docId);
res.ok = !!res.startedForceSave;
return res;
} else if (commonDefines.c_oAscForceSaveTypes.Form === type || commonDefines.c_oAscForceSaveTypes.Internal === type) {
res.ok = true;
res.inProgress = true;
@ -1407,13 +1419,13 @@ function* cleanDocumentOnExit(ctx, docId, deleteChanges, opt_userIndex) {
}
yield unlockWopiDoc(ctx, docId, opt_userIndex);
}
function* cleanDocumentOnExitNoChanges(ctx, docId, opt_userId, opt_userIndex, opt_forceClose) {
function* cleanDocumentOnExitNoChanges(ctx, docId, opt_userId, opt_userIndex, opt_forceClose, opt_deleteChanges) {
var userAction = opt_userId ? new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, opt_userId) : null;
// We send that everyone is gone and there are no changes (to set the status on the server about the end of editing)
yield sendStatusDocument(ctx, docId, c_oAscChangeBase.No, userAction, opt_userIndex, undefined, undefined, undefined, opt_forceClose);
//if the user entered the document, the connection was broken, all information was deleted on the server,
//when the connection is restored, the userIndex will be saved and it will match the userIndex of the next user
yield* cleanDocumentOnExit(ctx, docId, false, opt_userIndex);
yield* cleanDocumentOnExit(ctx, docId, opt_deleteChanges || false, opt_userIndex);
}
function createSaveTimer(ctx, docId, opt_userId, opt_userIndex, opt_userLcid, opt_queue, opt_noDelay, opt_initShardKey) {

View File

@ -651,7 +651,7 @@ function* commandSendMailMerge(ctx, cmd, outputData) {
}
}
let commandSfctByCmd = co.wrap(function*(ctx, cmd, opt_priority, opt_expiration, opt_queue, opt_initShardKey) {
var selectRes = yield taskResult.select(ctx, cmd.getDocId());
var selectRes = yield taskResult.selectWithCache(ctx, cmd.getDocId());
var row = selectRes.length > 0 ? selectRes[0] : null;
if (!row) {
return false;
@ -1807,7 +1807,7 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
//we do a select, because during the timeout the information could change
var selectRes = yield taskResult.select(ctx, docId);
var row = selectRes.length > 0 ? selectRes[0] : null;
if (row && row.status == commonDefines.FileStatus.SaveVersion && row.status_info == statusInfo) {
if (row && row.status == commonDefines.FileStatus.SaveVersion && row.status_info == statusInfo && row.callback) {
if (null == optFormat) {
optFormat = changeFormatByOrigin(ctx, row, constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
}
@ -1837,6 +1837,10 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
yield docsCoServer.editorStat.addShutdown(redisKeyShutdown, docId);
}
ctx.logger.debug('AddTask saveFromChanges');
} else if(row && !row.callback) {
ctx.logger.debug('saveFromChanges empty callback: %s', docId);
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(ctx, docId, opt_userId, opt_userIndex, false, true);
//todo restore status
} else {
if (row) {
ctx.logger.debug('saveFromChanges status mismatch: row: %d; %d; expected: %d', row.status, row.status_info, statusInfo);

View File

@ -98,7 +98,20 @@ TaskResultData.prototype.completeDefaults = function() {
function upsert(ctx, task) {
return sqlBase.upsert(ctx, task);
}
/**
* Return TaskResult rows for docId, caching the last query result on ctx.taskResultCache or fetching from the database.
* @param {object} ctx
* @param {string} docId
* @returns {Promise<Array<object>>}
*/
async function selectWithCache(ctx, docId) {
//todo merge with select and remove on update
if (ctx.taskResultCache && ctx.taskResultCache[0].id === docId) {
return ctx.taskResultCache;
}
ctx.taskResultCache = await select(ctx, docId);
return ctx.taskResultCache;
}
function select(ctx, docId) {
return new Promise(function(resolve, reject) {
let values = [];
@ -316,6 +329,7 @@ function removeIf(ctx, mask) {
exports.TaskResultData = TaskResultData;
exports.upsert = upsert;
exports.select = select;
exports.selectWithCache = selectWithCache;
exports.update = update;
exports.updateIf = updateIf;
exports.restoreInitialPassword = restoreInitialPassword;