From b70444c3890dc0676aad19082d4c4b5767584fd4 Mon Sep 17 00:00:00 2001 From: Hare Date: Thu, 1 Oct 2026 10:44:20 +0900 Subject: [PATCH] docs: generalize client cache and acquisition model --- 4-client.md | 72 ++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/4-client.md b/4-client.md index e0ea528..a0cae9e 100644 --- a/4-client.md +++ b/4-client.md @@ -2,9 +2,9 @@ ## 役割 -Clientは、Hostが提供するWorldspaceをユーザーへ提示する実装主体である。WIP Protocolを利用しつつ、Objectが参照するInterface集合を解決し、用途に応じたViewやAPIへ投影する。 +Clientは、Hostが提供するWorldspaceを利用する実装主体である。WIP Protocolを利用しつつ、Objectが参照するInterface集合を解決し、用途に応じたView、Tool、API等の上位インターフェースへ投影する。 -ClientはHostから得た情報をそのまま一時表示するだけでなく、rootからindexable edgeを辿って構成したエントリツリーと、必要に応じて選択したエントリを保持し、ユーザーから見た**既知の空間**を構成する。 +ClientはHostから得た情報をinteractionごとに破棄するだけでなく、rootからindexable edgeを辿って構成したエントリツリーと、必要に応じて選択したエントリを保持し、上位層にとっての**既知の空間**を構成する。 ## Known Space @@ -12,6 +12,8 @@ Known Spaceは、Clientが**現在保持しているエントリの集合**で Known SpaceとDiscoverable SpaceはClientが過去の観測から構築したcacheであり、Host上の現在状態を同期したreplicaではない。HostはClientのcache状態を追跡または更新しない。 +Clientは、観測結果が同じeffective Worldspace viewに属する範囲でcacheを共有する。接続先、認証主体、tenant、その他のsecurity contextによって異なるWorldspaceが公開され得る場合、それらのKnown Space、Object observation、Interface cacheを混在させない。具体的なcache namespaceの構成はClientおよびTransport Bindingに委ねる。 + 次のような経路で得られたエントリをKnown Spaceへ追加できる。 - `observe`で取得したエントリ @@ -21,48 +23,22 @@ Operationを通して発見されたpathは、必ずしもKnown Spaceへ追加 既知エントリ間の移動や参照はClient側で処理できる。既知の空間を辿るたびにHostへ問い合わせる必要はない。 -## Object storeとEntry Tree +## Entry TreeとObject observation -ClientはKnown Spaceを、flatなObject storeとEntry Treeへnormalizeして保持できる。 +Clientは、観測したObjectをcanonical path上のEntryへ対応付け、観測済みのindexable child edgeとともに保持できる。具体的なcache表現は規定しない。Clientは`ObjectObservation`に近い入れ子構造またはforestを保持しても、path index、flatなObject store、Entry Treeへnormalizeしてもよい。 -```rust -struct CachedWorldspace { - objects: HashMap, - entries: HashMap, -} +EntryのpathとchildrenはWorldspace上の配置contextであり、Object identityそのものには含まれない。同じObjectが複数のEntryから観測される場合、Clientはshared record、複製したsnapshot、その他の内部表現を使用できる。ただし、保存形式によって`ref`、validator、Object representationのconsistencyを変えてはならない。 -struct CachedObject { - name: String, - description: Option, - interfaces: Vec, - r#ref: Option, - validator: Option>, - metadata_stale: bool, -} +- 同じ有効な`ref`を持つ観測は、同じWorldspace内の同じObjectを表す。Clientは一つのObject stateを共有しても、Entryごとにsnapshotを保持してもよい。 +- `ref`がないこと、または異なることから、複数のEntryが同じObjectか異なるObjectかを判断しない。Clientはrepresentationが同じという理由だけでObject identityを推測しない。 +- Objectの`interfaces`はmembershipをsetとして扱い、同じ参照の重複を`InvalidResponse`として拒否する。ClientはHostの立項順を保持し、InterfaceやOperationの提示順に使用してよい。 +- 同じ`ref`と同じvalidator valueを持つObjectを再観測したとき、validatorが存在するにもかかわらずObject representationが異なる場合、Clientはresponseを`InvalidResponse`として扱う。同じ`ref`でvalidatorが異なる場合、またはvalidatorが存在しない場合は、同一Objectの新しい観測として扱い、最後に受理した成功観測をその`ref`の現在状態とする。 -struct CachedEntry { - object: InternalObjectKey, - children: Option>, -} -``` - -`InternalObjectKey`はClient内部だけで使用し、Protocolへ公開しない。 - -- 観測したObjectが`ref`を持ち、同じWorldspaceのObject storeに同じ`ref`が存在する場合、既存のCachedObjectを更新してEntryから参照する。 -- `ref`がない場合、ClientはEntryごとにInternalObjectKeyを発行し、異なるpath間でObjectをdeduplicateしない。 -- Entry Treeはpathと親子関係を保持し、Object storeはObjectの現在状態を保持する。`CachedEntry.children = None`はchildren未観測、`Some([])`は観測済みでemptyであることを表す。 -- `children`が存在するresponse nodeをmergeするときは、そのentryで観測済みのdirect child edge一覧をresponseの完全な一覧で置き換える。`children`が省略されたnodeは構造について新しい情報を持たないため、既存の観測済み一覧を`None`へ戻したり、既存edgeを削除したりしない。 -- 同じObjectを複数のEntryが参照しても、Object stateをEntryごとに複製しない。 - -Objectの`interfaces`はmembershipをsetとして扱い、同じ参照の重複を`InvalidResponse`として拒否する。ClientはHostの立項順をCachedObjectへ保持し、InterfaceやOperationの表示順に使用してよい。 - -同じ`ref`と同じvalidator valueを持つObjectを再観測したとき、validatorが存在するにもかかわらずObject representationが異なる場合、Clientはresponseを`InvalidResponse`として扱う。同じ`ref`でvalidatorが異なる場合、またはvalidatorが存在しない場合は、同一Objectの新しい観測として最後に成功した観測でCachedObjectを更新する。 - -このnormalizeはClientのcache実装であり、Objectと別のWIP resourceまたはProtocol上のEntry resourceを導入するものではない。 +このcache表現はClient内部の実装であり、Objectと別のWIP resourceまたはProtocol上のEntry resourceを導入するものではない。 ## Interface cache -Objectの公開情報はOperation定義を直接含まず、Interface参照のordered setを持つ。Clientは各参照を`fetch_interface`で解決し、取得したInterface Descriptorとoptionalなvalidatorを観測としてcacheする。 +Objectの公開情報はOperation定義を直接含まず、Interface参照のordered setを持つ。Clientは必要な参照を`fetch_interface`で解決し、取得したInterface Descriptorとoptionalなvalidatorを観測としてcacheする。 ```rust struct CachedInterface { @@ -75,7 +51,7 @@ Clientはvalidatorが存在する観測を`(interface, validator)`の組で識 一つのInterface Descriptorに宣言されたOperationの集合が、そのInterfaceのOperation一覧である。Objectは複数のInterfaceを組み合わせられ、複数のObjectも同じInterfaceを共有できる。 -ClientはObjectの`interfaces`とcacheを比較し、未知のInterfaceだけを取得する。Interface validator mismatch等で更新が必要になった参照は再取得する。複数の`fetch_interface`は、Transport Bindingが提供するbatchを利用してまとめてよい。 +ClientはDescriptorが必要なInterface参照とcacheを比較し、未知のInterfaceだけを取得する。Objectの`interfaces`からDescriptor interestを先行して導出しても、Operationを選択した時点で必要な参照だけを取得してもよい。Interface validator mismatch等で更新が必要になった参照は再取得する。複数の`fetch_interface`は、Transport Bindingが提供するbatchを利用してまとめてよい。 異なるInterfaceで同じOperation名が存在しても、ClientはInterface参照とOperation名の組で識別する。UIやAI Toolでは必要に応じて`.`と表示する。Operation callでは表示文字列をparseせず、Interface参照とOperation名を別fieldとして送る。 @@ -105,10 +81,26 @@ Clientは、Operation Resultの`entry`型として発見したpathを現在の Clientは`observe(path, depth)`を使い、対象Objectだけが必要なら`depth = 0`、indexableな配下も必要なら正のdepthを指定する。一つのinteractionでrequested depthまでを取得するため、Clientが各nodeについてdata-dependentな取得requestを逐次発行する必要はない。 -Response nodeの`children`が省略されている場合、そのnodeのchildrenは未観測であり、空であるとは扱わない。`children`が存在する場合、その一覧は完全であり、空arrayならindexable childが存在しない。Clientは起点pathと各Objectの`name`からchild pathを導出する。 +Response nodeの`children`が省略されている場合、そのnodeのchildrenは未観測であり、空であるとは扱わない。`children`が存在する場合、その一覧は完全であり、空arrayならindexable childが存在しない。Clientは起点pathと各Objectの`name`からchild pathを導出する。`children`が存在するnodeをcacheへmergeするときは、そのEntryで観測済みのdirect child edgeをresponseの完全な一覧で置き換える。`children`が省略されたnodeは構造について新しい情報を持たないため、既存edgeを削除したり、観測済みの一覧を未観測へ戻したりしない。 件数の非常に多いCollectionの個々の要素は、通常indexableな子エントリとして露出しない。個別要素はCollection Objectの`query`や`list`等のOperationを通して発見することを想定する。 +## Interestと取得計画 + +Clientの上位層は、特定pathについて必要な観測depth、または特定Interface参照についてDescriptorが必要であることを、Client-localな**interest**として示せる。InterestはProtocol dataではなく、Hostはその状態を追跡しない。Interestの追加または削除は、保持済み観測のProtocol上の意味や有効性を変更しない。Interestがなくなった観測を保持するかevictするかはClient policyに委ねる。 + +Clientはinterestを、現在有効なObject observation、children coverage、Interface Descriptor observation、および進行中の取得requestと比較し、不足するlogical interactionだけを発行できる。要求されたdepthまでのcoverageがすでに存在する場合、または進行中のrequestによって満たされる場合、同じinterestの調整処理は重複requestを発行しない。Depth境界で`children`が省略されたnodeは、その配下に対する正のdepthのinterestを満たさない。 + +Clientは、interestを満たすためのidempotentな調整と、既存の観測を置き換える明示的な再観測を区別できる。明示的な再観測は、現在有効な観測または同じ対象の進行中requestがあっても新しいrequestを発行し、それ以前のrequestをsupersedeしてよい。 + +Clientは、保持する観測、進行中request、並列度、request rateへboundedな上限を設ける。上限によって新しい取得を開始できない場合、interest自体をProtocol failureとして扱わず、別のrequestの完了、容量の解放、またはinterestの変更後に再評価できる。具体的な優先順位、batching、prefetch範囲、fairness、cache容量、eviction algorithmはClient実装に委ねる。 + +Clientは、上位層から直接示されたinterestに加えて、観測したObjectのInterface参照やindexable child edgeから次のinterestを先行して導出してよい。WIPは全量取得、暗黙の再帰展開、または特定のprefetch範囲を要求しない。取得計画とevictionは、interestの変更や明示的な再観測がないまま同じ観測を繰り返し破棄して再取得する、自己維持的なloopを作ってはならない。 + +複数の取得requestを並行実行するClientは、各responseを元のrequestとそのeffective Worldspace viewへ対応付ける。Clientがある観測状態のownershipを後続requestへ移した場合、supersedeされたrequestのresponseでその状態を上書きしない。Overlapping observationを部分的にmergeする場合も、後続requestが所有するObjectまたはchild coverageを以前のresponseで置き換えない。Success、Protocol failure、Transport failure、またはlocal cancellationによって終了したrequestを、進行中として残してはならない。 + +`observe`または`fetch_interface`の失敗を自動的に再試行するかはClient policyに委ねるが、retry回数、間隔、並列度はboundedでなければならない。取得requestのretry policyを`call_operation`の再実行へ適用せず、OperationについてはProtocolのfailure semanticsに従う。 + ## Objectの同一性 `ref`は、同じ主体に公開された一つのWorldspace内で、複数の観測またはエントリが同じObjectを表すことを示すoptionalなopaque markerである。 @@ -125,7 +117,7 @@ Objectが`validator`を持つ場合、Clientは観測したpathとvalidatorを ClientはOperationに選択したInterface参照と、`fetch_interface`で観測したoptionalなInterface validatorもrequestへ含める。MutableなInterfaceがvalidatorを返す場合は必須preconditionとして使用し、`InterfaceValidatorMismatch`ではInterfaceだけを再観測する。`InterfaceMismatch`ではObjectを再観測し、現在のInterface集合を取得する。 -Operation responseが新しいObject validatorを返した場合、Clientは対象のCachedObjectへ反映する。 +Operation responseが新しいObject validatorを返した場合、Clientは対応するObject observationへ反映する。 ## Failure handling