mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2026-01-06 03:32:40 +00:00
allowExceedingIndices for our patch applier
Test if it allows patches to go through, and log error if it doesn't match the expected output.
This commit is contained in:
@@ -247,6 +247,9 @@ const EditPage = createClass({
|
|||||||
save : async function(){
|
save : async function(){
|
||||||
if(this.debounceSave && this.debounceSave.cancel) this.debounceSave.cancel();
|
if(this.debounceSave && this.debounceSave.cancel) this.debounceSave.cancel();
|
||||||
|
|
||||||
|
const brewState = this.state.brew; // freeze the current state
|
||||||
|
const preSaveSnapshot = { ...brewState };
|
||||||
|
|
||||||
this.setState((prevState)=>({
|
this.setState((prevState)=>({
|
||||||
isSaving : true,
|
isSaving : true,
|
||||||
error : null,
|
error : null,
|
||||||
@@ -256,12 +259,10 @@ const EditPage = createClass({
|
|||||||
await updateHistory(this.state.brew).catch(console.error);
|
await updateHistory(this.state.brew).catch(console.error);
|
||||||
await versionHistoryGarbageCollection().catch(console.error);
|
await versionHistoryGarbageCollection().catch(console.error);
|
||||||
|
|
||||||
const preSaveSnapshot = { ...this.state.brew };
|
|
||||||
|
|
||||||
//Prepare content to send to server
|
//Prepare content to send to server
|
||||||
const brew = { ...this.state.brew };
|
const brew = { ...brewState };
|
||||||
brew.text = brew.text.normalize();
|
brew.text = brew.text.normalize('NFC');
|
||||||
this.savedBrew.text = this.savedBrew.text.normalize();
|
this.savedBrew.text = this.savedBrew.text.normalize('NFC');
|
||||||
brew.pageCount = ((brew.renderer=='legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1;
|
brew.pageCount = ((brew.renderer=='legacy' ? brew.text.match(/\\page/g) : brew.text.match(/^\\page$/gm)) || []).length + 1;
|
||||||
brew.patches = stringifyPatches(makePatches(this.savedBrew.text, brew.text));
|
brew.patches = stringifyPatches(makePatches(this.savedBrew.text, brew.text));
|
||||||
brew.hash = await md5(this.savedBrew.text);
|
brew.hash = await md5(this.savedBrew.text);
|
||||||
@@ -295,8 +296,8 @@ const EditPage = createClass({
|
|||||||
shareId : res.body.shareId,
|
shareId : res.body.shareId,
|
||||||
version : res.body.version
|
version : res.body.version
|
||||||
},
|
},
|
||||||
isSaving : false,
|
isSaving : false,
|
||||||
unsavedTime : new Date()
|
unsavedTime : new Date()
|
||||||
}), ()=>{
|
}), ()=>{
|
||||||
this.setState({ unsavedChanges : this.hasChanges() });
|
this.setState({ unsavedChanges : this.hasChanges() });
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ const api = {
|
|||||||
// Initialize brew from request and body, destructure query params, and set the initial value for the after-save method
|
// Initialize brew from request and body, destructure query params, and set the initial value for the after-save method
|
||||||
const brewFromClient = api.excludePropsFromUpdate(req.body);
|
const brewFromClient = api.excludePropsFromUpdate(req.body);
|
||||||
const brewFromServer = req.brew;
|
const brewFromServer = req.brew;
|
||||||
|
splitTextStyleAndMetadata(brewFromServer);
|
||||||
|
|
||||||
if(brewFromServer?.version !== brewFromClient?.version){
|
if(brewFromServer?.version !== brewFromClient?.version){
|
||||||
console.log(`Version mismatch on brew ${brewFromClient.editId}`);
|
console.log(`Version mismatch on brew ${brewFromClient.editId}`);
|
||||||
@@ -347,9 +348,7 @@ const api = {
|
|||||||
return res.status(409).send(JSON.stringify({ message: `The server version is out of sync with the saved brew. Please save your changes elsewhere, refresh, and try again.` }));
|
return res.status(409).send(JSON.stringify({ message: `The server version is out of sync with the saved brew. Please save your changes elsewhere, refresh, and try again.` }));
|
||||||
}
|
}
|
||||||
|
|
||||||
splitTextStyleAndMetadata(brewFromServer);
|
brewFromServer.text = brewFromServer.text.normalize('NFC');
|
||||||
|
|
||||||
brewFromServer.text = brewFromServer.text.normalize();
|
|
||||||
brewFromServer.hash = await md5(brewFromServer.text);
|
brewFromServer.hash = await md5(brewFromServer.text);
|
||||||
|
|
||||||
if(brewFromServer?.hash !== brewFromClient?.hash) {
|
if(brewFromServer?.hash !== brewFromClient?.hash) {
|
||||||
@@ -359,26 +358,27 @@ const api = {
|
|||||||
return res.status(409).send(JSON.stringify({ message: `The server copy is out of sync with the saved brew. Please save your changes elsewhere, refresh, and try again.` }));
|
return res.status(409).send(JSON.stringify({ message: `The server copy is out of sync with the saved brew. Please save your changes elsewhere, refresh, and try again.` }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let brew = _.assign(brewFromServer, brewFromClient);
|
|
||||||
brew.title = brew.title.trim();
|
|
||||||
brew.description = brew.description.trim() || '';
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const patches = parsePatch(brewFromClient.patches);
|
const patches = parsePatch(brewFromClient.patches);
|
||||||
// Patch to a throwaway variable while parallelizing - we're more concerned with error/no error.
|
// Patch to a throwaway variable while parallelizing - we're more concerned with error/no error.
|
||||||
const patchedResult = applyPatches(patches, brewFromServer.text)[0];
|
const patchedResult = applyPatches(patches, brewFromServer.text, { allowExceedingIndices: true })[0];
|
||||||
|
if(patchedResult != brewFromClient.text)
|
||||||
|
throw("Patches did not apply cleanly, text mismatch detected");
|
||||||
// brew.text = applyPatches(patches, brewFromServer.text)[0];
|
// brew.text = applyPatches(patches, brewFromServer.text)[0];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
debugTextMismatch(brewFromClient.text, brewFromServer.text, `edit/${brewFromClient.editId}`);
|
debugTextMismatch(brewFromClient.text, brewFromServer.text, `edit/${brewFromClient.editId}`);
|
||||||
console.error('Failed to apply patches:', {
|
console.error('Failed to apply patches:', {
|
||||||
patches : brewFromClient.patches,
|
patches : brewFromClient.patches,
|
||||||
brewId : brew.editId || 'unknown',
|
brewId : brewFromClient.editId || 'unknown',
|
||||||
error : err
|
error : err
|
||||||
});
|
});
|
||||||
// While running in parallel, don't throw the error upstream.
|
// While running in parallel, don't throw the error upstream.
|
||||||
// throw err; // rethrow to preserve the 500 behavior
|
// throw err; // rethrow to preserve the 500 behavior
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let brew = _.assign(brewFromServer, brewFromClient);
|
||||||
|
brew.title = brew.title.trim();
|
||||||
|
brew.description = brew.description.trim() || '';
|
||||||
brew.text = api.mergeBrewText(brew);
|
brew.text = api.mergeBrewText(brew);
|
||||||
|
|
||||||
const googleId = brew.googleId;
|
const googleId = brew.googleId;
|
||||||
|
|||||||
Reference in New Issue
Block a user