/** * Copyright (c) 2006-2024, draw.io AG * Copyright (c) 2006-2024, JGraph Holdings Ltd * * Class for polling files for changes. */ DrawioFilePolling = function(file, sync) { this.file = file; this.sync = sync; }; /** * Maximum number if attempts to poll after an error. */ DrawioFilePolling.prototype.maxRetries = 2; /** * The minimum delay between polls for adaptive polling. */ DrawioFilePolling.prototype.minPollDelay = 2000; /** * Starts the polling with the given delay. */ DrawioFilePolling.prototype.start = function(delay) { if (!this.isConnected()) { this.maxDelay = delay; this.delay = delay; var threadFn = mxUtils.bind(this, function() { this.poll(0, nextFn); }); var nextFn = mxUtils.bind(this, function() { // To get adaptive polling, we use timeout instead of interval this.thread = setTimeout(threadFn, this.delay); this.delay = Math.min(this.maxDelay, this.delay + 2000); // TODO this or this.delay * 2 }); nextFn(); EditorUi.debug('DrawioFilePolling.start', [this], 'thread', this.thread, 'delay', delay, 'rev', this.file.getCurrentRevisionId()); } }; /** * Checks if the file has been modified. */ DrawioFilePolling.prototype.updateStatus = function() { if (this.hasOtherWriters()) { this.sync.lastMessage = mxResources.get('otherUsersEditing'); } this.sync.lastModified = this.file.getLastModifiedDate(); this.sync.updateStatus(); }; /** * Checks if the file has been modified. */ DrawioFilePolling.prototype.poll = function(retry, nextFn) { retry = (retry != null) ? retry : 0; var handleError = mxUtils.bind(this, function(e) { if (retry < this.maxRetries) { this.retryPoll(mxUtils.bind(this, function() { this.poll(retry + 1, nextFn); })); } else { nextFn(); } }); this.file.getLatestVersionId(mxUtils.bind(this, function(latestVersionId) { if (latestVersionId != -1) { var currentVersionId = this.file.getCurrentRevisionId(); if (latestVersionId != currentVersionId) { this.file.getLatestVersion(mxUtils.bind(this, function(latestFile) { this.file.mergeFile(latestFile, mxUtils.bind(this, function() { // An update is detected, so start adaptive polling this.delay = this.minPollDelay; this.lastOtherWriter = Date.now(); this.updateStatus(); nextFn(); }), handleError); }), handleError); } else { this.updateStatus(); nextFn(); } } else { nextFn(); } }), handleError); }; /** * Translates this point by the given vector. * * @param {number} dx X-coordinate of the translation. * @param {number} dy Y-coordinate of the translation. */ DrawioFilePolling.prototype.retryPoll = function(fn) { var delay = 300 + Math.random() * 300; window.setTimeout(fn, delay); EditorUi.debug('StorageFile.retryPoll', [this], 'delay', delay); }; /** * Stops the polling. */ DrawioFilePolling.prototype.stop = function() { EditorUi.debug('DrawioFilePolling.stop', [this], 'thread', this.thread); clearTimeout(this.thread); this.thread = null; }; /** * Returns true if polling is active. */ DrawioFilePolling.prototype.isConnected = function() { return this.thread != null; }; DrawioFilePolling.prototype.hasOtherWriters = function() { return this.lastOtherWriter != null && Date.now() - this.lastOtherWriter < 60 * 1000; // Other writer detected in the last minute };