[英]What happens when I “sleep” in GAS ? (execution time limit workaround)
Behind this (not so much I admit...) funny question is a real question about a workaround I use without really understanding how it works. 在这背后(不是我承认......)有趣的问题是关于我使用的解决方法的真正问题,而没有真正理解它是如何工作的。
First a brief description of my use case, all this is happening in a document bound UiApp showing up in the sidebar : 首先简要介绍一下我的用例,这一切都发生在侧边栏中显示的文档绑定UiApp中:
I have to create and send by email a couple of hundred documents in a mail merge application written in GAS. 我必须在用GAS编写的邮件合并应用程序中通过电子邮件创建和发送几百个文档。 It takes of course far too long to be processed in one batch without hitting the 5 minutes execution time limit so I tried a few different workarounds to get the task done : 当然,在没有达到5分钟执行时间限制的情况下,在一个批处理中花费太长时间,所以我尝试了几个不同的解决方法来完成任务:
It works perfectly, I process 40 documents batches is each call (during about 3 minutes) then pause for a while and start again until it gets finished. 它工作得很好,我处理40个文件批次是每次调用(大约3分钟)然后暂停一段时间并重新开始直到它完成。 Each call is triggered by the checkBox linked server handler, the check box itself is changed in the handler function, creating its own trigger this way. 每个调用都由checkBox链接服务器处理程序触发,复选框本身在处理程序函数中更改,以这种方式创建自己的触发器。
My question (finally ;-) is : knowing that the whole process might take 30 to 60 minutes how precisely is that possible ? 我的问题(最后;-)是:知道整个过程可能需要30到60分钟,这可能有多精确? How / why are these server handler function considered as multiple process since they are created from inside the function itself ? 这些服务器处理函数如何/为什么被视为多个进程,因为它们是从函数本身内部创建的?
I hope I'm clear enough, (which I doubt since it is a bit confuse in my mind :-) 我希望我足够清楚,(我怀疑,因为它在我的脑海里有点混乱:-)
I join below the code of the clock test app that gave me the idea, it will probably make things easier to understand. 我加入了时钟测试应用程序的代码,它给了我这个想法,它可能会让事情更容易理解。
function doGet() {
var app = UiApp.createApplication().setTitle('Counter/Timer');
var Panel = app.createAbsolutePanel().setStyleAttribute('padding','35');
var counter = app.createHTML().setId('counter').setHTML('<B>Timer = wait</B>').setStyleAttribute('fontSize','40px');// set start display
var clo = app.createTextBox().setName('clo').setId('clo').setValue('0').setVisible(false);//set start value in seconds
var handler1 = app.createServerHandler('doSomething').addCallbackElement(Panel);
var chk1 = app.createCheckBox('test1').addValueChangeHandler(handler1).setVisible(true).setId('chk1').setVisible(false);
app.add(Panel.add(chk1).add(counter).add(clo));
chk1.setValue(true,true);// start the process
return app}
function doSomething(e) {
var app = UiApp.getActiveApplication();
var xx = Number(e.parameter.clo);
var disp = app.getElementById('counter')
xx++ ;// replace by xx-- to count downwards
if(xx>600){ // 10 minutes timeout for example
disp.setHTML('<B> GAME OVER ;-)</B>').setStyleAttribute('fontSize','80px').setStyleAttribute('color','RED')
return app
}
var cnt = app.getElementById('clo').setValue(xx)
disp.setHTML('<B>'+T(xx)+'</B>')
Utilities.sleep(1000); // instead of sleeping do something !
// below comes the "active" part
var chk1 = app.getElementById('chk1').setValue(false,false)
var chk1 = app.getElementById('chk1').setValue(true,true)
return app;
}
function T(val){
var min = parseInt(val/60);
var sec = val-(60*min);
if(sec<10){sec='0'+sec}
if(min<10){min='0'+min}
var st = '> '+min+':'+sec
return st
}
The statement that the server handler function calls aren't independent processes because they "are created from inside the function itself" isn't quite true. 服务器处理程序函数调用的语句不是独立进程,因为它们“是从函数本身内部创建的”并不完全正确。
You've set up a checkBox element chk1
with a server handler doSomething
. 您已经使用服务器处理程序doSomething
设置了一个checkBox元素chk1
。 Whenever the checkBox is checked, then, an event is dispatched to the server. 每当选中checkBox时,都会将一个事件分派给服务器。 (...and your script is causing those events with every chk1.setValue()
call) The checkBox
and surrounding UI code is running in your browser - click "show source" or use an explorer to see what's been served to your browser by the google servers. (...并且您的脚本在每次chk1.setValue()
调用时都会导致这些事件) checkBox
和周围的UI代码在您的浏览器中运行 - 单击“显示源”或使用资源管理器查看chk1.setValue()
浏览器提供的内容谷歌服务器。 (Warning - it's obfuscated. But you might recognize some of your strings, and from that your client-side code.) (警告 - 它被混淆了。但你可能会认识到你的一些字符串,以及你的客户端代码。)
Here's what we're told in the documentation for Class ServerHandler : 以下是我们在Class ServerHandler的文档中所说的内容 :
When a ServerHandler is invoked, the function it refers to is called on the Apps Script server in a "fresh" script. 当调用ServerHandler时,它引用的函数在Apps脚本服务器上以“新鲜”脚本调用。
That's the key to extending your operating time: each dispatched event results in invocation of doSomething()
in a completely new operating context - it's like you've opened the script editor in a different browser, and clicked "run" on your script. 这是延长操作时间的关键:每个调度事件都会导致在全新的操作上下文中调用doSomething()
- 就像您在其他浏览器中打开脚本编辑器一样,并在脚本上单击“运行”。 The "fresh" script has no access to var values of previous run... but it is also given it's own set of operating restrictions, including timers. “新鲜”脚本无法访问以前运行的var值...但它也有自己的一组操作限制,包括计时器。
PS: You should make sure that server-side handler is "thread safe" by using Lock, since you're accessing shared resources that may be accessed by multiple instances of the doSomething()
callback. PS:您应该通过使用Lock确保服务器端处理程序是“线程安全的”,因为您正在访问可由多个doSomething()
回调实例访问的共享资源。 Related to that, it's possible to hit another limit with this script: 与此相关,可以使用此脚本达到另一个限制:
Just for fun, I commented out .setVisible(false)
on chk1
, so the checkBox would be visible. 为了好玩,我在chk1
上注释了.setVisible(false)
,因此checkBox是可见的。 I then rapidly clicked it several dozen times. 然后我快速点击了几十次。 The time display ran out-of-order, and eventually the above error popped up. 时间显示无序运行,最终出现上述错误。 (minutes later) It's an artificial situation, of course, but still an error state that's easily avoided. (几分钟后)当然,这是一个人为的情况,但仍然是一个容易避免的错误状态。
PPS: I wonder if one could use the same technique to dispatch multiple parallel server-side handlers, and thus reduce the elapsed time to complete the whole job? PPS:我想知道是否可以使用相同的技术来分派多个并行服务器端处理程序,从而减少完成整个作业所用的时间?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.