mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	introduced mutex to avoid conflicts during tab closing
This commit is contained in:
		
							parent
							
								
									1dfde76b95
								
							
						
					
					
						commit
						d6016f9b81
					
				@ -7,11 +7,14 @@ import treeService from "./tree.js";
 | 
				
			|||||||
import utils from "./utils.js";
 | 
					import utils from "./utils.js";
 | 
				
			||||||
import NoteContext from "./note_context.js";
 | 
					import NoteContext from "./note_context.js";
 | 
				
			||||||
import appContext from "./app_context.js";
 | 
					import appContext from "./app_context.js";
 | 
				
			||||||
 | 
					import Mutex from "../utils/mutex.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class TabManager extends Component {
 | 
					export default class TabManager extends Component {
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.mutex = new Mutex();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.activeNtxId = null;
 | 
					        this.activeNtxId = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // elements are arrays of note contexts for each tab (one main context + subcontexts [splits])
 | 
					        // elements are arrays of note contexts for each tab (one main context + subcontexts [splits])
 | 
				
			||||||
@ -292,6 +295,9 @@ export default class TabManager extends Component {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async removeNoteContext(ntxId) {
 | 
					    async removeNoteContext(ntxId) {
 | 
				
			||||||
 | 
					        // removing note context is async process which can take some time, if users presses CTRL-W quickly, two
 | 
				
			||||||
 | 
					        // close events could interleave which would then lead to attempting to activate already removed context.
 | 
				
			||||||
 | 
					        await this.mutex.runExclusively(async () => {
 | 
				
			||||||
            const noteContextToRemove = this.getNoteContextById(ntxId);
 | 
					            const noteContextToRemove = this.getNoteContextById(ntxId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (noteContextToRemove.isMainContext()) {
 | 
					            if (noteContextToRemove.isMainContext()) {
 | 
				
			||||||
@ -337,6 +343,7 @@ export default class TabManager extends Component {
 | 
				
			|||||||
            this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove});
 | 
					            this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.tabsUpdate.scheduleUpdate();
 | 
					            this.tabsUpdate.scheduleUpdate();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tabReorderEvent({ntxIdsInOrder}) {
 | 
					    tabReorderEvent({ntxIdsInOrder}) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										28
									
								
								src/public/app/utils/mutex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/public/app/utils/mutex.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					export default class Mutex {
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.current = Promise.resolve();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** @returns {Promise} */
 | 
				
			||||||
 | 
					    lock() {
 | 
				
			||||||
 | 
					        let resolveFun;
 | 
				
			||||||
 | 
					        const subPromise = new Promise(resolve => resolveFun = () => resolve());
 | 
				
			||||||
 | 
					        // Caller gets a promise that resolves when the current outstanding lock resolves
 | 
				
			||||||
 | 
					        const newPromise = this.current.then(() => resolveFun);
 | 
				
			||||||
 | 
					        // Don't allow the next request until the new promise is done
 | 
				
			||||||
 | 
					        this.current = subPromise;
 | 
				
			||||||
 | 
					        // Return the new promise
 | 
				
			||||||
 | 
					        return newPromise;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async runExclusively(cb) {
 | 
				
			||||||
 | 
					        const unlock = await this.lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            await cb();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        finally {
 | 
				
			||||||
 | 
					            unlock();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user