NNoAccidentupdate 3.22.3
8d9d8202创建于 2022年3月28日历史提交


let wrapCallback = function(callback, log, methodName){
	callback = callback || function(){};
	let start = new Date().getTime();
	return function(err, result){
		log.runLog('info', methodName, 'ObsClient cost ' +  (new Date().getTime() - start) + ' ms');
		if(Object.prototype.toString.call(err) === '[object String]'){
			return callback(new Error(err), result);
		}
		
		return callback(err, result);
	};
};


let wrapEventCallback = function(eventCallback){
	eventCallback = eventCallback || function(){};
	return function(t, key, result){
		if(Object.prototype.toString.call(result) === '[object Error]'){
			return eventCallback(t, key, result);
		}
		
		if(Object.prototype.toString.call(result) === '[object String]'){
			return eventCallback(t, key, new Error(result));
		}
		
		if(!result){
			return;
		}
		
		if(result.CommonMsg.Status > 300){
			return eventCallback(t, key, new Error('status:' + result.CommonMsg.Status + ', code:' + result.CommonMsg.Code + ', message:' + result.CommonMsg.Message));
		}

		eventCallback(t, key, result);
	};
};

let checkPrefix = function(prefix){
	if(Object.prototype.toString.call(prefix) === '[object String]' && prefix.lastIndexOf('/') !== prefix.length - 1){
		prefix += '/';
	}
	return prefix;
};

let posix = {};
posix.extend = function(ObsClient){
	ObsClient.prototype.dropFile = function(param, callback){
		this.deleteObject(param, callback);
	};
	
	ObsClient.prototype.dropFolder = function(param, callback){
		let that = this;
		param = param || {};
		let _callback = wrapCallback(callback, that.log, 'dropFolder');
		let eventCallback = wrapEventCallback(param.EventCallback);
		let taskNum = param.TaskNum || 1;
		let runningTask = 0;
		let taskQueue = [];

		let doNext = function(){
			while(runningTask < taskNum && taskQueue.length > 0){
				taskQueue.shift()();
			}
		};
		
		let doDropOne = function(key, ctx, done, dryRun){
			if(dryRun){
				ctx.finished++;
				done(ctx);
				return;
			}
			
			let task = function(){
				runningTask++;
				that.dropFile({
					Bucket : ctx.bucket,
					Key : key,
				}, function(err, result){
					runningTask--;
					ctx.finished++;
					doNext();
					if(err){
						eventCallback('dropFileFailed', key, err);
						ctx.subDeleted = false;
					}else if(result.CommonMsg.Status >= 300){
						eventCallback('dropFileFailed', key, result);
						ctx.subDeleted = false;
					}else{
						eventCallback('dropFileSucceed', key, result);
					}
					done(ctx);
				});
			};
			
			if(runningTask < taskNum){
				task();
			}else{
				taskQueue.push(task);
			}
		};
		
		let delimiter = '/';
		
		let createDone = function(subFolder, ctx, done){
			return function(subCtx){
				if(!subCtx.isTruncated && subCtx.finished === subCtx.total && subCtx.subDeleted){
					doDropOne(subFolder, ctx, done, false);
				}
			};
		};
		
		let recursiveDropByFolder = function(ctx, bucket, prefix, marker, done){
			runningTask++;
			that.listObjects({
				Bucket : bucket,
				Prefix : prefix,
				Delimiter : delimiter,
				Marker : marker,
			}, function(err, result){
				runningTask--;
				if(err){
					return _callback(err);
				}
				
				if(result.CommonMsg.Status >= 300){
					return _callback(null, result);
				}
				
				ctx.total += result.InterfaceResult.Contents.length;
				ctx.total += result.InterfaceResult.CommonPrefixes.length;
				if(ctx.total === 0){
					done(ctx);
					return;
				}
				
				ctx.isTruncated = result.InterfaceResult.IsTruncated === 'true';
				
				let createRecursiveDropByFolderTask = function(subFolder){
					return function(){
						recursiveDropByFolder({total : 0, finished : 0, isTruncated : false, bucket : bucket, subDeleted : true}, bucket, subFolder, null, createDone(subFolder, ctx, done));
					};
				};
				
				for(let j=0;j<result.InterfaceResult.CommonPrefixes.length;j++){
					let subFolder = checkPrefix(result.InterfaceResult.CommonPrefixes[j]['Prefix']);
					if(runningTask < taskNum){
						recursiveDropByFolder({total : 0, finished : 0, isTruncated : false, bucket : bucket, subDeleted : true}, bucket, subFolder, null, createDone(subFolder, ctx, done));
					}else{
						taskQueue.push(createRecursiveDropByFolderTask(subFolder));
					}
				}
				
				for(let j=0;j<result.InterfaceResult.Contents.length;j++){
					let key = result.InterfaceResult.Contents[j]['Key'];
					doDropOne(key, ctx, done, key.lastIndexOf(delimiter) === key.length - 1);
				}
				
				if(ctx.isTruncated){
					if(runningTask < taskNum){
						recursiveDropByFolder(ctx, bucket, prefix, result.InterfaceResult.NextMarker, done);
					}else{
						taskQueue.push(function(){
							recursiveDropByFolder(ctx, bucket, prefix, result.InterfaceResult.NextMarker, done);
						});
					}
				}
			});
		};
		
		let folder = checkPrefix(param.Prefix);
		recursiveDropByFolder({total : 0, finished : 0, isTruncated : false, bucket : param.Bucket, subDeleted : true}, param.Bucket, folder, null, function(ctx){
			if(ctx.isTruncated || ctx.finished !== ctx.total){
				return;
			}
			
			if(ctx.subDeleted){
				that.dropFile({
					Bucket : ctx.bucket,
					Key : folder
				}, function(err, result){
					if(err){
						eventCallback('dropFileFailed', folder, err);
						return _callback(err);
					}
					
					if(result.CommonMsg.Status >= 300){
						eventCallback('dropFileFailed', folder, result);
						return _callback(null, result);
					}
					eventCallback('dropFileSucceed', folder, result);
					return _callback(null, result);
				});
				return;
			}
			let errMessage = 'drop folder ' + folder + ' failed due to child file deletion failed';
			eventCallback('dropFileFailed', folder, new Error(errMessage));
			_callback(errMessage);
		});
		
	};
};

export default posix;