1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

All: Improved request repeating mechanism

This commit is contained in:
Laurent Cozic 2018-02-07 19:46:07 +00:00
parent 69fd32e7c6
commit 3f14878d0f
2 changed files with 82 additions and 25 deletions

View File

@ -18,6 +18,10 @@ class FileApiDriverWebDav {
return this.api_; return this.api_;
} }
requestRepeatCount() {
return 3;
}
async stat(path) { async stat(path) {
try { try {
const result = await this.api().execPropFind(path, 0, [ const result = await this.api().execPropFind(path, 0, [

View File

@ -4,6 +4,31 @@ const { shim } = require('lib/shim');
const BaseItem = require('lib/models/BaseItem.js'); const BaseItem = require('lib/models/BaseItem.js');
const JoplinError = require('lib/JoplinError'); const JoplinError = require('lib/JoplinError');
const ArrayUtils = require('lib/ArrayUtils'); const ArrayUtils = require('lib/ArrayUtils');
const { time } = require('lib/time-utils.js');
function requestCanBeRepeated(error) {
const errorCode = typeof error === 'object' && error.code ? error.code : null;
if (errorCode === 'rejectedByTarget') return false;
return true;
}
async function tryAndRepeat(fn, count) {
let retryCount = 0;
while (true) {
try {
const result = await fn();
return result;
} catch (error) {
if (retryCount >= count) throw error;
if (!requestCanBeRepeated(error)) throw error;
retryCount++;
await time.sleep(1 + retryCount * 3);
}
}
}
class FileApi { class FileApi {
@ -16,6 +41,14 @@ class FileApi {
this.driver_.fileApi_ = this; this.driver_.fileApi_ = this;
} }
// Ideally all requests repeating should be done at the FileApi level to remove duplicate code in the drivers, but
// historically some drivers (eg. OneDrive) are already handling request repeating, so this is optional, per driver,
// and it defaults to no repeating.
requestRepeatCount() {
if (this.driver_.requestRepeatCount) return this.driver_.requestRepeatCount();
return 0;
}
tempDirName() { tempDirName() {
if (this.tempDirName_ === null) throw Error('Temp dir not set!'); if (this.tempDirName_ === null) throw Error('Temp dir not set!');
return this.tempDirName_; return this.tempDirName_;
@ -59,50 +92,70 @@ class FileApi {
} }
// DRIVER MUST RETURN PATHS RELATIVE TO `path` // DRIVER MUST RETURN PATHS RELATIVE TO `path`
list(path = '', options = null) { async list(path = '', options = null) {
if (!options) options = {}; if (!options) options = {};
if (!('includeHidden' in options)) options.includeHidden = false; if (!('includeHidden' in options)) options.includeHidden = false;
if (!('context' in options)) options.context = null; if (!('context' in options)) options.context = null;
this.logger().debug('list ' + this.baseDir_); this.logger().debug('list ' + this.baseDir_);
return this.driver_.list(this.baseDir_, options).then((result) => { const result = await tryAndRepeat(() => this.driver_.list(this.baseDir_, options), this.requestRepeatCount());
if (!options.includeHidden) {
let temp = []; if (!options.includeHidden) {
for (let i = 0; i < result.items.length; i++) { let temp = [];
if (!isHidden(result.items[i].path)) temp.push(result.items[i]); for (let i = 0; i < result.items.length; i++) {
} if (!isHidden(result.items[i].path)) temp.push(result.items[i]);
result.items = temp;
} }
return result; result.items = temp;
}); }
return result;
// return this.driver_.list(this.baseDir_, options).then((result) => {
// if (!options.includeHidden) {
// let temp = [];
// for (let i = 0; i < result.items.length; i++) {
// if (!isHidden(result.items[i].path)) temp.push(result.items[i]);
// }
// result.items = temp;
// }
// return result;
// });
} }
// Deprectated // Deprectated
setTimestamp(path, timestampMs) { setTimestamp(path, timestampMs) {
this.logger().debug('setTimestamp ' + this.fullPath_(path)); this.logger().debug('setTimestamp ' + this.fullPath_(path));
return this.driver_.setTimestamp(this.fullPath_(path), timestampMs); return tryAndRepeat(() => this.driver_.setTimestamp(this.fullPath_(path), timestampMs), this.requestRepeatCount());
//return this.driver_.setTimestamp(this.fullPath_(path), timestampMs);
} }
mkdir(path) { mkdir(path) {
this.logger().debug('mkdir ' + this.fullPath_(path)); this.logger().debug('mkdir ' + this.fullPath_(path));
return this.driver_.mkdir(this.fullPath_(path)); return tryAndRepeat(() => this.driver_.mkdir(this.fullPath_(path)), this.requestRepeatCount());
} }
stat(path) { async stat(path) {
this.logger().debug('stat ' + this.fullPath_(path)); this.logger().debug('stat ' + this.fullPath_(path));
return this.driver_.stat(this.fullPath_(path)).then((output) => {
if (!output) return output; const output = await tryAndRepeat(() => this.driver_.stat(this.fullPath_(path)), this.requestRepeatCount());
output.path = path;
return output; if (!output) return output;
}); output.path = path;
return output;
// return this.driver_.stat(this.fullPath_(path)).then((output) => {
// if (!output) return output;
// output.path = path;
// return output;
// });
} }
get(path, options = null) { get(path, options = null) {
if (!options) options = {}; if (!options) options = {};
if (!options.encoding) options.encoding = 'utf8'; if (!options.encoding) options.encoding = 'utf8';
this.logger().debug('get ' + this.fullPath_(path)); this.logger().debug('get ' + this.fullPath_(path));
return this.driver_.get(this.fullPath_(path), options); return tryAndRepeat(() => this.driver_.get(this.fullPath_(path), options), this.requestRepeatCount());
} }
async put(path, content, options = null) { async put(path, content, options = null) {
@ -112,32 +165,32 @@ class FileApi {
if (!await this.fsDriver().exists(options.path)) throw new JoplinError('File not found: ' + options.path, 'fileNotFound'); if (!await this.fsDriver().exists(options.path)) throw new JoplinError('File not found: ' + options.path, 'fileNotFound');
} }
return this.driver_.put(this.fullPath_(path), content, options); return tryAndRepeat(() => this.driver_.put(this.fullPath_(path), content, options), this.requestRepeatCount());
} }
delete(path) { delete(path) {
this.logger().debug('delete ' + this.fullPath_(path)); this.logger().debug('delete ' + this.fullPath_(path));
return this.driver_.delete(this.fullPath_(path)); return tryAndRepeat(() => this.driver_.delete(this.fullPath_(path)), this.requestRepeatCount());
} }
// Deprectated // Deprectated
move(oldPath, newPath) { move(oldPath, newPath) {
this.logger().debug('move ' + this.fullPath_(oldPath) + ' => ' + this.fullPath_(newPath)); this.logger().debug('move ' + this.fullPath_(oldPath) + ' => ' + this.fullPath_(newPath));
return this.driver_.move(this.fullPath_(oldPath), this.fullPath_(newPath)); return tryAndRepeat(() => this.driver_.move(this.fullPath_(oldPath), this.fullPath_(newPath)), this.requestRepeatCount());
} }
// Deprectated // Deprectated
format() { format() {
return this.driver_.format(); return tryAndRepeat(() => this.driver_.format(), this.requestRepeatCount());
} }
clearRoot() { clearRoot() {
return this.driver_.clearRoot(this.baseDir_); return tryAndRepeat(() => this.driver_.clearRoot(this.baseDir_), this.requestRepeatCount());
} }
delta(path, options = null) { delta(path, options = null) {
this.logger().debug('delta ' + this.fullPath_(path)); this.logger().debug('delta ' + this.fullPath_(path));
return this.driver_.delta(this.fullPath_(path), options); return tryAndRepeat(() => this.driver_.delta(this.fullPath_(path), options), this.requestRepeatCount());
} }
} }