

GASのスクリプト同時実行にて下記のサンプルでわからないことがあります。

[code]

    function test() {
      var docLock = LockService.getDocumentLock();
      // ドキュメントに対してLockがかかっているかチェック
      if (docLock.tryLock(500)) {
        //やりたい処理
    
        // Lockかけた状態のまま１０秒待つ
        Utilities.sleep(10000);
    
        // Lockの解放
        docLock.releaseLock();
      }
    }
    
[/code]

tryLockは自分が実行しようとする際、他人がスクリプトを実行していない確認し、していたらそれが終了するまで5秒まで待つだと思いますが、以下の処理をなぜ必要とするのかが理解できません。

[code]

     // Lockかけた状態のまま１０秒待つ
        Utilities.sleep(10000);
    
[/code]

目的の処理が終わったらさっさとロックを解除すればいいと思うのですが。  
Utilities.sleepを書いていないサンプルコードを見たこともあるのでますますわからなくなりました。

(追記)

`hasLock()` というものもあってますますわかりません。  
同じスプレッドシートにて（プロジェクト）スクリプトが走っていたらその間に実行しようとしたらそれが終了するまで待機し、先のスクリプトが終了したら次のスクリプトが実行するようにしたいだけです。

参考にしたページ:  
[GASで排他処理を実現してみる](https://for-dummies.net/gas-noobs/how-to-use-lockservice-by-
gas/#index_id0)

GoogleFormにてフォーム送信によりスプレッドシートに書き込みされたタイミングで、その書き込みに対し５秒程度の処理を加えています。  
getlastrowで最終行を取得して該当行を処理しますが、同時送信だと最終行が同じになってしまい、同じ内容の処理が行われてしまいます。  
これを防止したい為に排他処理を行いたいのですが、結果に変わりがありません。

何パターンか試しましたが変わりありません。

[code]

    function 転記() {
      const ss = SpreadsheetApp.getActiveSpreadsheet();
      const sh = ss.getSheetByName('転記先');
      const Mysh = ss.getSheetByName('フォームの回答 1');    
    
      //ドキュメントロックを使用する
      var lock = LockService.getDocumentLock();
    
      //10秒間のロックを実施
      if (lock.tryLock(10000)) {
        try {       
            let MyLastrow = Mysh.getLastRow();   
            let shLastrow = sh.getLastRow();
            以下処理       
        } catch(e) {
            //ここにエラー時の処理を記述する
        } finally {
            //最期に必ずロックを開放する
            lock.releaseLock();
        }
      }else{
        
      } //try    
          
    }//end
    
[/code]

この処理でMyLastrowが変わらないようで、同時にドームをっ送信すると転記先側シートに同じ内容が記載されてしまいます。


CC BY-SA 4.0
2023-11-15T21:02:49.827
96786
2023-11-21T15:46:08.757
2023-11-19T06:15:39.613
3060
60285
question
google-apps-script
GASの排他処理でsleepを行うケースがあるのはなぜ？


お示しのコードは、サンプルのコードですから

> // Lockかけた状態のまま１０秒待つ

というのは、  
本来の目的の処理に10秒かかると仮定しての  
その代わりのコードではないでしょうか？

なお、既に他で回答済みですが、  
フォームの送信をトリガーイベントとするスクリプトは、  
「フォームの回答 1」シートに回答が記入されたセル範囲のデータを  
引数として受け取っているので、  
「フォームの回答 1」シートへの自動記入後に起動していると考えられます。

なので、フォームの回答の送信が短時間に2件あった場合は、  
先発送信者によるトリガーイベントでスクリプトが起動する前に  
先発者に加え、後発者の回答データも「フォームの回答 1」シートに記入ずみの場合は、  
スクリプトの処理に排他処理をかけたとしても  
最終行として同じ行（後発送信者の回答の行）を取得することになります。

そのため、フォーム送信のトリガーイベントから  
それぞれの回答が記入されたセル範囲を取得して行を特定する必要があります。

そして、  
取得した回答データをトリガー起動のスクリプトで他のシートに再転記するときは、  
最終行の変動がスクリプトによるものなので  
書込み対象行（最終行 + 1）の取得から書込みまでの処理を  
排他処理にして実行する必要があります。

さらに加えると、  
スプレッドシートのトリガーイベントの引数からは、  
セル範囲だけでなく回答データの内容を配列として（e.values）得ることができるので、  
「フォームの回答 1」シートの値を行を特定して読み取るのではなく、  
直接引数として渡されたトリガーイベントから得た回答内容を  
スクリプトによる転記先のシートに排他処理をかけて記入することができます。  
e.values[0] タイムスタンプ（秒単位まで：ミリ秒まで必要ならシートから）  
e.values[1] 1問目の回答  
e.values[2] 2問目の回答  
...  
...

（参考）  
<https://developers.google.com/apps-
script/guides/triggers/events?hl=ja#Google%20Sheets-events>


CC BY-SA 4.0
2023-11-18T07:37:06.163
96817
2023-11-18T08:04:58.533
2023-11-18T08:04:58.533
57654
57654
96786
answer


ありがとうございます、なかなか難しいですね・・・

`const LastRwAll=e.range.getRow();` と `appendRow();` にて現在解決しました。

`appendRow`の上書き問題について書かれた記事を見たことがありますが、自身の環境で何度もテストした結果上書きは起こりませんでしたのでとりあえず良しとしています。


CC BY-SA 4.0
2023-11-20T04:39:59.283
96843
2023-11-21T15:46:08.757
2023-11-21T15:46:08.757
3060
60285
96786
answer