RENOY
AppSheet

AppSheetのBotが二重に実行される原因と対策|二重登録を防ぐ設計

目次

現場アプリをAppSheetで作り、ボタンを押したら自動で記録が残る——ノーコードで業務が回り始めると、社内の反応は一気に変わります。ところが運用を始めてしばらく経つと、こんな声が上がることがあります。

「同じ内容が2件、登録されているんですけど」

実案件(匿名)で私たちが経験したのも、まさにこれでした。ユーザーの操作は1回。それなのに、AppSheetのBot(自動化)が2回走り、データが2セット作られていたのです。

この記事では、なぜノーコードの自動化で二重登録が起きるのか、そして「アプリ側だけでは防げない」理由と対策を整理します。

起きたこと:1回の操作で、処理が2回走る

症状はシンプルです。ユーザーがアプリ上でボタンを1回押すと、Botが起動して外部処理(GAS)を呼び出す。その結果として作られるはずのデータが、なぜか2セット存在する。

厄介なのは、毎回必ず再現するわけではない点です。「たまに二重になる」という状態は、原因の切り分けが難しく、現場では「操作ミスでは」と片付けられがちです。しかし調べてみると、アプリの作り方そのものに原因がありました。

原因:Grouped Actionの各サブアクションが、それぞれイベントになる

AppSheetには、複数のアクションをまとめて順番に実行するGrouped Actionという仕組みがあります。「ステータスを更新して、日時を記録して、フラグを立てる」といった一連の操作を、ボタン1つにまとめられる便利な機能です。

問題は、ここです。Grouped Actionの中の各サブアクションが、それぞれ別々のデータ変更イベントとして扱われることがあります。つまり、ユーザーから見れば「1回の操作」でも、Botから見れば「複数回のデータ変更」なのです。

Botはデータが変わるたびにトリガー条件を再評価します。その結果、条件を満たすタイミングが複数回訪れ、同じレコードに対してBotが多重発火する。これが二重登録の正体でした。

なお、AppSheetの仕様は変わるため、Botのトリガー挙動やGrouped Actionの扱いについては、最新の情報を必ず公式ドキュメントで確認してください。

対策1:Bot側は「値がすべて揃った状態」だけで発火させる

まず手を入れたのは、Botのトリガー条件です。

よくあるのは、「ステータスが◯◯になったら」といった単一の条件だけで発火させる書き方です。これだと、途中の中途半端な状態でも条件を満たしてしまい、複数回引っかかります。

そこで、条件を**「処理に必要な値がすべて揃った状態」として厳密に記述**しました。必要な項目が1つでも欠けていれば発火しない。すべて埋まった瞬間だけ、1回だけ発火する。こう書き換えることで、Grouped Actionの途中段階では条件を満たさなくなり、多重発火が大きく減ります。

考え方としては、「何かが変わったら動く」ではなく、**「完成した状態になったときだけ動く」**にする、ということです。

対策2:呼ばれる側(GAS)に冪等性を実装する

ただし、Bot側の条件を整えるだけでは不十分です。理由は単純で、二重発火の原因はアプリの作り方だけではないからです。

  • ユーザーがボタンを二度押しする
  • 通信が不安定で、端末側がリクエストを再送する
  • 一時的なエラーで、リトライが走る

これらはアプリの設定では防げません。だから、呼び出される側——今回はGAS——に、**「同じ入力が2回来ても壊れない」性質(冪等性)**を持たせます。実装したのは次の3点です。

対策目的
LockServiceで排他制御同時に走った処理を直列化し、同時書き込みを防ぐ
処理済みステータスでガードすでに処理済みなら、2回目は何もせず終了する
SpreadsheetApp.flush()書き込みを確定させ、次の判定が古い状態を見ないようにする

とくに重要なのが2番目の処理済みガードです。処理を始める前に「このレコードはもう処理済みか」を確認し、済んでいれば黙って終わる。この1行の判断があるだけで、何回呼ばれてもデータは1セットしか作られません。

そして、ガードが正しく働くには、書き込みが確定していることが前提になります。1回目の処理が「済み」を書いたのに、それが反映される前に2回目が判定してしまえば、ガードはすり抜けます。だから排他制御と書き込み確定(flush)をセットで入れます。

全体像:入口と出口の二重防護

整理すると、対策は入口(AppSheet側)と出口(GAS側)の両方に置きます。

  • 入口(AppSheet):そもそも余計に発火させない。値が揃った状態だけで1回発火する条件にする
  • 出口(GAS):万一2回来ても、2回目は無害に終わる。ロック・処理済みガード・書き込み確定

どちらか一方では足りません。入口だけを直すと、ユーザーの二度押しや通信リトライで破綻します。出口だけを直すと、無駄な呼び出しが走り続け、動作は遅く、原因の切り分けも難しくなります。

教訓:ノーコードでも「壊れない設計」は必要

この一件で確認できたのは、シンプルな原則です。

ノーコードの自動化でも、冪等性の設計はプロコードと同じように必要になる。

ノーコードツールは「作りやすさ」で選ばれます。実際、AppSheetは短期間で現場アプリを立ち上げられる強力な選択肢です。ただし、作りやすいことと、壊れにくいことは別の話です。ボタンを押す人は必ず二度押しますし、電波の悪い現場では通信も必ず失敗します。

「正常に操作されれば正しく動く」ではなく、**「想定外の操作が来ても壊れない」**ところまで設計して、はじめて業務に乗せられます。とくに請求・在庫・受発注のように、データが1件増えるだけで実害が出る業務では、この違いが決定的です。

二重登録を疑うときのチェックポイント

  • Botのトリガー条件が、途中の状態でも成立する書き方になっていないか
  • Grouped Actionでまとめた操作が、複数のデータ変更イベントになっていないか
  • 外部処理(GAS等)に、処理済みかどうかの判定があるか
  • 同時実行を直列化する仕組み(ロック)が入っているか
  • 「たまに二重になる」を操作ミスとして片付けていないか

まとめ

  • AppSheetのBotは、Grouped Actionの各サブアクションごとにトリガー条件が再評価され、多重発火することがある
  • 対策はBot側だけでは足りない。入口(条件の厳密化)と出口(GASの冪等性)の二重防護で守る
  • GAS側はロックによる直列化・処理済みステータスのガード・書き込みの確定をセットで実装する
  • 二度押しや通信リトライはアプリ設定では防げない。同じ入力が2回来ても壊れない設計が前提になる
  • ノーコードでも、業務データを扱う以上、求められる堅牢さはプロコードと変わらない(各サービスの仕様は変わるため、最新は公式で確認)

RENOYでは、AppSheetやGASを使った業務自動化を、作って終わりにせず「現場の使い方で壊れないか」まで含めて設計しています。「すでに作ったアプリで、たまに変なデータが増える」といった段階のご相談も歓迎です。まずはお気軽に無料個別相談(オンライン・60分)をご利用ください。サービス内容をまとめた資料は資料請求からご覧いただけます。

#AppSheet#GAS#業務自動化#中小企業#ノーコード