Help us understand the problem. What is going on with this article?

Google Apps Script で並列処理をしたい 2

背景と概要

2019 年 4 月 8 日の Google Apps Script Project のアップデートにより、これ以降に作成した GAS プロジェクトで Apps Script API を使用するためには Cloud Platform Project と GAS プロジェクトをリンクする必要が発生し、これにより設定が少し複雑になりました。このため、ここでは設定が簡単な Web Apps を使った並列処理を提案させていただきます。これに関する問い合わせが多かったこともあり、こちらでもご紹介させていただきます。

以前紹介させていただきました Google Apps Script API を使用した並列処理はこちらでご覧頂けます。

fetchAll について

初めに、 UrlFetch サービスに追加されたfetchAll メソッドについて簡単に記載させていただきます。fetchAll メソッドの使い方を見ても動作状態などは書かれていませんでしたので、実際に調べてみようと次のような実験を行いました。

  • Web Apps を 5 つデプロイ
    • 動作は 5 秒のスリープ
  • デプロイした 5 つの Web Apps へのコールをリクエストとして fetchAll メソッドで実行

この結果、UrlFetchApp.fetchAll()は総実行時間は 5 秒程度だったのに対して、従来のUrlFetchApp.fetch()では総実行時間は 25 秒程度でした。これは fetchAll メソッドが非同期で実行していることを意味します。この結果を得たことで並列処理に応用してみようと考えました。

詳細、並びに使用したスクリプトはこちらの gistでご覧いただけます。

GAS を用いた並列処理

fetchAll メソッドが非同期で動作することが確認できたことで、この fetchAll メソッドと ここでは Web Apps を利用してネイティブ GAS による並列処理を行うために Google Apps Script 用のライブラリとして RunAll(GitHub)をアップデートしました。スクリプト自体はシンプルにも関わらずライブラリとして作成した理由は、クライアント側のスコープの自由度を維持したいと考えたためです。この意味の詳細はこちらをご覧ください。

RunAll

ライブラリ自体は、Google Apps Script API を使った並列処理のためのメソッドと、Web Apps を使った並列処理のメソッドの 2 つを用意しています。ここでは、後者の Web Apps を使った並列処理について紹介させていただきます。

RunAll (https://github.com/tanaikech/RunAll)を使用するまでの手順は下記の通りです。

1. スタンドアロンスクリプトタイプあるいはバウンドスクリプトタイプのプロジェクトを用意する

こちらへアクセスしてhttps://script.google.com/新規スクリプト(スタンドアロンタイプ)を作成することも可能です。

2. ライブラリ(RunAll)をインストールする

インストール方法はこちらです。

  • ライブラリのプロジェクトキーは 1FWYhQFhL7UIAZJn-FR3TlcHvXwHPJc2HwI4vtmNUAQv2OybGe-S97Lal です。

3. Web Apps をデプロイする

  1. スクリプトエディタ上で「公開」 -> 「ウェブアプリケーションとして導入」を選択してダイアログを開く。
  2. 「次のユーザーとしてアプリケーションを実行:」を「自分」、「アプリケーションにアクセスできるユーザー:」を「自分だけ」に設定する。
    • この設定では、オーナー本人からのアクセスのみです。他者からのアクセスはできません。
    • 「プロジェクト バージョン:」へ適当な文字列を入れてバージョンに説明を付けることも可能です。入れなくても問題ありません。
  3. 「承認が必要です」というダイアログが表示されると、許可を確認し、使用するスコープを承認してください。
    • ここで使用するスコープは次の通りです。
      • https://www.googleapis.com/auth/drive.readonly : Web Apps へのアクセスに使用
      • https://www.googleapis.com/auth/script.external_request : 各エンドポイントへのアクセスに使用
  4. 承認が完了すると、承認のためのダイアログが閉じて「現在のウェブ アプリケーションの URL」が表示されたダイアログが出ます。ここで、「ウェブ アプリケーションで最新のコードをテストします。」の「最新のコード」の URL をコピーしておきます。
    • URL はこのようなものです。https://script.google.com/macros/s/###/dev
  5. OK ボタンを押して設定を終了します。

この設定では Web Apps をデプロイしたプロジェクト内のスクリプトから、デプロイした Web Apps へアクセスする流れです。

4. サンプルスクリプトをコピーペーストする

下記のスクリプトを今開いている Web Apps をデプロイしたスクリプトエディタへ入れて下さい。このとき、スクリプト内のurlへ先ほどコピーしたhttps://script.google.com/macros/s/###/devをセットしてください。

function myFunction(e) {
  Utilities.sleep(1000);
  return e;
}

function doPost(e) {
  return RunAll.RunFunctionsByDoPost(this, e);
}

function main() {
  var url = "https://script.google.com/macros/s/###/dev"; // Here, please set the URL of Web Apps.
  var token = ScriptApp.getOAuthToken();
  var resource = [
    {
      functionName: "myFunction",
      arguments: "sample parameter 1",
      webAppsURL: url,
      accessToken: token
    },
    {
      functionName: "myFunction",
      arguments: "sample parameter 2",
      webAppsURL: url,
      accessToken: token
    },
    {
      functionName: "myFunction",
      arguments: "sample parameter 3",
      webAppsURL: url,
      accessToken: token
    }
  ];
  var res = RunAll.DoWebApps(resource);
  res.forEach(function(r) {
    Logger.log(r.getContentText());
  });
}

実行した結果は下記の通りです。

{"FunctionName":"myFunction","Arguments":"sample parameter 1","Result":"sample parameter 1"}

{"FunctionName":"myFunction","Arguments":"sample parameter 2","Result":"sample parameter 2"}

{"FunctionName":"myFunction","Arguments":"sample parameter 3","Result":"sample parameter 3"}
  • main()を実行することで非同期でmyFunction()が 3 回実行されます。
  • 実際に実行してみると、同期実行の場合は少なくとも 3 秒以上経過しますが、この方法では 1.6 秒程度でした。

制限

  • Web Apps を使用していますので、この仕様により、与える引数と返される値は文字型である必要があります。これが制限の一つです。

  • 一度に実行できる最大ワーカー数は 30 です。ただし、30 丁度で実行させると、時々 1 あるいは 2 つエラーが返されますので、28 を最大値にする方が安心かもしれません。参考

参考

tanaike
Google Developer Expert (GDE) in G Suite
https://tanaikech.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした