開発者のヒントとコツ
2025年5月
キャッシュサービス
Vantiqアプリケーションをしばらく開発してきた方なら、この言葉はご存知でしょう。もしかしたら、枕に刺繍したり、壁掛けの「Live, Laugh, Love」を消して、代わりにこんな言葉を書いたりしたことがあるかもしれません。
"パフォーマンス
優勢である
「粘り強さ」です。
もちろん、Vantiqの状態管理機能を活用してリソースを大量に消費するデータベースとのやり取りを回避することが、アプリケーションシステムにおけるリアルタイムな応答性を実現する上で最適であるという意味です。このスローガンは、他の意味に解釈することはできません。
サービス状態管理
サービスは、アプリケーションロジックの実行に必要な状態を維持します。この状態にレプリケーション係数を設定することで、フォールトトレランスを強化できます。ビジュアルイベントハンドラー内の複数のアクティビティタスクはプログラム状態を利用し、サービスは開発者が実行して状態を管理できる手順を自動的に生成します。
データベース相互作用の軽減
状態は実行中のアプリケーションの「作業用」メモリとして役立ちますが、アプリケーションでも追加情報を検索したり、後で参照するためにデータベースに何かを保存したりする必要がある場合があります。サービスには、データベースの読み取りと書き込みを最小限に抑えるツールがあります。その一例がCachedEnrichです。これは、データベースの読み取り操作を一定期間メモリ内に保持します。これにより、その期間内の将来の検索では、新しい読み取りではなく、メモリ内のデータが使用されます。スケジュールされたプロシージャは、自動化された時間間隔で非同期的に状態を保持できます。そしてもちろん、開発者は、入ってくるすべてのイベントを保持するよりも賢明な方法を知っています。選択的に、後で取得するために役立つものだけを保持してください。
キャッシュされたサービス
Vantiqが提供する、タイミングの悪い、あるいは過剰なデータベース操作からアプリケーションのパフォーマンスを保護するための新たな機能をご紹介します。新しいサービスを作成するたびに、サービスの種類を選択するように求められます。

Foundationsクラスでは、(きっとご丁寧に)キャッシュサービスを無視し、「通常」の内容を優先していましたが、キャッシュサービスは「データベースインタラクションミニマリズム」において強力なツールであることが判明しました。そのため、注目に値します。
「新しいキャッシュ サービス」の選択肢をクリックすると、すぐに別の選択肢が表示されます。

したがって、キャッシュ サービスには次の 2 種類があります。
ルックアップキャッシュ:
これは、データベース内に既に存在し、頻繁に参照されるものの、それほど頻繁に変更されない情報に最適です。言い換えれば、これはCachedEnrichとほぼ同じ動作をします。
選択したタイプには、一意のキャッシュキーが必要です。これは、そのタイプに格納されているレコードを一意に識別する、一意のプロパティまたはプロパティセットです。
サービスが開くと、自動生成されたサービスパブリックプロシージャが既に作成されていることがわかります。不思議なことに、このプロシージャは「生成済み」リストには表示されません。これは、開発者がプログラムの必要に応じてプロシージャに変更を加えることが推奨されているためです。このコードを少し「軽く読んで」みると、このプロシージャが期待どおりに動作することがわかります。
- 目的のレコードがすでに状態に存在するかどうかを確認します
- そうでない場合は、タイプから選択して状態に追加します。
- 目的のレコードを返す

キャッシュを更新:
このタイプのキャッシュサービスは、スケジュールされたプロシージャのように動作し、開発者は標準タイプのアップサートを非同期的に実行する頻度を設定できます。最小間隔は1分ごとですが、「週ごと」に設定することもできます。

ルックアップ キャッシュと同様に、更新キャッシュでは、その型への書き込みを実行するために一意のキャッシュ キーが必要です。

新しいサービスが開くと、次の 3 つのサービス プロシージャがすでに記述されていることがわかります。

「GetBy」手順はルックアップ キャッシュから確認したので、このサービスをルックアップ キャッシュとしても使用できます。
「UpdateBy」プロシージャは、皆さんが想像しているものとは違います!データベースへの書き込みは行わず、State 内の型レコードのみを更新します。
「WriteAll」は、Stateパーティション内のすべてのレコードを収集し、それらのレコードすべてに対して一括アップサート操作を一度に実行します。「悲観的ロック」モデル(このStateは頻繁に更新されることを前提としています)を使用して、Stateパーティション内の現在のレコードを収集した後、このプロシージャはコレクションのクローンを作成し、その後はクローンのみを使用して処理を行います。Stateパーティションはそのままで、次回のWriteAll実行に向けて変更が継続されます。
ユースケース #1: CachedEnrich をキャッシュサービス手順に置き換える
Foundations クラスのこのビジュアル イベント ハンドラーを覚えていますか?

ポンプセンサーの読み取り値を取得した後、PumpIdで結合し、このVEHに送信しました。左端のブランチは異常な読み取り値をフィルタリングし、ポンプの位置情報を追加します。 ポンプの詳細 入力して悪い知らせを送信し、別のサービスで対処します。 詳細を追加 不正な読み取りをフィルタリングする直後のタスクは、 キャッシュされたエンリッチ代わりにキャッシュ サービス プロシージャを使用しましょう。
ステップ1: キャッシュサービスを作成する
「追加」メニューから「サービス」を選択し、「新しいキャッシュサービス」→「キャッシュサービス」を選択します。これは単なるルックアップサービスです。

ステップ2: VEHから手順を実行する
まずは小さなステップがあります。 GetBy_PumpId 新しいキャッシュサービスの手順を見ると、PumpIdによる選択が既に行われていることがわかります。つまり、上流のSplitByGroupタスクを使用する必要はありません。このブランチを削除し、イベントストリームから開始する新しいブランチを作成します。例:

これで、作業中のブランチが中央に移動しました。新しい「Procedure」タスクをフィルターに追加しましょう。

…そして、PumpDetailsCacheの「GetBy…」プロシージャに設定します。パラメータは「event.PumpId」に設定してください。このプロシージャタスクを、 詳細を追加 CachedEnrichタスクでは、 返品行動 〜へ 戻り値を returnProperty にアタッチする、そのプロパティに名前を付けます ポンプの詳細 そのようです:

その後、 住所検索 へのタスク 手順 タスクを削除し、 詳細を追加 タスク。

新しい VEH を実行すると、以前と同じように動作します。

しかし、なぜ?
すばらしいです、 あなたは考えています。 作成してそのサービス用のプロシージャを呼び出す必要があったため、動作していたCachedEnrichを置き換えました。これにより、どのようなメリットがあるでしょうか? ああ、聞いてくれて本当に嬉しいです。
CachedEnrich を設定する際に、更新間隔を設定する必要があることを思い出してください。そうでない場合は、デフォルトの 15 時間のままにしておいてください。もちろん、アプリケーションの実行開始から 45 分後に同僚が型を更新した場合、変更がアプリケーションに反映されるのはさらに XNUMX 分後になります。間隔を短くすると、不要なデータベース読み取りが負荷に追加される可能性があります。型の変更を検知し、変更後すぐにキャッシュをクリアする方法があればなお良いでしょう。
もしも… ああ、待てよ、あるんだ。キャッシュサービスに戻って、型への書き込みをリッスンするイベントハンドラーを作成し、キャッシュを消去できるようにしよう。
まず、ソースイベントハンドラ(実装タブ)を追加して、 書き込み時にクリーンアップします。 新しいイベントストリームの設定で、 inboundResourceとして、 ポンプ.モニター.ポンプの詳細 inboundResourceIdとして、 アップサート OPとして:

…そして、キャッシュを消去する手順をリンクできるようになりました。

この後、PumpDetails タイプが実際に変更された場合にのみ状態が更新されます。
ユースケース #2: 一定の間隔で自動的に型の状態をデータベースに書き込む
ユースケース1で使用した分析サービスのVEHはまだ終わりではありません。 状態配列 タスクは、各ポンプからすべての読み取り値を収集するマルチパーティション手順であり、その後、 ホールド状態 タスクはAccumulateStateタスクであり、後で使用できるようにStateに保持されます。 分析レポート クライアント。この StateArray をデータベースに保存しておくことにしました…時々。
ステップ1: データを保持するための標準型を作成する
現在、VEHに取り込まれているのはスキーマ型です。プロジェクトコンテンツでその型の横にあるコンテキストメニューをクリックして複製を作成し、今度は標準型として保存します。私の場合は「PumpStateType」という名前にしました。
ステップ2: 標準タイプに基づいてキャッシュサービスを作成する
今回はUpdate Cacheです。最初は1分に1回間隔を設定しましたが、後で変更できます。Cache Keyは引き続きPumpIdで、これはこの型の一意のインデックスであり、自然キーでもあります。
ステップ3:「WriteAll…」スケジュールを確認する

ご覧の通り、既に1分に設定されていますが、ここで変更できます。テスト目的なので、このくらい短く設定しています。
ステップ4: 型の状態を作成する
手順タスクを追加しました タイプ状態の作成 から ポンプステータスストリーム イベントストリーム。これは、このタイプのキャッシュサービスで「UpdateBy..」プロシージャを呼び出すように設定されています。パラメータは、キーのPumpId、イベントパラメータのイベント、isPartialの「false」です。

10 件のイベントの後、PumpStateType のレコード検索を実行しました。

…1分待ってリフレッシュしました:

このタイプのキャッシュ サービス内のスケジュールされた手順は完全に機能しています。
まとめ:
キャッシュサービスのように、標準型の状態と操作を保持する専用のサービスを持つことには、多くの利点があります。その一つは、単純に整理できることです。型用のサービス、ソース用のサービス、イベント処理用のサービス、AIエージェント用のサービスなどです。あらゆるものに適切な場所があり、すべてが適切な場所にあります。各サービスの目的と機能が明確に定義されていると、テストもはるかに容易になります。また、ある型に対するすべての操作が同じサービスで保持されていれば、アプリケーションシステムの動作を追跡するのもはるかに容易になります。
キャッシュ サービスは、アプリケーション システムの読み取り、テスト、スケーラビリティ、パフォーマンスを維持するのに役立つツールです。
添付ファイル:
あなたがでなければなりません
ログイン 添付ファイルを表示します。
開発者のヒントとコツ
2025年5月
キャッシュサービス
Vantiqアプリケーションをしばらく開発してきた方なら、この言葉はご存知でしょう。もしかしたら、枕に刺繍したり、壁掛けの「Live, Laugh, Love」を消して、代わりにこんな言葉を書いたりしたことがあるかもしれません。
もちろん、Vantiqの状態管理機能を活用してリソースを大量に消費するデータベースとのやり取りを回避することが、アプリケーションシステムにおけるリアルタイムな応答性を実現する上で最適であるという意味です。このスローガンは、他の意味に解釈することはできません。
サービス状態管理
サービスは、アプリケーションロジックの実行に必要な状態を維持します。この状態にレプリケーション係数を設定することで、フォールトトレランスを強化できます。ビジュアルイベントハンドラー内の複数のアクティビティタスクはプログラム状態を利用し、サービスは開発者が実行して状態を管理できる手順を自動的に生成します。
データベース相互作用の軽減
状態は実行中のアプリケーションの「作業用」メモリとして役立ちますが、アプリケーションでも追加情報を検索したり、後で参照するためにデータベースに何かを保存したりする必要がある場合があります。サービスには、データベースの読み取りと書き込みを最小限に抑えるツールがあります。その一例がCachedEnrichです。これは、データベースの読み取り操作を一定期間メモリ内に保持します。これにより、その期間内の将来の検索では、新しい読み取りではなく、メモリ内のデータが使用されます。スケジュールされたプロシージャは、自動化された時間間隔で非同期的に状態を保持できます。そしてもちろん、開発者は、入ってくるすべてのイベントを保持するよりも賢明な方法を知っています。選択的に、後で取得するために役立つものだけを保持してください。
キャッシュされたサービス
Vantiqが提供する、タイミングの悪い、あるいは過剰なデータベース操作からアプリケーションのパフォーマンスを保護するための新たな機能をご紹介します。新しいサービスを作成するたびに、サービスの種類を選択するように求められます。
Foundationsクラスでは、(きっとご丁寧に)キャッシュサービスを無視し、「通常」の内容を優先していましたが、キャッシュサービスは「データベースインタラクションミニマリズム」において強力なツールであることが判明しました。そのため、注目に値します。
「新しいキャッシュ サービス」の選択肢をクリックすると、すぐに別の選択肢が表示されます。
したがって、キャッシュ サービスには次の 2 種類があります。
ルックアップキャッシュ:
これは、データベース内に既に存在し、頻繁に参照されるものの、それほど頻繁に変更されない情報に最適です。言い換えれば、これはCachedEnrichとほぼ同じ動作をします。
選択したタイプには、一意のキャッシュキーが必要です。これは、そのタイプに格納されているレコードを一意に識別する、一意のプロパティまたはプロパティセットです。
サービスが開くと、自動生成されたサービスパブリックプロシージャが既に作成されていることがわかります。不思議なことに、このプロシージャは「生成済み」リストには表示されません。これは、開発者がプログラムの必要に応じてプロシージャに変更を加えることが推奨されているためです。このコードを少し「軽く読んで」みると、このプロシージャが期待どおりに動作することがわかります。
キャッシュを更新:
このタイプのキャッシュサービスは、スケジュールされたプロシージャのように動作し、開発者は標準タイプのアップサートを非同期的に実行する頻度を設定できます。最小間隔は1分ごとですが、「週ごと」に設定することもできます。
ルックアップ キャッシュと同様に、更新キャッシュでは、その型への書き込みを実行するために一意のキャッシュ キーが必要です。
新しいサービスが開くと、次の 3 つのサービス プロシージャがすでに記述されていることがわかります。
「GetBy」手順はルックアップ キャッシュから確認したので、このサービスをルックアップ キャッシュとしても使用できます。
「UpdateBy」プロシージャは、皆さんが想像しているものとは違います!データベースへの書き込みは行わず、State 内の型レコードのみを更新します。
「WriteAll」は、Stateパーティション内のすべてのレコードを収集し、それらのレコードすべてに対して一括アップサート操作を一度に実行します。「悲観的ロック」モデル(このStateは頻繁に更新されることを前提としています)を使用して、Stateパーティション内の現在のレコードを収集した後、このプロシージャはコレクションのクローンを作成し、その後はクローンのみを使用して処理を行います。Stateパーティションはそのままで、次回のWriteAll実行に向けて変更が継続されます。
ユースケース #1: CachedEnrich をキャッシュサービス手順に置き換える
Foundations クラスのこのビジュアル イベント ハンドラーを覚えていますか?
ポンプセンサーの読み取り値を取得した後、PumpIdで結合し、このVEHに送信しました。左端のブランチは異常な読み取り値をフィルタリングし、ポンプの位置情報を追加します。 ポンプの詳細 入力して悪い知らせを送信し、別のサービスで対処します。 詳細を追加 不正な読み取りをフィルタリングする直後のタスクは、 キャッシュされたエンリッチ代わりにキャッシュ サービス プロシージャを使用しましょう。
ステップ1: キャッシュサービスを作成する
「追加」メニューから「サービス」を選択し、「新しいキャッシュサービス」→「キャッシュサービス」を選択します。これは単なるルックアップサービスです。
ステップ2: VEHから手順を実行する
まずは小さなステップがあります。 GetBy_PumpId 新しいキャッシュサービスの手順を見ると、PumpIdによる選択が既に行われていることがわかります。つまり、上流のSplitByGroupタスクを使用する必要はありません。このブランチを削除し、イベントストリームから開始する新しいブランチを作成します。例:
これで、作業中のブランチが中央に移動しました。新しい「Procedure」タスクをフィルターに追加しましょう。
…そして、PumpDetailsCacheの「GetBy…」プロシージャに設定します。パラメータは「event.PumpId」に設定してください。このプロシージャタスクを、 詳細を追加 CachedEnrichタスクでは、 返品行動 〜へ 戻り値を returnProperty にアタッチする、そのプロパティに名前を付けます ポンプの詳細 そのようです:
その後、 住所検索 へのタスク 手順 タスクを削除し、 詳細を追加 タスク。
新しい VEH を実行すると、以前と同じように動作します。
しかし、なぜ?
すばらしいです、 あなたは考えています。 作成してそのサービス用のプロシージャを呼び出す必要があったため、動作していたCachedEnrichを置き換えました。これにより、どのようなメリットがあるでしょうか? ああ、聞いてくれて本当に嬉しいです。
CachedEnrich を設定する際に、更新間隔を設定する必要があることを思い出してください。そうでない場合は、デフォルトの 15 時間のままにしておいてください。もちろん、アプリケーションの実行開始から 45 分後に同僚が型を更新した場合、変更がアプリケーションに反映されるのはさらに XNUMX 分後になります。間隔を短くすると、不要なデータベース読み取りが負荷に追加される可能性があります。型の変更を検知し、変更後すぐにキャッシュをクリアする方法があればなお良いでしょう。
もしも… ああ、待てよ、あるんだ。キャッシュサービスに戻って、型への書き込みをリッスンするイベントハンドラーを作成し、キャッシュを消去できるようにしよう。
まず、ソースイベントハンドラ(実装タブ)を追加して、 書き込み時にクリーンアップします。 新しいイベントストリームの設定で、 inboundResourceとして、 ポンプ.モニター.ポンプの詳細 inboundResourceIdとして、 アップサート OPとして:
…そして、キャッシュを消去する手順をリンクできるようになりました。
この後、PumpDetails タイプが実際に変更された場合にのみ状態が更新されます。
ユースケース #2: 一定の間隔で自動的に型の状態をデータベースに書き込む
ユースケース1で使用した分析サービスのVEHはまだ終わりではありません。 状態配列 タスクは、各ポンプからすべての読み取り値を収集するマルチパーティション手順であり、その後、 ホールド状態 タスクはAccumulateStateタスクであり、後で使用できるようにStateに保持されます。 分析レポート クライアント。この StateArray をデータベースに保存しておくことにしました…時々。
ステップ1: データを保持するための標準型を作成する
現在、VEHに取り込まれているのはスキーマ型です。プロジェクトコンテンツでその型の横にあるコンテキストメニューをクリックして複製を作成し、今度は標準型として保存します。私の場合は「PumpStateType」という名前にしました。
ステップ2: 標準タイプに基づいてキャッシュサービスを作成する
今回はUpdate Cacheです。最初は1分に1回間隔を設定しましたが、後で変更できます。Cache Keyは引き続きPumpIdで、これはこの型の一意のインデックスであり、自然キーでもあります。
ステップ3:「WriteAll…」スケジュールを確認する
ご覧の通り、既に1分に設定されていますが、ここで変更できます。テスト目的なので、このくらい短く設定しています。
ステップ4: 型の状態を作成する
手順タスクを追加しました タイプ状態の作成 から ポンプステータスストリーム イベントストリーム。これは、このタイプのキャッシュサービスで「UpdateBy..」プロシージャを呼び出すように設定されています。パラメータは、キーのPumpId、イベントパラメータのイベント、isPartialの「false」です。
10 件のイベントの後、PumpStateType のレコード検索を実行しました。
…1分待ってリフレッシュしました:
このタイプのキャッシュ サービス内のスケジュールされた手順は完全に機能しています。
まとめ:
キャッシュサービスのように、標準型の状態と操作を保持する専用のサービスを持つことには、多くの利点があります。その一つは、単純に整理できることです。型用のサービス、ソース用のサービス、イベント処理用のサービス、AIエージェント用のサービスなどです。あらゆるものに適切な場所があり、すべてが適切な場所にあります。各サービスの目的と機能が明確に定義されていると、テストもはるかに容易になります。また、ある型に対するすべての操作が同じサービスで保持されていれば、アプリケーションシステムの動作を追跡するのもはるかに容易になります。
キャッシュ サービスは、アプリケーション システムの読み取り、テスト、スケーラビリティ、パフォーマンスを維持するのに役立つツールです。
添付ファイル:
あなたがでなければなりません ログイン 添付ファイルを表示します。