0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GASのLockServiceってキューじゃないの?と気づいた話

0
Posted at

はじめに

GAS使いの皆さんこんにちは、よきGASライフをお過ごしでしょうか?

先日LockServiceを使った重複対策をしていたときにふと、疑問が浮かびました。

自分はずっと、GASの LockService を「キューみたいに順番待ちさせるやつ」だと思って使ってた。waitLock って書いてあるし、なんとなく「並んで待つ感じね」で読み流して、特に深く考えずに何個もスクリプトに突っ込んでた。

ある日ふと「これ、複数リクエストが来たとき内部的に何やってるんだろう?」が気になって調べてみたら、自分の理解はわりと違っていた。

たぶん同じ勘違いしてる人、がけっこういると思う。
「GAS キュー」とか「GAS 順番待ち」で検索してこの記事に辿り着いた人向けに、勘違いしていた自分の話としてまとめておきます。


LockServiceは「キュー」じゃなくて「鍵」

結論を一行で。

LockService はキュー(順番待ちの行列)ではなく、排他制御(鍵)です。

イメージで言うと、

  • キュー → 順番に並んでて、全員いつかは処理される前提(行列)
  • ロック → 一人ずつ通すための門番。先に取った人が解放するまで他は入れない

waitLock(ms) で「鍵が空くまで最大 ms ミリ秒待つ」ができるので、外から見ると順番待ちっぽく見える。これがたぶん誤解の入り口。

実際には「待ち列の順序」は保証されてないし、待ちきれなかった人は例外で落ちる。「並んでる」のではなくて「鍵の前で押し合いへし合いしてる」が正しい。


たぶん多くの人が勘違いしてる3つ

1. FIFO保証されてない

これが一番びっくりした。

「先に waitLock を呼んだ人が先に通れる」と思ってた。でも、公式ドキュメントを読んでも「先着順で渡す」とは書かれていない。Apps Script の実装としては、複数の実行が同時にロック取得を試みたとき、どの実行が次に取れるかは決まっていない

なので、

  • A が先に waitLock を呼んだ
  • 直後に B が waitLock を呼んだ
  • A が解放した瞬間、次に取るのは A?B? → 未定義

「キューだから A → B の順で動くはず」を前提に設計すると、ハマる。

2. waitLock(ms) の上限がそこそこ短い

待ち時間の上限はミリ秒で指定するけど、現実的に長く待たせるユースケースには向いてない。

  • 並列実行が増えると、待たされる側は普通にタイムアウト例外で死ぬ
  • リトライを書いていないと、その実行ぶんのタスクはただ消える

「大量タスクを順に捌く」みたいなのを LockService だけで実現しようとすると、ここで詰む。

3. 「順番待ちっぽく見える」だけのカラクリ

結局のところ、

  • 鍵を取れた1つだけが動く
  • 残りは鍵が空くのを待つ
  • 空いたら誰か1つが取る(誰かは未定義)

これを外から見ると「ちゃんと順番に処理されてる気がする」となる。同時実行が少ない&処理が一瞬で終わる場合は、たいてい結果的に到着順っぽく動くので、ますます気付かない。

自分はここでずっと「キューだな〜」と思っていた。違いました。


じゃあ本物のキューが必要なときは?

正直に書くと、自分のユースケースでは本物のキューが必要な案件は今のところ無かった。同時実行を防いで「ちょっと順番待ち」したい程度なら、LockService で必要十分だった。

ただ、もし「順序を厳密に守って大量タスクを捌きたい」が出てきたら、選択肢としてはこのあたりになりそう。

  • スプレッドシート+定期トリガー+LockService
    待合室をスプシにして、トリガーで1件ずつ消化。LockService は「定期トリガーの重複実行防止」に使う
  • GCP Cloud Tasks
    GASの6分上限を超えて本格的に順序・リトライをやるならこっち

要は、

  • 同時実行を捌く番人が欲しい → LockService
  • タスクを並べて順に処理したい → キュー(自作 or Cloud Tasks)

役割が違うので、片方で済むかは要件次第。


まとめ

  • LockService は キュー(行列)ではなく排他制御(鍵)
  • FIFO は保証されていない
  • 「順番待ちっぽく見える」のは結果論で、設計の前提にしてはいけない
  • 同時実行を防ぎたいだけなら LockService で十分。順序保証や大量処理が必要なら、別途キューの仕組みを足す

「キューだと思って使ってる」のと「鍵だと知って使ってる」のは、見た目同じコードでも事故ったときの怖さが全然違う。同じ勘違いをしていた人の参考になれば。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?