kintoneの限界を知る

この記事は、[kintone Advent Calendar 2015](http://qiita.com/advent-calendar/2015/kintone)参加の記事です。

# 己の限界を知る
kintone楽しいですよね？
Advent Calendarにも連日、システム連携やkintoneの便利な機能の紹介など、楽しい記事が掲載されています。

でも、それでいいんですか？

例えば、お酒を飲むときは己の限界を知った上で飲むのが大人というものですよね？
スポーツ選手は、今の自分の限界を知った上で、そこを越えていく練習をするわけですよね？

そう、我々もkintoneの限界を知る必要があるのです。

# 限界を知ってどうするのか？
もちろん、圧力です。
（圧力の詳細は、[この記事](http://itpro.nikkeibp.co.jp/atcl/column/14/346926/022700183/)を参照してください）

kintoneにより便利になってほしい、より高度なことができるようになってほしい、M◯のPowerAppsなんかに負けてほしくない、という願いを込めて、kintoneに己の限界を超えてもらうべく、サイ◯ウズさんに圧力をかけるわけです。

# 限界その1（サブテーブルの行数）
kintoneは、データ構造中にサブテーブルが持てて便利ですよね。
Master-Slave型のデータ構造が簡単に表現できます。

でも、このSlave側行数が増えるとどうなるか、ご存知ですか？

例えば、こんなコードでがっつりサブテーブルに行を入れてみます。

``` JavaScript
for(var i = 0; i < 100; i++ ){
	record.record.subTable.value.push(
                {
                    'value': {
                        'no': {
                            'type' : 'SINGLE_LINE_TEXT',
                            'value': ''
                        },
                        'price': {
                            'type' : 'NUMBER',
                            'value': price
                        },
                        'remarks1': {
                            'type' : 'SINGLE_LINE_TEXT',
                            'value': remarks1
                        },
                        'remarks2': {
                            'type' : 'SINGLE_LINE_TEXT',
                            'value': remarks2
                        },
                        'remarks3': {
                            'type' : 'SINGLE_LINE_TEXT',
                            'value': remakrs3
                        },
                        //列はもっとある
                    }
                });
}

// これが鬼門
kintone.app.record.set(record);
```

はい、死亡しましたね。
このデータを開くと、画面に行がぴろぴろ表示されていくのが見えます。

しかも、```kintone.app.record.set()```というJavaScriptから変更したレコードを画面に反映するこの関数、すごい遅いです。
100行追加したら、軽く数分帰ってこないことがあります。

## こうしてほしい
リバースするほど解析したわけではないですが、ぴろぴろ表示されるということは、データを読みながらDOMを更新してるんじゃないかと推測されます。
そうなると、都度reflowが起きるので遅くなるんじゃないかと。
更新する部分はフラグメントにしておいて、あとで一気にDOMに追加する形になれば速くなるんじゃないかなと。

これ速くなると喜ぶ人多数いると思います。ね、サイ◯ウズさん


# 限界その2（UpSertは慎重に）
kintoneでJSカスタマイズしていると、UpSert処理をよく使います。
UpSert処理というのは、あるデータがあれば更新、なければ挿入というやつですね。

```Promise``` 使って、こんな感じのコード書く方多いと思います。

``` JavaScript
// 同じキーのデータがあるか検索する
kintone.api("/k/v1/records", "GET", searchParam).then(function (searchResp) {
	if (searchResp.totalCount === "0") {
		// ないのでPost（=挿入）する
		return kintone.api("/k/v1/record", "POST", postData).then(function (postResp) {
			console.log("Post result:" + JSON.stringify(postResp));
		});
	} else {
		// あるのでidを設定してPut（＝更新）する
		postData["id"] = loopResp.records[0].$id.value;
		return kintone.api("/k/v1/record", "PUT", postData).then(function (putResp) {
			console.log("Put result:" + JSON.stringify(putResp));
		});
	}
});
```

ここで、最初の検索で、2件ヒットしたらどうなるでしょうか？
（2件ヒットさせる時点でプログラムが間違っているわけですが・・・）
下の更新の場合に```records[0]```で１つ目のid使ってるので問題ないように見えますよね？

これ、kintoneが、「不正なリクエストです」って返す場合があります。

理由は・・・ここには書けませんが、何か裏でkintoneがヒーヒー言っちゃうようです。
これが起きると、なぜかしばらくスペースにコメントが書き込めなくなったりもします。

## こうしてほしい
2件ヒットさせる私が悪いです。すいません。
だけど、2件ヒットしても大丈夫にしてほしい。
（おそらく、これが解消されるとkintoneのパフォーマンスが上がる）

# 限界その3（Chromeだって神じゃない）
これは、kintoneの限界というより、Chromeの限界です。でもkintoneでコード書いてると無意識にこの限界に到達することがあります。

例えば、以下のようなコード

``` JavaScript
var listA = ["A", "B", "C", "D", "E",.....]; // 7000個要素がある

return kintone.Promise.all($.map(listA, function(aItem, index){
	return asyncFunctionForEachItem(aItem); // これはエラーになる
})).then(function(){
	// ここはlistAの要素全てに対する非同期呼び出しが終わってから呼ばれる
});;

```

これChromeではエラーになります。

- ```$.map()```は全要素を非同期に一斉に処理しようとする
- 非同期呼び出し内で外部のAPIの呼び出しがあると、7000個を同時に呼ぶことはできないのでブラウザ内で待ち行列が作られて順次処理される
- Chromeの場合は、この待ち行列用に確保できるメモリが25MBまでと決まっている（変更もできないハードコーディング）
- 25MBでおよそ6000個に相当するため、これを超える呼び出しを行うと、```net::ERR_INSUFFICIENT_RESOURCES```というエラーが続発する

## こうしてほしい
Chromeがんばれとしか言いようがない・・・ちなみに、Firefoxだと意外といけたりします。
kintoneの限界じゃなかったですね、すいません。
でも、ふんふん♪てコード書いてるとあっさりこの限界を迎えることがあります。

# まとめ
disりたいわけじゃないです。
kintoneをもっと良くしたいんです。

この想いが、サイ◯ウズさんに伝われば光栄です。

明日は、ミスターkintone ジョイゾーの四宮さんです。