2014-09-16

無限リストビュー

ここでクイズ。

Salesforceのリストビューは1オブジェクトにつき最大何件まで保持することができるでしょうか??

  1. 1,000

  2. 10,000

  3. 100,000

  4. 根性が続くまで

  5. Salesforceに怒られるまで

 

ということで検証してみました。

ちなみにリストビューの件数制限に関してはSFDCのhelpには記載されておりません(多分)

 

検証方法1. Eclipseでメタデータ直接いじる

Eclipseで対象オブジェクトのメタデータを抽出

→適当なスクリプトでリストビューのXMLをガツっと入れて保存

と最も手軽に試せる方法。

 

Pythonだとこんな感じのスクリプトを書く

for num in range(0, 10):
    print("""<listViews>
<fullName>TestView%09d</fullName>
<filterScope>Everything</filterScope>
<label>TestView_%09d</label>
</listViews>""" % (num, num))

 

これを使って生成したテキストを***.objectの中にガツっと入れてSave to Serverする。

inf-listview-eclipse-flow

 

 

1万件くらいの保存だと5-10分程度で保存可能。

ただし10万件とかになるとEclipseのヒープサイズの方でエラーになってくるので

この方法ではリストビューの限界を調査するのが難しそう。ということで一旦別の方法を検討。

 

検証方法2. CRUDベースのMetadataAPIを使ってチマチマ入れる

CRUDベースのMetadataAPI使って最大10件ずつこまめに作成する方法です。

 

Pythonだとこんな感じのスクリプトを組めばOK。

SessionIDはログイン状態のCookieから奪うなり何なりして取得してください。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib.request
import urllib.error

BASE_URL = "https://na12.salesforce.com" #対象の環境のベースURLを入力

f = open("create_metadata_base.xml")
payload = f.read().replace("{{sessionId}}", "Input SessionID")
f.close()

f = open("listview_base.xml")
base = f.read()
f.close()


#ユーザ属性の取得
try:
    max_size = 100000
    temp_lists = []
    for i in range(max_size):
        temp_lists.append(base.replace('{{number}}', '%09d' % i))
        if i%6 == 5 or i == max_size-1:
            req = urllib.request.Request(
                url=BASE_URL + "/services/Soap/m/28.0",
                headers={
                    "SOAPAction": '""',
                    "Content-Type": "text/xml"
                },
                data=payload.replace("{{body}}", "".join(temp_lists)).encode(),
                method="POST"
            )
            res = urllib.request.urlopen(req)
            print(res.read().decode())
            temp_lists = []
except urllib.error.HTTPError as e:
    print(e.read())
    print(e.reason)

 

create_metadata_base.xml

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">
      <sessionId>{{sessionId}}</sessionId>
    </SessionHeader>
  </soap:Header>
  <soap:Body>
    <create xmlns="http://soap.sforce.com/2006/04/metadata">{{body}}</create>
  </soap:Body>
</soap:Envelope>

 

listview_base.xml

<metadata xsi:type="ListView">
  <fullName>Account.TestView{{number}}</fullName>
  <label>TestView_{{number}}</label>
  <filterScope>Everything</filterScope>
  <columns>ACCOUNT.NAME</columns>
  <columns>ACCOUNT.CREATED_DATE</columns>
</metadata>

 

本来は一回のcreateMetadataコールで10個までのメタデータを作成できるんですが、

なぜか以下のエラーが発生して6個くらいしか一気に作成できず…。※6個でもたまにエラる。

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sf="http://soap.sforce.com/2006/04/metadata">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>sf:UNKNOWN_EXCEPTION</faultcode>
      <faultstring>UNKNOWN_EXCEPTION: Async job could not be executed</faultstring>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

 

forumの方にはこんな記事が上がってますがAPIバージョン上げ下げしても結果変わらず…。

この方法だと1日あたり15,000回のAPIコール数(Dev)で一回あたり6リストビューなので

一日最大90,000件のリストビューを作成可能ということになります。

とはいえ何十万件までいけるか検証するには時間がかかる…。ということで別の方法を検討。

 

検証方法3. antで保存

1の方法でEclipseではなくantでデプロイする。

デプロイ対象はリストビューのみ。

 

スクリプトはこんな感じ

from subprocess import check_call

for i in range(0, 5):
    f = open("retrievedUnpackaged/objects/Contact.object", "w")
    print("""<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">""", file=f)

    for num in range(i*100000, (i+1)*100000):
        print("""<listViews>
<fullName>TestView%09d</fullName>
<filterScope>Everything</filterScope>
<label>TestView_%09d</label>
</listViews>""" % (num, num), file=f)

    print("</CustomObject >", file=f)
    f.close()
    check_call("ant deployUnpackaged")

 

package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
  <types>
    <members>*</members>
    <name>ListView</name>
  </types>
  <version>29.0</version>
</Package>

 

build.xml

<project name="Sample usage of Salesforce Ant tasks" default="test" basedir="." xmlns:sf="antlib:com.salesforce">
  <property file="build.properties"/>
  <property environment="env"/>

  <!-- Deploy the unpackaged set of metadata retrieved with retrieveUnpackaged -->
  <target name="deployUnpackaged">
    <sf:deploy username="${sf.username_dst}" password="${sf.password_dst}" serverurl="${sf.serverurl_dst}" maxPoll="${sf.maxPoll}" deployRoot="retrieveUnpackaged" rollbackOnError="true" pollWaitMillis="60000"/>
  </target>
</project>

 

10万件ごとにメタデータファイル作成→antデプロイをひたすら繰り返します。

 

検証方法1のEclipseパターンでも結局FileベースのMetadataAPIをコールしていることから

package.xmlを書き換えちゃえば同様の事が手動で出来ます。

 

この方法だとEclipseと違って10万件を保存しようとしてもヒープサイズで落ちることなくリリースできます。

リリース状況こんな感じになります。10万コンポーネントのデプロイw

inf-listview-release-status

 

リリース時間は10万件当たり2〜3時間程度でAPIコール数の消費も少ないということで検証2より効率がよく

検証1より多くの件数を保存できそうだったので、今回はこの方法で何件までいけるかを試しました。

 

現時点での限界値

上記でリリース時間10万件あたり2~3時間程度と記載しましたが、実は”最初の10万件”の話で

リストビューが増えていくにつれてコンポーネントのロード(リリースが始まる前準備)の時間がどんどん増えていき

60→70万件までのリストビュー作成では10時間かかるハメに…。

ということで現状70万件まで作成できました。

inf-listview-result

 

コレ以上は

・時間がかかりすぎる

・そろそろどっかから怒られそう

という理由で作成を断念。

 

DeveloperEditionの最大レコード数は2500件(5MB÷2kb)とかそこらだったので

レコード件数の300倍リストビューを作成できることになりますw

 

冒頭クイズの正解は今のところは「4. 根性が続くまで」ですが

やり過ぎると怒られること必至なので「5. Salesforceに怒られるまで」が正解!

 

ちなみにリストビューを確認するときにmac mini(昨年購入のスペック)+Chromeだとなぜかフリーズしちゃうので

Windows + Chromeの組み合わせがオススメです。

70万件のリストビューだとオブジェクトのホーム画面でgzip圧縮で3.7MB、実サイズ40MBありました。

inf-listview-size

ちなみに件数多いとオブジェクトのホーム画面になかなかたどり着けません。

inf-listview-time-error

 

良い子は真似しないように!

 

このエントリーをはてなブックマークに追加