2014-03-12 172 views
7

我写了一个脚本,可以通过在谷歌云端硬盘文件夹有大量的文件进行迭代。由于我对这些文件所做的处理超出了最大执行时间。当然,我写入脚本使用DriveApp.continueFileIterator(continuationToken):令牌存储在项目属性中,当脚本运行时,它会检查是否有令牌,如果存在则从令牌创建FileIterator,如果不是则重新开始。正确使用

我发现了什么是即使脚本与它仍然具有迭代的开头开始延续标记重新启动,再次尝试处理相同的文件,这是浪费时间的后续执行。我是否错过了一些至关重要的命令或方法,使它从离开的地方开始?我是否应该在while(content.hasNext())循环中的各个阶段更新延续令牌?

这里的瘦身,给你一个想法的示例代码:

function listFilesInFolder() { 
    var id= '0fOlDeRiDg'; 
    var scriptProperties = PropertiesService.getScriptProperties(); 
    var continuationToken = scriptProperties.getProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN'); 
    var lastExecution = scriptProperties.getProperty('LAST_EXECUTION'); 
    if (continuationToken == null) { 
    // first time execution, get all files from drive folder 
    var folder = DriveApp.getFolderById(id); 
    var contents = folder.getFiles(); 
    // get the token and store it in a project property 
    var continuationToken = contents.getContinuationToken(); 
    scriptProperties.setProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN', continuationToken); 
    } else { 
    // we continue to import from where we left 
    var contents = DriveApp.continueFileIterator(continuationToken); 
    } 
    var file; 
    var fileID; 
    var name; 
    var dateCreated; 

    while(contents.hasNext()) { 
    file = contents.next(); 
    fileID = file.getId(); 
    name = file.getName(); 
    dateCreated = file.getDateCreated(); 
    if(dateCreated > lastExecution) { 
     processFiles(fileID); 
    } 
    } 
    // Finished processing files so delete continuation token 
    scriptProperties.deleteProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN'); 
    var currentExecution = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss"); 
    scriptProperties.setProperty('LAST_EXECUTION',currentExecution); 
}; 
+0

第一次执行或完成时是否超时? – Jonathon

回答

1

您的日期比较不会在你的方式工作。

var currentExecution = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss"); 

将存储"2014-04-18 08:32:01",而文件日期file.getDateCreated()会返回一个Date对象比较这些使用任<>将始终返回false。

所以我建议你保存时间时间戳(因为你不能店Date对象),然后比较,为文件创建日期的时间戳。

// stored time stamp 
var lastExecution = scriptProperties.getProperty('LAST_EXECUTION'); 

… 

dateCreated = file.getDateCreated().getTime(); 

… 

var currentExecution = new Date().getTime(); 
scriptProperties.setProperty('LAST_EXECUTION',currentExecution); 

该比较将按照您的预期工作。

12

像乔纳森说,你错比较日期。但这不是你剧本的主要问题,也不是你所问的。

你得到错误的主要概念是,你做你的循环之前延续令牌不能保存。当你得到令牌时,它会保存那个时候的位置,如果你继续迭代,那么这个不会被保存,你将在后面重复这些步骤,就像你正在经历的那样。

获得令牌后,你不能让你的脚本发生错误终止。您必须测量您可以在5分钟内处理多少个文件并在此之前手动停止脚本,以便您有机会保存令牌。

这里做的正确方法:

function listFilesInFolder() { 
    var MAX_FILES = 20; //use a safe value, don't be greedy 
    var id = 'folder-id'; 
    var scriptProperties = PropertiesService.getScriptProperties(); 
    var lastExecution = scriptProperties.getProperty('LAST_EXECUTION'); 
    if(lastExecution === null) 
    lastExecution = ''; 

    var continuationToken = scriptProperties.getProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN'); 
    var iterator = continuationToken == null ? 
    DriveApp.getFolderById(id).getFiles() : DriveApp.continueFileIterator(continuationToken); 


    try { 
    for(var i = 0; i < MAX_FILES && iterator.hasNext(); ++i) { 
     var file = iterator.next(); 
     var dateCreated = formatDate(file.getDateCreated()); 
     if(dateCreated > lastExecution) 
     processFile(file); 
    } 
    } catch(err) { 
    Logger.log(err); 
    } 

    if(iterator.hasNext()) { 
    scriptProperties.setProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN', iterator.getContinuationToken()); 
    } else { // Finished processing files so delete continuation token 
    scriptProperties.deleteProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN'); 
    scriptProperties.setProperty('LAST_EXECUTION', formatDate(new Date())); 
    } 
} 

function formatDate(date) { return Utilities.formatDate(date, "GMT", "yyyy-MM-dd HH:mm:ss"); } 

function processFile(file) { 
    var id = file.getId(); 
    var name = file.getName(); 
    //your processing... 
    Logger.log(name); 
} 

无论如何,它可能是一个文件,你的运行之间建立得到和你没有得到它在你的不断迭代。然后,通过在上次运行后保存执行时间,您可能会在下次运行时错过它。我不知道你的用例,如果最终重新处理一些文件或错过一些文件是可以接受的。如果你根本没有任何一种情况,那么我看到的唯一解决方案就是保存已处理的所有文件的ID。您可能需要将这些文件存储在驱动器文件中,因为对于太多的ID,PropertiesService可能太小。