これまでのバージョンで、リモートデータストアやクライアント/サーバー構成で作業する際のパフォーマンスを向上させるため、ORDA RESTリクエストが自動的に最適化されることを知りました。
また、ORDA RESTリクエストの自動最適化を利用するために、コンテキストを使用できることも学びました。
これは重要なステップでしたが、今度は RESTリクエストの動作を完全に制御することを提案します。パフォーマンスは戦略的な問題なので、この新機能をぜひ活用してください!
それだけではありません。問題を理解しデバッグするのに役立つ新しいツールも利用できるようになりました。
詳細については、引き続きこのブログ記事をお読みください。
HDI: ORDAキャッシュの管理とRESTリクエストの最適化
コンテキストがなんであるか、覚えていますか?
始める前に、ここで簡単にまとめておきます:
- エンティティセレクションで作業する際には、4D は “学習” を経て、自動的に最適化されたリクエスト (必要な属性のみをサーバーに要求) をトリガーします。
- コンテキストを使って、その最適化を持続させ、他のエンティティセレクション (またはエンティティ) で作業するときに再利用することができます。
ORDAキャッシュについてご存知でしょうか?
ORDA でサーバーにデータを要求すると、そのデータはクライアントマシンの ORDAキャッシュに入れられます。
ORDAキャッシュはデータクラスごとに管理されています。読み込まれたエンティティは、要求された属性の内容を含むオブジェクトとして ORDAキャッシュに格納されます。
コンテキストとORDAキャッシュの詳細については、Summit 2020のセッション (英語) をご覧ください。
新たなステップ: コンテキストを完全に制御する
ご理解のとおり、コンテキストの属性は 4D の学習により定義されます。データストアのおかげで、既存のコンテキストにどのような属性を含めるかを .setRemoteContextInfo() 関数で指定できるようになったことが大きな前進です。
例題
この例題では、Persons データクラスの firstname と lastname 属性を contextA とういう名のコンテキストに入れています。
これにより、all() 関数を呼び出したとき、最初の Personsエンティティは (学習が必要な場合とは異なり) 完全にはロードされません。サーバーに送信されるリクエストは、すでに完全に最適化されているからです。
var $ds : 4D.DataStoreImplementation
var $contextA : Object
var $persons : cs.PersonsSelection
var $p : cs.PersonsEntity
var $text : Text
$ds:=Open datastore(New object("hostname"; "school.acme.com"); "schools")
$ds.setRemoteContextInfo("contextA"; "Persons"; New collection("firstname"; "lastname"))
$contextA:=New object("context"; "contextA")
$persons:=$ds.Persons.all($contextA)
$text:=""
For each ($p; $persons)
$text:=$p.firstname+" "+$p.lastname
End for each
リストボックスについて
なお、$persons のエンティティセレクションをリストボックスで使用する場合、“ページモード” コンテキストで必要な属性を指定することができます。
以下の例では、Persons データクラスの firstname と lastname 属性がリストボックスのコンテキストに含まれています。
エンティティを選択すると、カレント項目コンテキスト (firstname, lastname, children, gender) の属性が直ちにロードされます。
最初のエンティティが完全にロードされることを要求する “学習” はもう必要ありません。
var $contextPersons : Object
var $listAttributes; $pageAttributes : Collection
$contextPersons:=New object("context"; "persons")
$listAttributes:=New collection("firstname"; "lastname")
Form.ds.setRemoteContextInfo("persons"; Form.ds.Persons; $listAttributes) //Form.ds はリモートデータストアです
$pageAttributes:=New collection("firstname"; "lastname"; "children"; "gender")
Form.ds.setRemoteContextInfo("persons"; Form.ds.Persons; $pageAttributes; "currentItem")
Form.persons:=Form.ds.Persons.all($contextPersons) // Form.persons がリストボックスに表示されます
エンティティセレクションのページ長を処理する
エンティティセレクションのリクエストにあたっては、ページ長を設定できることに留意してください。良いことに、これはリレートエンティティズ型の属性にも適用されます。
以下の例では、Address エンティティが 100件のページ長で city 属性指定でサーバーに対して要求されています。
また、各 Address エンティティについては、リレートエンティティズ型の persons属性 のエンティティセレクションが、firstname とlastname 属性指定、50件のページ長 で要求されます。
var $ds : 4D.DataStoreImplementation
var $contextA : Object
var $addresses : cs.AddressSelection
var $a : cs.AddressEntity
var $p : cs.PersonsEntity
var $text : Text
$ds:=Open datastore(New object("hostname"; "school.acme.com"); "schools")
$ds.setRemoteContextInfo("contextA"; $ds.Address; "city, persons:50, persons.lastname, persons.firstname"; "main"; 100)
$contextA:=New object("context"; "contextA")
$addresses:=$ds.Address.all($contextA)
$text:=""
For each ($a; $addresses)
$text:=$text+"/ "+$a.city
For each ($p; $a.persons)
$text:=$text+" - "+$p.firstname+$p.lastname
End for each
End for each
ORDAキャッシュ
その他、ORDAキャッシュのタイムアウトや最大サイズを扱うための便利なツールや、ORDAキャッシュの内容を調査する手段も提供されています。
より詳細な情報については、ドキュメントウェブサイトを参照ください。
たとえば、リクエストの頻度に適応するように ORDAキャッシュのタイムアウトを変更することができます。これは、データが頻繁に変更される可能性があるかどうかが、あらかじめわかっている場合に便利です。
例題
以下の例では、Cities データクラスに郵便番号と都市情報が含まれており、これらは頻繁には変更されないため、タイムアウトが延長されています。
var $ds : 4D.DataStoreImplementation
$ds:=Open datastore(New object("hostname"; "school.acme.com"); "schools")
// エンティティの有効期限は 3時間です
// Cities データクラスのキャッシュには最大 350件のエンティティが含まれます
$ds.Cities.setRemoteCacheSettings(New object("timeout"; 10800; "maxEntries"; 350))
メモリを節約するために、データクラスごとに、キャッシュに含めるエンティティの最大数を更新することもできます。
コンテキストの調査とリセット
この魅力的な主題を追求するには、ドキュメントを参照ください。
重要: 完全に理解し、デバッグするためには、おそらくリクエストを調査する必要があることに留意してください。
もうひとつ
この機能とはあまり関係ありませんが、価値のある機能として、データクラス内のエンティティ数を取得するために dataClass.getCount() 関数が利用できるようになりました。
dataClass.all().length を呼び出す必要がなくなることにより、サーバー上でエンティティセレクションを構築したり、先頭エンティティをクライアントにフルロードしたりすることもなくなります。
var $count : Integer
$count:=ds.Persons.getCount()
HDI と SUMMIT 2020 のデモを触ってみましょう
実際の動作を確かめるには、HDI と Summit 2020 の セッションデモ をダウンロードして触ってみましょう。