Renato
Renato

Reputation: 705

Event duplication?

I'm facing a strange issue with a Google Spreadsheet Script on GAS.

Sometimes a function, triggered by the event "mouse up" below, is executed two or three times with a difference of seconds between each running. It doesn't happen every time, the problem looks pretty much random.

Button:

var button = app.createButton("Alocar").addClickHandler(app.createClientHandler().forEventSource().setEnabled(false)).addMouseUpHandler(app.createServerHandler("onAllocateTask").addCallbackElement(panel));

"onAllocateTask" beginning:

function onAllocateTaskSheet(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  ss.toast("Aguarde alguns minutos.", "Atenção", 8);

  var task = e.parameter[TASK_ALLOCATION_PARAMETER];
  if (task == null || task == "") {
    return;
  }

  ... continues ...
}

I can guarantee the function "onAllocateTaskSheet" is called just once in the code (on the piece of code above). Another important information is that this procedure (onAllocateTaskSheet) has a high execution time (it copies dozens of Google Docs documents).

Is there a explanation for a duplicated execution of this function? Perhaps I'm using the wrong event? Some internal error can cause the procedure to be reexecuted?

Thanks again for helping!

EDIT:

Ok, now I can confirm the problem is not related with the button or the event mouseUp. The problem is the function "onAllocateTask" being reexecuted after X minutes. It does not happen when onAllocateTask finishes quickly (in less than 1 minute for example). I guess it related with some timeout or internal error.

Unexpected exception upon serializing continuation Google Apps Script Here someone says something about Google Apps Scripts losing the "loop pointer". Could it be possible?

Upvotes: 0

Views: 215

Answers (2)

Taras
Taras

Reputation: 1023

Just disable the button on the clent side while your server request is running. But you should definitely use the same event for the server and the client handler.

var button = app.createButton("Alocar");
button.addClickHandler(app.createClientHandler().forEventSource().setEnabled(false));
button.addClickHandler(app.createServerHandler("onAllocateTask").addCallbackElement(panel));

Upvotes: 0

Serge insas
Serge insas

Reputation: 46802

I don't have any good explanation on this but it happened to me too. The best solution is to use the lock service that will guarantee that only one instance of a function will be executed on one click. It is very easy to implement :

at the begin of your function get a lock like this :

  ...
  var lock = LockService.getPublicLock();
  var success = lock.tryLock(5000);
   if (!success) {
     Logger.log('tryLock failed to get the lock');
     return
   }

and at the end of normal execution release the lock like this :

   lock.releaseLock();

(taken from documentation here)

Upvotes: 1

Related Questions