docs: rewrite reference and clarify interface abstraction
This commit is contained in:
@@ -2,35 +2,35 @@
|
||||
|
||||
## Status
|
||||
|
||||
この文書は、Rust / TypeScript Host APIを設計する前に、動的なWorldspaceを運用するための責務、処理モデル、要件を整理するdraftである。
|
||||
動的なWorldspaceを運用するには、Hostが何を解決し、どの範囲のObjectを投影し、どうOperationを実行するかを整理する必要がある。このdraftは、Rust / TypeScript Host APIの設計に先立って、その責務、処理モデル、要件をまとめたものである。
|
||||
|
||||
具体的なtrait、class、function、decorator、macro、builderのsyntaxは定義しない。この文書で使用する`Projection Provider`、`Projection Resolution`、`Projected Object`等の名称もworking terminologyであり、canonicalなProtocol typeではない。
|
||||
具体的なtrait、class、function、decorator、macro、builderのsyntaxは、ここでは定義しない。`Projection Provider`、`Projection Resolution`、`Projected Object`等もHost内部の設計を検討するためのworking terminologyであり、canonicalなProtocol typeではない。
|
||||
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。言語別のconceptual API modelは[Rust API Model](rust-api-model.md)と[TypeScript API Model](typescript-api-model.md)で扱う。
|
||||
|
||||
## 目的
|
||||
|
||||
WIP Hostの中心的な実装対象は、事前に列挙された静的endpointだけではない。Filesystem、database row、repository内容、検索結果、外部service上のentityなど、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。
|
||||
WIP Hostは、事前に列挙した静的endpointだけでなく、実行時に存在と状態が決まる空間をWorldspaceへ投影できなければならない。Filesystem、database row、repository内容、検索結果、外部service上のentityなどが、その実装対象になる。
|
||||
|
||||
HostがWorldspace内のすべてのObjectを常駐instanceとして保持することは要求しない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
|
||||
そのために、すべてのObjectを常駐instanceとして保持する必要はない。Backend dataをrequest時に解決し、必要な範囲だけObjectとして投影できることを基本とする。
|
||||
|
||||
固定pathへ登録されたObjectやservice endpointは、同じ動的projection modelにおいてrouting / resolution structureが固定された特殊ケースとして扱えるべきである。現在の主体やbackend stateに応じて、そこで返すObject representationやvalidatorが変化することは妨げない。静的登録だけを基本形とし、動的空間を大量のObject登録によって模倣する設計にはしない。
|
||||
固定pathに登録するObjectやservice endpointも、同じ動的projection modelで表現できるべきである。この場合はrouting / resolution structureが固定されているが、返すObject representationやvalidatorは、現在の主体やbackend stateに応じて変化してよい。静的登録を基本形にして大量のObject登録で動的空間を模倣するのではなく、動的な解決の特殊ケースとして静的登録を扱う。
|
||||
|
||||
## 基本的な分離
|
||||
|
||||
Host実装APIでは、少なくとも次の責務を区別する必要がある。この区別を一対一のpublic type、trait、objectへ分割することまでは決定しない。
|
||||
Host実装APIでは、少なくとも次の責務を区別する必要がある。ただし、責務ごとに一つのpublic type、trait、objectを設けるかどうかは未決定である。
|
||||
|
||||
### Interface Declaration
|
||||
|
||||
Operation名、parameter、return type、documentation等を宣言し、Interface Descriptor、Value codec、boundary validationを生成する。
|
||||
Interface Declarationは、Operation名、parameter、return type、documentation等の宣言である。その宣言からInterface Descriptor、Value codec、boundary validationを生成する。
|
||||
|
||||
Interface Declarationは、多数のObjectが共有できる比較的静的なcapability schemaである。Objectの列挙やbackend dataのlifecycleは担当しない。
|
||||
多数のObjectが共有できる、比較的静的なcapability schemaとして扱う。Objectの列挙とbackend dataのlifecycleは、Interface Declarationの責務には含めない。
|
||||
|
||||
### Worldspace Projection
|
||||
|
||||
Clientから受け取ったpathを、現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する。一つのProjected Objectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
|
||||
Worldspace Projectionは、Clientから受け取ったpathを現在の主体とbackend stateに基づいて解決し、Protocol上のObject projectionを生成する処理である。投影するObjectは、Host固有のentityを持たないvirtual nodeでも、一つのbackend entityに対応するものでも、複数のbackend entityを集約したものでもよい。
|
||||
|
||||
Projectionは、少なくとも次を決定する。
|
||||
Projectionで決定する内容には、少なくとも次が含まれる。
|
||||
|
||||
- そのpathのObjectを現在の主体へ公開するか。
|
||||
- 公開する`name`、optionalな`description`、`ref`、`validator`。
|
||||
@@ -40,26 +40,28 @@ Projectionは、少なくとも次を決定する。
|
||||
|
||||
### Host Runtime
|
||||
|
||||
Protocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClientが指定した一つのDescriptorを固定し、そこに宣言されたOperationをObjectのHost内implementationへ適用する。
|
||||
Host RuntimeはProtocol requestを受け取り、ProjectionとInterface registryを協調させる。Operation callでは、現在のProjected Objectが公開するInterface集合からClient指定のDescriptorを一つ固定し、そのDescriptorに宣言されたOperationをObjectのHost内implementationへ適用する。
|
||||
|
||||
Host RuntimeはProtocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等を担う。Backend固有のprojection resolutionやdomain operation implementationそのものはProvider等のHost componentへ委譲できる。Object implementationとOperation実装を接続する具体的なAPIは各言語のSDK側で決定し、Protocol conceptとして追加しない。
|
||||
また、Protocol validation、Interface Descriptorの公開、Value validation、error mapping、resource limit等も担う。一方、backend固有のprojection resolutionやdomain operation implementationそのものは、Provider等のHost componentへ委譲できる。
|
||||
|
||||
Object implementationとOperation実装を接続する具体的なAPIは、各言語のSDK側で決める。これはHost内の実装を接続するためのAPIであり、新たなProtocol conceptとしては追加しない。
|
||||
|
||||
## Working terminology
|
||||
|
||||
このdraftでは、Host内部の議論のために次の語を使う。
|
||||
Host内部の投影処理を検討するため、次の語を使う。
|
||||
|
||||
- **Backend Entity** — File、database row、issue、repository、remote entity等、projectionの入力になり得るHost固有の実体。一つのProjected Objectと一対一に対応するとは限らない。
|
||||
- **Projection Resolution** — 現在の主体とpathについて、公開するObject representationと、後続処理に必要なHost-private情報を得るrequest-timeの解決結果。
|
||||
- **Projection Provider** — Pathと主体からProjection Resolutionを生成し、indexable childrenの発見を支援するHost component。
|
||||
- **Projected Object** — その時点でClientへ返すProtocol `Object`。Backend Entityを持たないvirtual Object、一つのentityのprojection、複数entityのaggregateのいずれでもよく、Host内の常駐instanceを意味しない。
|
||||
|
||||
HostがOperationを実装するために使用するRust struct、TypeScript object、backend handle、transaction context等はHost-privateであり、共通するHost abstractionを必須にしない。これらをProtocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開または流用しない。
|
||||
Operationの実装に使うRust struct、TypeScript object、backend handle、transaction context等はHost-privateである。これらに共通するHost abstractionは必須としない。また、Protocolの`Target { path, validator }`、canonical path、Objectの`ref`として公開したり、それらへ流用したりしない。
|
||||
|
||||
## 運用モデル
|
||||
|
||||
### `observe`
|
||||
|
||||
`observe(path, depth)`では、Hostは概念的に次を行う。
|
||||
`observe(path, depth)`では、要求された範囲のObjectを現在の状態から投影する。Hostが概念的に行う処理は次のとおりである。
|
||||
|
||||
1. Requestの主体とpathをProjection Providerへ渡す。
|
||||
2. Providerが現在のbackend stateから、そのpathで公開するProjected ObjectのProjection Resolutionを生成する。
|
||||
@@ -69,23 +71,25 @@ HostがOperationを実装するために使用するRust struct、TypeScript obj
|
||||
6. Nodeがrequested depthに達した場合はchildrenを観測せず、responseの`children` fieldを省略する。
|
||||
7. Requested depthまで完全な`ObjectObservation`を返す。
|
||||
|
||||
ProviderはWorldspace全体をmaterializeせず、現在処理しているparentのdirect childrenを遅延して発見できる必要がある。Childrenをstream、iterator、cursor等のHost内部表現で生成してよいが、一つのparentについて成功するには公開されたindexable childrenをすべて調べ終えなければならない。
|
||||
Providerには、Worldspace全体をmaterializeせず、処理中のparentのdirect childrenを遅延して発見できることが必要になる。Host内部ではstream、iterator、cursor等でchildrenを生成してよい。ただし、一つのparentの観測を成功とするには、その主体へ公開するindexable childrenをすべて調べ終える必要がある。
|
||||
|
||||
Backend failure、cancellation、またはresource budget超過をclean exhaustionとして扱わない。Requested depthまでの完全なresponseを構築できない場合、Host Runtimeは部分的なsuccess responseを返さず、対応するfailureを返す。
|
||||
Backend failure、cancellation、resource budget超過は、列挙が正常に完了したclean exhaustionとは区別する。Requested depthまで完全なresponseを構築できなければ、Host Runtimeは部分的なsuccess responseではなく、対応するfailureを返す。
|
||||
|
||||
各childについて現在のObject projectionを構築し、そのcanonical pathを後の`observe`または`call_operation`で現在のProjected Objectとして再解決できなければならない。以前観測したbackend entityやHost内部instanceを再現することは要求しない。
|
||||
列挙した各childについては、現在のObject projectionを構築し、そのcanonical pathを後の`observe`や`call_operation`で再解決できなければならない。再解決の対象は、その時点のProjected Objectである。以前観測したbackend entityやHost内部instanceの再現は要求しない。
|
||||
|
||||
この処理のために、Hostが以前の`observe`で生成したObject instanceを保持している必要はない。内部cacheを利用してもよいが、cacheの有無によってProtocol semanticsを変えてはならない。
|
||||
したがって、Hostが以前の`observe`で作ったObject instanceを保持する必要もない。内部cacheは利用してよいが、その有無でProtocol semanticsを変えてはならない。
|
||||
|
||||
### `fetch_interface`
|
||||
|
||||
ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から取得可能なDescriptorへ解決されなければならない。
|
||||
ProjectionがObjectへ割り当てた各Interface参照は、その主体から取得可能なDescriptorへ解決されなければならない。複数のObjectで同じ参照を共有でき、一つのObjectに複数のInterfaceを組み合わせることもできる。
|
||||
|
||||
複数のObjectは同じInterface参照を共有でき、一つのObjectも複数のInterfaceを組み合わせられる。Validatorを返すInterface参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照のDescriptorは、その参照が有効な間immutableである。Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決定する。
|
||||
Descriptorの変更可否は、Interface参照がvalidatorを返すかどうかで分かれる。Validatorを返す参照ではDescriptorを変更でき、同じ参照とvalidatorの組が一つのDescriptor observationを表す。Validatorを返さない参照では、その参照が有効な間、Descriptorはimmutableである。
|
||||
|
||||
Interface参照のscopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。登録API、生成時期、deduplication、cacheの具体実装は別途決める。
|
||||
|
||||
### `call_operation`
|
||||
|
||||
`call_operation`では、HostはProviderまたはbackend固有のexecution boundaryへ入り、その同じboundary内で概念的に次を行う。
|
||||
`call_operation`では、現在のObjectを解決する処理と、そのObjectへの実行を同じexecution boundary内で行う。HostはProviderまたはbackend固有のboundaryに入り、概念的に次を行う。
|
||||
|
||||
1. 現在の主体と`target.path`からProjection Resolutionを生成し、同じbackend対象を保持するstable handleまたはtransaction contextを取得する。
|
||||
2. そのpathのProjected Objectを現在も公開するか確認する。
|
||||
@@ -97,15 +101,15 @@ ProjectionがObjectへ割り当てた各Interface参照は、同じ主体から
|
||||
8. 固定したObject implementation、Interface Descriptor、Operation implementationを、step 1で固定した同じbackend対象へ適用する。
|
||||
9. Resultを同じOperation Declarationで検証し、nestedしたすべての`Entry`へ現在の主体のvisibility checkを適用してから、実行後Object validatorとともに返す。
|
||||
|
||||
Step 3から8までの間にObject、Interface、Descriptor、Operation implementation、backend対象の対応が変化し得る実装は、この手順を満たさない。Projectionは、Host RuntimeとProviderがこのatomicityを実現するために必要なstable handle、transaction、conditional operation、lock等を使用できるようにしなければならない。
|
||||
Step 3から8までの間に、Object、Interface、Descriptor、Operation implementation、backend対象の対応が変わり得る実装では、この手順を満たせない。Host RuntimeとProviderがatomicityを実現できるよう、Projectionは必要なstable handle、transaction、conditional operation、lock等を使用できる必要がある。
|
||||
|
||||
過去の`observe`で作成したHost内部Object instanceの存在を前提にしてはならない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。Validatorを省略したcallを現在のOperationが許可する場合は、過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
|
||||
解決には、過去の`observe`で作ったHost内部Object instanceを前提としない。Clientから届くprotocol-level Targetはpathとoptionalなvalidatorであり、Hostはcall時の現在状態からObject implementationを解決する。現在のOperationがvalidatorの省略を許可する場合、callは過去に観測したObjectではなく、実行時にpathが指す現在のObjectへ無条件に実行する。
|
||||
|
||||
Validatorを指定した場合は、Clientが観測したObject identityおよび保護対象状態と実行対象を照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceのいずれも、単独ではProtocol上の永続的なObject identityとして扱わない。
|
||||
一方、validatorが指定されたcallでは、Clientが観測したObject identityと保護対象状態を実行対象へ照合する。Path、`ref`、以前のProjection Resolution、cacheされたHost内部instanceは、いずれも単独ではProtocol上の永続的なObject identityとして扱わない。
|
||||
|
||||
## Filesystem projectionの評価例
|
||||
|
||||
Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに対応するObject instanceを作成する必要はない。
|
||||
Filesystemを`/files`以下へ投影する場合も、全file / directory分のObject instanceを作成する必要はない。Request時の解決と投影を、次のように行える。
|
||||
|
||||
- `observe("/files/a.txt", depth = 0)`では、pathをfilesystem entryへ解決し、stat等からObject projectionを構築する。
|
||||
- `observe("/files", depth = 1)`では、directory listingから直接のindexable childrenをすべて列挙する。
|
||||
@@ -113,7 +117,7 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
|
||||
- 主体の権限に応じてObjectを非公開にしたり、read-only、writable等のcapability Interfaceを集合へ追加または除外できる。
|
||||
- File Operationでは、call時にpathを現在のfilesystem entryへ解決し、Rust struct、TypeScript object、file descriptor等を使ってOperationを実装できる。
|
||||
|
||||
この例で、Objectはfileそのものでも、file内容を複製したrecordでもない。FileをWorldspace上で発見および操作するためのprotocol-level projectionである。
|
||||
この場合のObjectは、fileをWorldspace上で発見・操作するためのprotocol-level projectionである。Fileそのものを渡すわけでも、file内容を複製したrecordを渡すわけでもない。
|
||||
|
||||
## 要件
|
||||
|
||||
@@ -167,13 +171,13 @@ Filesystemを`/files`以下へ投影する場合、Hostが全file / directoryに
|
||||
- Operation call時には、その時点でpathが指す現在のProjected ObjectとInterface集合を再解決し、Clientが指定した参照のmembershipとvalidatorを確認する。
|
||||
- 非公開Object、非公開Operation、公開済みだが実行拒否されたOperationをProtocolで定めたerrorへ一貫して対応付ける。
|
||||
|
||||
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityおよび状態と条件付き実行の対応はvalidatorで保護する。Validatorを省略したcallをOperationが許可する場合は実行時の現在Objectへ無条件に実行し、Operationがvalidatorを要求する場合は`ValidatorRequired`として実行しない。
|
||||
Backendが並行して変化する場合、複数request間で同じsnapshotを保証することまでは要求しない。観測したObject identityと状態を条件付き実行の対象へ対応付けるため、validatorを使う。Operationがvalidatorの省略を許可すれば、callは実行時の現在Objectへ無条件に実行する。Validatorを要求するOperationでは、省略されたcallを`ValidatorRequired`として拒否し、実行しない。
|
||||
|
||||
### Operation解決と実行対象のatomicity
|
||||
|
||||
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を一つのlinearization pointで固定しなければならない。ValidatorなしのObject実行をOperationが許可する場合でも、解決後にpathの指すProjected Objectが変化し、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることを許してはならない。
|
||||
Operation callでは、visibility、Object identityとvalidator、Interface membershipとvalidator、Interface Descriptor、Operation implementation、backend対象を、一つのlinearization pointで固定しなければならない。Object validatorなしの実行をOperationが許可する場合も、この固定は必要である。解決後にpathの指すProjected Objectが変わり、以前のDescriptorに基づくOperation implementationが現在の別Objectへ適用されることは許さない。
|
||||
|
||||
少なくとも次を一つのatomicなexecution boundaryとして扱えなければならない。
|
||||
少なくとも次の処理を、一つのatomicなexecution boundaryとして扱える必要がある。
|
||||
|
||||
- Pathが現在指すObject identityと保護対象状態の確認。
|
||||
- Object validatorの必須判定と比較。
|
||||
@@ -183,9 +187,9 @@ Operation callでは、visibility、Object identityとvalidator、Interface memb
|
||||
- Authorizationの確認。
|
||||
- 同じbackend対象へのOperation実行。
|
||||
|
||||
単にpathを一度解決し、validatorを比較した後に、同じpathを別途開き直してOperationを実行する実装では、比較と実行の間に対象が差し替わる可能性がある。
|
||||
Pathを一度解決してvalidatorを比較しても、その後に同じpathを別途開き直して実行すると、比較と実行の間に対象が差し替わる可能性がある。
|
||||
|
||||
Host APIは、backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等、Providerがbackendに適した方法でatomicityを実現できる境界を提供する必要がある。すべてのbackendに共通する特定のlocking方式は要求しない。
|
||||
そのためHost APIには、Providerがbackendに適した方法でatomicityを実現できる境界が必要になる。Backend transaction、lock、revision付きconditional update、file descriptor、identity再確認等を利用できるようにするが、すべてのbackendに共通する特定のlocking方式は要求しない。
|
||||
|
||||
### Host内部Object stateのlifecycleを限定できること
|
||||
|
||||
@@ -229,7 +233,7 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
|
||||
|
||||
### RustとTypeScriptで同じsemanticsを表現できること
|
||||
|
||||
言語ごとのAPI syntaxは異なってよいが、少なくとも次を両方で実現できなければならない。
|
||||
RustとTypeScriptでAPI syntaxが異なっても、次の処理や制約は両方で実現できなければならない。
|
||||
|
||||
- Asyncなpath resolutionとchild enumeration。
|
||||
- Data-drivenなObject projection。
|
||||
@@ -240,11 +244,11 @@ Host APIは、backend transaction、lock、revision付きconditional update、fi
|
||||
- Request context、主体、cancellation、resource limitの伝播。
|
||||
- Protocol errorとbackend / implementation errorの分離。
|
||||
|
||||
Rust固有のtrait、generic、associated type、type erasureや、TypeScript固有のobject definition、generic inference、runtime schema libraryの選択は、この要件を満たすためのAPI設計段階で決める。
|
||||
Rustのtrait、generic、associated type、type erasureや、TypeScriptのobject definition、generic inference、runtime schema libraryの選択は、これらの要件を満たすAPIを設計する段階で決める。
|
||||
|
||||
## Host内部cache
|
||||
|
||||
Hostは性能最適化として、path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよい。ただし、cacheはProtocol contractではない。
|
||||
Host内部のcacheは性能最適化であり、Protocol contractではない。Path resolution、backend metadata、Object projection、Interface Descriptor、Host内部Object state等をcacheしてよいが、次の条件を守る必要がある。
|
||||
|
||||
- Cacheがなくても正しく動作しなければならない。
|
||||
- Visibilityとauthorizationを異なる主体間で誤って共有してはならない。
|
||||
@@ -254,21 +258,23 @@ Hostは性能最適化として、path resolution、backend metadata、Object pr
|
||||
|
||||
## Composition
|
||||
|
||||
一つのHostは、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
|
||||
一つのHostで、Filesystem、database、remote API等の複数Providerを一つのWorldspaceへ合成できることが望ましい。
|
||||
|
||||
Composition後も、同じ主体へ公開されたWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等の方法で次を保証する。
|
||||
合成する場合も、同じ主体へ公開するWorldspace全体で`ref`とInterface参照のProtocol semanticsを保たなければならない。Provider-local identityやInterface keyをそのまま公開すると衝突し得るため、Hostはnamespace、変換、中央発行等によって次を保証する。
|
||||
|
||||
- 異なるObjectへ同じ有効な`ref`を割り当てない。
|
||||
- 同じ有効なInterface参照とvalidatorの組を異なるDescriptorへ対応付けない。
|
||||
- Validator比較がProvider routingの変更によって別Objectへ適用されない。
|
||||
|
||||
Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使用する。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`の具体的な発行方式は引き続き未決定とする。ScopeはそのpathのObjectに紐づき、self-scopeを許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開し、callで指定された`scope_ref`をrouting・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡を要求しない。
|
||||
Interface参照には、[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)の構造化参照を使う。Objectの祖先制約と、合成後のscope・path・typed `entry`の変換は、[ProtocolのWorldspace composition](../3-protocol.md#worldspace-composition)に従う。Objectの`ref`を具体的にどう発行するかは、引き続き未決定である。
|
||||
|
||||
ただし、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryは未決定である。ProtocolはHost内部のcomposition方式を公開しないため、Host APIでこれらをどこまで標準化するかを別途検討する。
|
||||
ScopeはそのpathのObjectに紐づき、self-scopeも許可する。RuntimeはDescriptorとscope Objectのoptionalな`ref`を一つのInterface observationとして公開する。Callで指定された`scope_ref`は、routing・implementationの固定と一貫して確認する。`ref`のないscopeも許可し、そのidentityの追跡は要求しない。
|
||||
|
||||
Host内部の合成方法については、mount API、path routing、Provider間のparent / child関係、同名entry conflict、cross-provider Operation、transaction boundaryが未決定である。ProtocolではHost内部のcomposition方式を公開しないため、これらをHost APIでどこまで標準化するかは別途検討する。
|
||||
|
||||
## 非目標
|
||||
|
||||
このdraftは次を要求しない。
|
||||
動的projectionの要件には、次を含めない。
|
||||
|
||||
- Worldspace全体の事前materialization。
|
||||
- Objectごとの常駐class instanceまたはactor。
|
||||
@@ -281,7 +287,7 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
|
||||
|
||||
## API設計前に評価するシナリオ
|
||||
|
||||
具体API案は、少なくとも次のシナリオで不自然な大量登録や永続Object instanceを要求しないことを確認する。
|
||||
具体API案は、少なくとも次のシナリオで評価する。不自然な大量登録や、永続Object instanceの保持を要求しないことを確認する必要がある。
|
||||
|
||||
1. 数百万entryを持つFilesystemを、directory listingに応じて遅延投影する。
|
||||
2. Database tableのrowをObjectとして投影し、row keyからcall時に再解決する。
|
||||
@@ -318,4 +324,4 @@ Interface参照は[2.2. Operation and Interface](../2.2-operation-and-interface.
|
||||
- Provider composition時のconflict、ownership、lifecycle、shutdown順序。
|
||||
- Observability、tracing、auditで非公開Objectやsecretを漏らさないための標準hook。
|
||||
|
||||
これらを決定する前に、Rust / TypeScript双方で複数のAPI sketchを作り、上記の評価シナリオと要件に照らして比較する。
|
||||
これらの決定に先立ち、Rust / TypeScript双方で複数のAPI sketchを作る。各案をここに挙げた評価シナリオと要件に照らして比較し、具体的なAPIを検討する。
|
||||
|
||||
@@ -2,30 +2,32 @@
|
||||
|
||||
## 位置付け
|
||||
|
||||
この文書は、YoiのFS投影に対して決めた探索仕様を、WIP Hostの投影方針として記録するdraftである。**Treeで発見するのはfilesystemの入口までとし、その内容はdirectoryのlist / glob / grep Operationで発見する。**
|
||||
YoiのFS投影では、Treeで発見する範囲をfilesystemの入口までとし、その内容をdirectoryのlist / glob / grep Operationで発見する方針を決めた。このdraftは、その探索仕様をWIP Hostの投影方針として記録するものである。
|
||||
|
||||
Indexableな範囲の全量取得をClientで縮めるのではなく、Hostが何をindexableとして公開するかを修正する。個々のファイル・フォルダは非indexableなObjectとして要求時に直接解決できる。
|
||||
変更するのは、Hostがindexableとして公開する範囲である。Indexableな範囲の全量取得をClient側で縮めるのではなく、Hostで入口と内容を分ける。個々のファイル・フォルダは非indexableなObjectとして、要求時に直接解決できる。
|
||||
|
||||
[Object tree / SchemaのIndexable children](../2.1-object-tree-schema.md#indexable-children)、[Client](../4-client.md)、[4.1. AI Tools](../4.1-ai-tools.md)を前提とする。Yoi側の実装追跡はT-714、既存投影はT-699である。本稿は仕様決定の記録であり、実装済みであることを示さない。
|
||||
前提となる仕様は、[Object tree / SchemaのIndexable children](../2.1-object-tree-schema.md#indexable-children)、[Client](../4-client.md)、[4.1. AI Tools](../4.1-ai-tools.md)に従う。Yoi側の実装追跡はT-714、既存投影はT-699である。このdraftは仕様決定の記録であり、実装済みであることを示すものではない。
|
||||
|
||||
## なぜFS全体をindexableにしないか
|
||||
|
||||
Indexable childrenには、件数がboundedまたは現実的な範囲で列挙でき、比較的安価で、自然な所有・内包関係であることが求められる。全件列挙が高コストまたは不自然な集合は、対象の集合を扱うObjectのOperationで検索・filter・paginationし、`entry` を返すのが既存の方針である。
|
||||
任意のfilesystem directoryには、浅い位置でも大量のfileやdirectoryが存在し得る。Depthを小さくしてもAIが把握できない件数になるため、depth制限だけで適切な探索空間を作ることはできない。
|
||||
|
||||
任意のfilesystem directoryは、浅い位置に大量のfileやdirectoryを持ち得る。Depthが小さくてもAIが把握できない件数になるため、depth制限だけでは適切な探索空間を作れない。
|
||||
Indexable childrenには、件数がboundedまたは現実的な範囲で列挙でき、比較的安価で、自然な所有・内包関係であることが求められる。全件列挙が高コストまたは不自然な集合については、その集合を扱うObjectのOperationで検索・filter・paginationし、`entry` を返すのが既存の方針である。
|
||||
|
||||
次の対策だけでFS内容をindexableにしてよいとはしない。
|
||||
FS内容の公開でも、このindexabilityの判断は必要になる。次の対策だけを理由に、内容をindexableにしてよいとはしない。
|
||||
|
||||
- Clientが小さいdepthを選ぶこと。
|
||||
- Hostが件数上限で `ResourceLimitExceeded` を返すこと。
|
||||
- Directoryをlazyに列挙し、常駐Objectや事前indexを作らないこと。
|
||||
- Clientが応答を切り捨てて表示すること。
|
||||
|
||||
前二者は必要な安全弁、lazy解決は実装上の性質であり、indexabilityの判断とは別である。部分的な応答を完全なtreeとして見せることもできない。本投影では、内容の件数が少ない場合だけchildrenへ展開する方式にはせず、入口と内容の境界を一貫させる。
|
||||
Depth制限と件数上限は必要な安全弁であり、lazy解決は実装上の性質である。いずれも、内容をindexableにするかどうかとは別の判断になる。また、部分的な応答を、完全なtreeとして見せることもできない。
|
||||
|
||||
この投影では、内容の件数が少ない場合だけchildrenへ展開する方式も採らない。件数によって探索方式が変わらないよう、入口と内容の境界を一貫させる。
|
||||
|
||||
## Indexableな公開境界
|
||||
|
||||
Yoiでは、rootからtreeで発見できる範囲を次とする。
|
||||
Yoiでrootからtreeを通じて発見できるのは、現在利用できるfilesystemの入口までである。配置は次の範囲とする。
|
||||
|
||||
```text
|
||||
/
|
||||
@@ -34,9 +36,9 @@ Yoiでは、rootからtreeで発見できる範囲を次とする。
|
||||
└── docs
|
||||
```
|
||||
|
||||
`/checkouts/<checkout-name>` は、現在利用できるfilesystemの入口であり、directoryとして操作できるObjectでもある。その直下から先のfile / directoryは、入口や内容directoryのindexable childrenには含めない。
|
||||
`/checkouts/<checkout-name>` はfilesystemの入口であり、directoryとして操作できるObjectでもある。ただし、その直下から先のfile / directoryは、入口にも内容directoryにもindexable childrenとして含めない。
|
||||
|
||||
例えば次のpathは有効な操作対象として存在し得るが、上のtreeには展開しない。
|
||||
例えば、次のpathは有効な操作対象として存在し得るが、上のtreeには展開しない。
|
||||
|
||||
```text
|
||||
/checkouts/main/README.md
|
||||
@@ -44,24 +46,24 @@ Yoiでは、rootからtreeで発見できる範囲を次とする。
|
||||
/checkouts/main/src/lib.rs
|
||||
```
|
||||
|
||||
`/checkouts` はYoi側の配置例であり、WIP Protocol全体へ固定namespaceを追加するものではない。単一FSをWorldspace `/` に直接投影する場合は `/` 自体が入口に相当し、その内容をindexable childrenへ展開しない。
|
||||
`/checkouts` はYoi側の配置例であり、WIP Protocol全体の固定namespaceにはしない。単一FSをWorldspace `/` に直接投影する場合は、`/` 自体を入口として扱い、その内容をindexable childrenへ展開しない。
|
||||
|
||||
入口の一覧自体についてもindexableの一般条件は維持する。この境界は、入口の数まで無制限に増やしてよいという意味ではない。
|
||||
入口の一覧にも、indexableの一般条件を適用する。内容をtreeに含めないからといって、入口の数まで無制限に増やしてよいわけではない。
|
||||
|
||||
## 非indexableと非公開は別
|
||||
|
||||
File / directoryをindexableにしないことは、Objectとして非公開にすることでも、pathで解決不能にすることでもない。
|
||||
File / directoryを非indexableにしても、Objectとしての公開やpathによる直接解決は可能である。Treeから発見できる範囲と、既知のpathから解決できる範囲は分けて扱う。
|
||||
|
||||
- `observe("/checkouts/main/src/lib.rs", depth = 0)` は、現在の主体に公開できるfileなら、そのObjectを返せる。
|
||||
- AI向け `inspect(path)` は、ClientがまだObjectを観測していないpathにも使える。
|
||||
- Directoryの探索やfileの読み書きは、そのObjectが公開するInterfaceのOperationとして実行する。
|
||||
- 直接解決にも現在の可視性・権限を適用する。Pathを知っていることは権限ではない。
|
||||
|
||||
非公開・存在しないpathの扱いは従来のProtocolに従う。非indexableという理由だけで `NotFound` を返してはならない。
|
||||
非公開・存在しないpathの扱いは、従来のProtocolに従う。非indexableという理由だけで `NotFound` を返してはならない。
|
||||
|
||||
## observeのchildren契約
|
||||
|
||||
FS入口およびその内容のdirectory/fileは、この投影では内容のindexable childrenを持たない。
|
||||
この投影では、FS入口にも、その配下のdirectory/fileにも、内容を表すindexable childrenはない。そのため、depthを深くしても入口から先の内容は列挙しない。
|
||||
|
||||
| 観測 | 応答の意味 |
|
||||
| --- | --- |
|
||||
@@ -71,13 +73,13 @@ FS入口およびその内容のdirectory/fileは、この投影では内容のi
|
||||
| `observe("/checkouts/main", 1)` | 入口Objectと `children: []` |
|
||||
| `observe("/checkouts/main/src", 1)` | 直接解決したdirectory Objectと `children: []` |
|
||||
|
||||
`children: []` は「indexable childがない」という意味であり、filesystem directoryが空であるとは限らない。内容が空かどうかを知るにはdirectoryの `list` を使う。
|
||||
`children: []` が示すのは、indexable childがないことである。Filesystem directoryが空であることまでは示さない。内容が空かどうかは、directoryの `list` で確認する。
|
||||
|
||||
File数が増えても、入口の正のdepth観測でbackendの全内容を列挙する必要はない。Client側だけで非表示にするのではなく、Hostのchildren列挙境界で内容への走査を行わないようにする。Depth境界でのfield省略と、観測済みの空のchildrenは従来どおり区別する。
|
||||
File数が増えても、入口を正のdepthで観測するためにbackendの全内容を列挙する必要はない。Client側で内容を非表示にするだけではなく、Hostのchildren列挙境界で内容への走査を行わないようにする。Depth境界でfieldを省略する場合と、観測した結果が空のchildrenである場合は、従来どおり区別する。
|
||||
|
||||
## 内容を発見するOperation
|
||||
|
||||
FS入口と配下directoryには、次の探索Operationを提供する。これらはInterface上のOperationであり、新しいProtocol interactionや `list` という子Objectではない。
|
||||
FS入口と配下directoryの内容は、次の探索Operationで発見する。これらはInterface上のOperationであり、新しいProtocol interactionを追加したり、`list` という子Objectを設けたりするものではない。
|
||||
|
||||
| Operation | 役割 |
|
||||
| --- | --- |
|
||||
@@ -93,32 +95,32 @@ FS入口と配下directoryには、次の探索Operationを提供する。これ
|
||||
- 大量件数はOperation結果として上限と継続を明示して扱う。部分的な一覧を全件であるかのように返さない。
|
||||
- Cursor等の継続方式、並び順、parameter名、result recordの具体形は、このdraftでは未決とする。
|
||||
|
||||
Yoiの `/checkouts` 自体にある `list` は入口一覧であり、`/checkouts/<checkout-name>` や配下directoryの `list` は内容一覧である。Operation名が同じでも対象とInterfaceが異なる。
|
||||
Yoiの `/checkouts` にある `list` は入口一覧を返す。一方、`/checkouts/<checkout-name>` や配下directoryの `list` は内容一覧を返す。同じOperation名でも、対象とInterfaceは異なる。
|
||||
|
||||
### glob / grep
|
||||
|
||||
対象directoryを基準にpatternや検索範囲を解釈する。Resultsからfile / directoryへ移動する参照は `entry` 型として宣言し、表示済みのfilenameや行番号付きtextを再parseして作らない。
|
||||
Patternや検索範囲は、対象directoryを基準に解釈する。Resultsからfile / directoryへ移動する参照は、`entry` 型として宣言する。表示済みのfilenameや行番号付きtextを再parseして参照を作る方式は採らない。
|
||||
|
||||
Globは条件に一致する対象を探す操作であり、directory直下の全内容を表すとは限らない。特にYoiの通常ToolsのGlobはfileのみを返し、directoryは返さず、配下を再帰的に走査し得る。`glob("*")` を `list` と同じ契約として扱わない。
|
||||
Globで得るのは条件に一致する対象であり、directory直下の全内容とは限らない。特にYoiの通常ToolsのGlobはfileのみを返し、directoryは返さず、配下を再帰的に走査し得る。このため、`glob("*")` を `list` と同じ契約として扱わない。
|
||||
|
||||
Grepは内容検索であり、treeの名前・構造の探索ではない。Ignore、検索範囲、結果上限、context、継続等は各Operationの明示された契約に従う。
|
||||
Grepはfileの内容検索であり、treeの名前や構造を探索する操作ではない。Ignore、検索範囲、結果上限、context、継続等は、各Operationに明示された契約に従う。
|
||||
|
||||
## Clientとの接続
|
||||
|
||||
典型的な利用は次の流れになる。これは操作の順序の例であり、Tool responseやInterface参照の具体構文を定義するものではない。
|
||||
Clientでは、treeで入口を知り、directoryのOperationで内容のpathを得て、必要なObjectだけをinspectする流れになる。典型的な操作順序は次のとおりである。これは利用例であり、Tool responseやInterface参照の具体構文を定義するものではない。
|
||||
|
||||
1. `tree("/", depth)` で `/checkouts/main` の入口を知る。
|
||||
2. `inspect("/checkouts/main")` でdirectoryの `list` / `glob` / `grep` を知る。
|
||||
3. 選んだOperationを `invoke` し、結果から `/checkouts/main/src` やfileのpathを得る。
|
||||
4. 必要なpathだけを `inspect` し、さらに探索するかfileのOperationを実行する。
|
||||
|
||||
結果のすべてのentryを即時にObjectへ展開する必要はない。AIはまずpathだけを受け取り、説明や操作が必要になったときにClientへinspectを依頼できる。
|
||||
Operation結果のすべてのentryを、直ちにObjectへ展開する必要はない。AIはまずpathだけを受け取り、説明や操作が必要になった時点でClientへinspectを依頼できる。
|
||||
|
||||
Clientがそれらを観測してKnown Spaceへ保持しても、rootからのtreeには混ぜない。Pathの階層関係だけからindexable edgeを生成しない。既知の内容directoryをtreeの起点として直接指定した場合も、そのObjectは表示できるが、内容をindexableな子として復活させない。
|
||||
観測した内容をClientがKnown Spaceへ保持しても、rootからのtreeには混ぜない。Pathの階層関係だけではindexable edgeを生成しない。既知の内容directoryをtreeの起点として直接指定した場合も、そのObjectは表示できるが、内容をindexableな子として再び表示することはしない。
|
||||
|
||||
## 解決・権限・整合性
|
||||
|
||||
探索方式の変更で、既存の権限やファイル操作の意味を変えない。
|
||||
内容の探索をOperationへ分けても、既存の権限やファイル操作の意味は変えない。一覧・検索・直接解決・操作には、次の境界を適用する。
|
||||
|
||||
- 現在の主体、root/attachment、scope、provider capabilityに基づき、一覧・検索・直接path解決・操作を実行する。
|
||||
- Hostの一覧結果には、主体へ公開できる対象だけを含める。直接path指定でも同じ境界を守る。
|
||||
@@ -126,15 +128,15 @@ Clientがそれらを観測してKnown Spaceへ保持しても、rootからのtr
|
||||
- Object identityとvalidatorは既存Protocolとproviderの実行境界で管理する。
|
||||
- Fileのread/edit/write等の具体的契約は、各投影のInterfaceに従う。本稿はbyte操作やtext操作の統一を要求しない。
|
||||
|
||||
Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・transport境界を共有する。Worker側でremote filesystemのホストパスを直接開く方法や、Bashの `ls` を必須にする方法へ置き換えない。
|
||||
Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・transport境界を共有する。Workerがremote filesystemのホストパスを直接開く方法や、Bashの `ls` を必須にする方法には置き換えない。
|
||||
|
||||
## 現行文書・実装との差
|
||||
|
||||
[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)のFilesystem評価例と、現行 `wip-fs-server` は、directoryの内容をchildrenとして列挙する経路を持つ。Yoiの既存 `/checkouts` 投影も、内部List処理をchildren列挙に使い、directoryの独立した `list` Operationは提供していなかった。
|
||||
[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)のFilesystem評価例と現行 `wip-fs-server` には、directoryの内容をchildrenとして列挙する経路がある。Yoiの既存 `/checkouts` 投影でも、内部List処理をchildren列挙に使い、directoryの独立した `list` Operationは提供していなかった。
|
||||
|
||||
本draftは、それらの現状を承認する文書ではなく、FS内容の探索をOperationへ分離する修正方針である。Lazyなrequest-time解決と、既知pathからの直接解決は維持するが、directory listingをindexable childrenの列挙として使う部分は見直す。
|
||||
それに対し、このdraftはFS内容の探索をOperationへ分離する修正方針である。Lazyなrequest-time解決と、既知pathからの直接解決は維持する。ただし、directory listingをindexable childrenの列挙に使う部分は見直すため、現状の実装を承認するものではない。
|
||||
|
||||
既存ProtocolがあらゆるFS Objectのindexabilityを一律に禁止する明文を持つという意味ではない。既存のindexable条件を、任意件数の内容を持つFSへ適用する具体的方針として、このdraftでは入口で境界を固定する。
|
||||
この方針は、既存Protocolに「あらゆるFS Objectを一律に非indexableとする」明文があることを意味しない。任意件数の内容を持つFSに既存のindexable条件を適用する具体的方針として、入口で境界を固定する。
|
||||
|
||||
## 検証するシナリオ
|
||||
|
||||
@@ -152,4 +154,4 @@ Yoiの実装では、既存Workdir providerのList/Glob/Grep処理と権限・tr
|
||||
- Symlinkや特殊entryのlist上の種別表現、各providerのignore方針との整合。
|
||||
- 本稿を既存の動的投影例、FS実装、AI用Toolsの正本文書へどう反映するか。
|
||||
|
||||
通常Tools modeへ独立したList Toolを追加するかどうかは、directory Operationの公開とは別の適用事項であり、本稿で追加済みとは扱わない。
|
||||
通常Tools modeへ独立したList Toolを追加するかどうかは、directory Operationの公開とは別の適用事項である。このdraftで追加済みとは扱わない。
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
## Status
|
||||
|
||||
この文書は、WIP HostをRustで実装するための概念的なAPI modelを整理するdraftである。
|
||||
WIP HostをRustで実装する際、Interfaceの宣言とObjectの実装をどう組み合わせて公開するか。このdraftは、そのための概念的なAPI modelを提案する。
|
||||
|
||||
このdraftで示すtrait名、attribute、derive、generated type名、method signatureは説明用であり、具体的なRust API syntaxとして確定しない。Ownership、lifetime、async runtime、error type、macro crate構成も未決定である。
|
||||
Trait名、attribute、derive、generated type名、method signatureは説明用であり、具体的なRust API syntaxは確定していない。Ownership、lifetime、async runtime、error type、macro crate構成も未決定である。
|
||||
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するTypeScript modelは[TypeScript API Model](typescript-api-model.md)を参照する。
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するTypeScript modelは[TypeScript API Model](typescript-api-model.md)を参照する。
|
||||
|
||||
## 目的
|
||||
|
||||
Rust APIでは、次のmodelを自然に表現できるようにする。
|
||||
Rust APIでは、Interfaceをtraitで宣言し、structで実装するmodelを自然に表現できるようにする。ただし、structが実装しているInterfaceと、ある時点で公開するInterfaceは分けて選べるようにする。
|
||||
|
||||
1. Rust traitでWIP Interfaceを宣言する。
|
||||
2. Rust structが、Protocol Objectとして公開するmetadataを提供する。
|
||||
@@ -19,13 +19,13 @@ Rust APIでは、次のmodelを自然に表現できるようにする。
|
||||
5. Trait declarationからInterface Descriptor、Value codec、validation、Operation dispatchに必要なcodeを生成する。
|
||||
6. Struct instanceをWorldspace全体について常駐させず、`observe`と`call_operation`の解決時にdata-drivenに生成できる。
|
||||
|
||||
このmodelでは、Protocol上のObjectとInterfaceの関連付けは`Object.interfaces`だけで表す。Operation implementationへ到達するためのRust内部codeはSDK / Host Runtimeの実装詳細であり、新しいProtocol conceptを導入しない。
|
||||
Protocol上でObjectとInterfaceを関連付けるのは`Object.interfaces`だけである。Operation implementationを呼び出すためのRust内部codeはSDK / Host Runtimeの実装詳細として扱い、新しいProtocol conceptは導入しない。
|
||||
|
||||
## Conceptual model
|
||||
|
||||
### Interface trait
|
||||
|
||||
WIP InterfaceはRust traitとして宣言する。
|
||||
WIP Interfaceは、Rust traitとして宣言する。
|
||||
|
||||
```rust
|
||||
#[wip::interface]
|
||||
@@ -47,9 +47,9 @@ trait FileInterface {
|
||||
}
|
||||
```
|
||||
|
||||
このcodeはconceptual syntaxである。`Option<i64>`の対応範囲、`Bytes` wrapper、documentationの取得方法、async methodとerrorの具体形は別途決定する。
|
||||
このcodeはconceptual syntaxであり、具体的なAPIとして確定したものではない。`Option<i64>`の対応範囲、`Bytes` wrapper、documentationの取得方法、async methodとerrorの具体形は別途決定する。
|
||||
|
||||
Trait declarationは、次のlogical declarationに対応する。
|
||||
Trait declarationとProtocol上の宣言は、次のように対応付ける。
|
||||
|
||||
- 一つのtrait declarationを、一つのInterface Descriptorを生成するRust側definitionとして扱う。
|
||||
- Trait名はgenerated Rust itemやlocal registrationを識別するために使用できるが、Protocol `InterfaceDescriptor`のfieldや構造化されたInterface参照としてそのまま公開しない。
|
||||
@@ -60,11 +60,11 @@ Trait declarationは、次のlogical declarationに対応する。
|
||||
- Rust typeをDescriptorの`TypeExpr`とProtocol `Value`へ対応付ける。
|
||||
- Documentationをtrait、method、parameter、return、関連typeから取得できるようにする。
|
||||
|
||||
Descriptorのshapeはtrait declarationによって決まり、各structのtrait implementationによって変化しない。
|
||||
したがって、Descriptorのshapeを決めるのはtrait declarationである。各structがそのtraitをどう実装するかによって、Descriptorは変化しない。
|
||||
|
||||
### Object implementation
|
||||
|
||||
Rust structは、その時点でWorldspaceへ投影するObjectをHost内部で表現できる。
|
||||
その時点でWorldspaceへ投影するObjectは、Host内部ではRust structとして表現できる。
|
||||
|
||||
```rust
|
||||
struct File {
|
||||
@@ -75,7 +75,7 @@ struct File {
|
||||
}
|
||||
```
|
||||
|
||||
Structは概念上の`WipObject` traitを実装する。
|
||||
公開metadataを提供するために、structが概念上の`WipObject` traitを実装する形を想定する。
|
||||
|
||||
```rust
|
||||
impl WipObject for File {
|
||||
@@ -97,20 +97,20 @@ impl WipObject for File {
|
||||
}
|
||||
```
|
||||
|
||||
`WipObject`が返す値のownershipやborrow形式は未決定である。概念的にはProtocol Objectのうち、publication時に選択するInterface集合以外の公開metadataを提供する。
|
||||
`WipObject`は、Protocol Objectの公開metadataのうち、publication時に選ぶInterface集合以外を提供する。返す値のownershipやborrow形式は未決定である。
|
||||
|
||||
`WipObject`がProtocol metadataとして返す値へ次を含めない。これらをimplementing structのprivate fieldとして保持することは禁止しない。
|
||||
Structが保持する情報のすべてを公開metadataにするわけではない。次の情報は`WipObject`がProtocol metadataとして返す値に含めないが、implementing structのprivate fieldとして保持してよい。
|
||||
|
||||
- Absolute path。PathはObjectのfieldではなく、Worldspace resolutionのcontextである。
|
||||
- Children。ChildrenはTree上の配置contextである。
|
||||
- 固定されたInterface集合。InterfaceはObjectを公開する時点で追加する。
|
||||
- Backend connection、file descriptor、credential等のHost-private state。
|
||||
|
||||
Structが保持する`path`やbackend handle等はHost内部のOperation implementationに使用できるが、`WipObject`のmetadataまたはProtocol Objectへ自動的にserializeしない。
|
||||
たとえば、structの`path`やbackend handleはHost内部のOperation implementationで使用できる。ただし、`WipObject`のmetadataやProtocol Objectへ自動的にserializeする対象にはしない。
|
||||
|
||||
### Interface implementation
|
||||
|
||||
Object implementationとして使用するstructは、公開したいInterface traitを実装する。
|
||||
Object implementationに使うstructは、公開したいInterface traitを実装する。
|
||||
|
||||
```rust
|
||||
impl FileInterface for File {
|
||||
@@ -131,15 +131,15 @@ impl FileInterface for File {
|
||||
}
|
||||
```
|
||||
|
||||
Trait implementationはOperationのbehaviorを提供する。Interface Descriptorはtrait implementationから生成せず、Interface trait declarationから生成する。
|
||||
Trait implementationが提供するのはOperationのbehaviorである。Interface Descriptorの生成元は、このimplementationではなくInterface trait declarationとする。
|
||||
|
||||
Rustには、あるtypeが実装しているtraitを列挙する一般的なreflectionがない。また、一つのstructが複数のInterface traitを実装し得る。そのため、trait implementationが存在するだけでInterfaceを暗黙に公開しない。
|
||||
また、traitを実装しただけでInterfaceを公開することにはしない。Rustには、あるtypeが実装しているtraitを列挙する一般的なreflectionがなく、一つのstructが複数のInterface traitを実装することもあるためである。
|
||||
|
||||
### Object publication
|
||||
|
||||
ObjectをWorldspaceへ返す時点で、struct instanceと公開する0個以上のInterface Declarationを明示的に組み合わせる。Interfaceは追加順を保持するordered setであり、同じDefinitionを重複して追加しない。
|
||||
ObjectをWorldspaceへ返す時点で、struct instanceと、公開する0個以上のInterface Declarationを明示的に組み合わせる。Interfaceは追加順を保持するordered setとし、同じDefinitionの重複追加は認めない。
|
||||
|
||||
Conceptual syntaxは次のようになる。
|
||||
次のconceptual syntaxでは、解決した`File`に公開するInterfaceを追加している。
|
||||
|
||||
```rust
|
||||
let file = File::resolve(path).await?;
|
||||
@@ -147,9 +147,9 @@ let object = PublishedObject::new(file)
|
||||
.expose(FileInterfaceDefinition);
|
||||
```
|
||||
|
||||
ここで各`InterfaceDefinition`は、`#[wip::interface]`が生成するconceptualなcompanion definitionである。実際の名前や、associated item、module、valueのどの形で生成するかは未決定である。
|
||||
各`InterfaceDefinition`は、`#[wip::interface]`が生成するconceptualなcompanion definitionを表す。実際の名前も、associated item、module、valueのどの形で生成するかも未決定である。
|
||||
|
||||
Publication APIは、追加する各Definitionについて概念的に次のboundを要求する。
|
||||
Publication APIが各Definitionの追加に要求するboundは、概念的には次の形になる。
|
||||
|
||||
```rust
|
||||
impl<T: WipObject> PublishedObject<T> {
|
||||
@@ -165,9 +165,9 @@ impl<T: FileInterface> InterfaceDefinition<T>
|
||||
}
|
||||
```
|
||||
|
||||
このboundにより、Objectへ追加する各Interfaceについて、公開する値がObject metadataとOperation implementationの両方を提供することをcompile timeに確認できる。どのInterfaceも追加しないObjectも表現できる。
|
||||
このboundで、公開する値がObject metadataを提供し、追加する各InterfaceのOperation implementationも提供することをcompile timeに確認できる。Interfaceを一つも追加しないObjectも表現できる。
|
||||
|
||||
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeとして追加しない。Host Runtimeはこれを使用して次を構築する。
|
||||
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeには追加しない。Host Runtimeはこの値からProtocol Objectを構築する。
|
||||
|
||||
```rust
|
||||
Object {
|
||||
@@ -179,13 +179,15 @@ Object {
|
||||
}
|
||||
```
|
||||
|
||||
`selected_interface_references`は、Hostが各generated Interface Definitionを登録または公開するときに割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べたものである。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Macroが参照をcompile timeに固定することは要求しない。
|
||||
`selected_interface_references`には、Hostが各generated Interface Definitionの登録または公開時に割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べる。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Macroが参照をcompile timeに固定することは要求しない。
|
||||
|
||||
`observe`はDescriptor自体をObjectへ埋め込まず、このInterface参照のordered setだけを返す。Clientが各参照を`fetch_interface`したとき、Host Runtimeはtrait declarationから生成されたDescriptorと、存在する場合はInterface validatorを返す。同じ参照とvalidatorの組のDescriptorはHost上で共有およびcacheできるため、Object instanceごとにDescriptorを再生成または再送する必要はない。
|
||||
`observe`でObjectに含めるのは、Descriptor自体ではなく、このInterface参照のordered setだけである。Clientが各参照を`fetch_interface`すると、Host Runtimeはtrait declarationから生成したDescriptorと、存在する場合はInterface validatorを返す。
|
||||
|
||||
同じ参照とvalidatorの組に対応するDescriptorは、Host上で共有およびcacheできる。このため、Object instanceごとにDescriptorを再生成したり再送したりする必要はない。
|
||||
|
||||
## Macroが生成する責務
|
||||
|
||||
`#[wip::interface]`は、conceptualには次を生成または提供する。
|
||||
`#[wip::interface]`には、宣言からDescriptorを生成するだけでなく、Valueの変換・検証とdispatchに必要なcodeを提供する役割を想定する。
|
||||
|
||||
- Interface Descriptorを構築するdefinition。
|
||||
- Trait methodとOperation Declarationの対応情報。
|
||||
@@ -196,15 +198,13 @@ Object {
|
||||
- 任意の`T: WipObject + InterfaceTrait`について、そのInterfaceを`PublishedObject<T>`へ追加するための型付きentry point。
|
||||
- HostがInterface参照、optional validator、Descriptorを登録、取得、cacheするためのidentity。
|
||||
|
||||
MacroがRust codebase内のtrait implementationを探索または列挙することは要求しない。Publication時のgeneric boundによって、対象structがInterface traitを実装していることを確認する。
|
||||
対象structがInterface traitを実装しているかは、publication時のgeneric boundで確認する。MacroがRust codebase内のtrait implementationを探索したり列挙したりすることは要求しない。
|
||||
|
||||
Generated dispatch codeはRust SDK内部の実装詳細である。Host内部のdispatch mechanismやRust type名等をProtocolへ公開しない。
|
||||
Generated dispatch codeはRust SDK内部の実装詳細である。Host内部のdispatch mechanismやRust type名等はProtocolへ公開しない。
|
||||
|
||||
## Rust typeとProtocol type
|
||||
|
||||
Interface traitで使用できるRust typeは、Descriptorの`TypeExpr`とProtocol `Value`へ対応付けられなければならない。
|
||||
|
||||
Conceptualにはderiveまたは明示的なcodec implementationを使用する。
|
||||
Interface traitで使うRust typeには、Descriptorの`TypeExpr`とProtocol `Value`への対応付けが必要となる。概念的には、deriveまたは明示的なcodec implementationを使うことを想定する。
|
||||
|
||||
```rust
|
||||
#[derive(WipType)]
|
||||
@@ -221,7 +221,7 @@ enum ReadResult {
|
||||
}
|
||||
```
|
||||
|
||||
このsyntaxも未決定である。少なくとも次を表現できる必要がある。
|
||||
このsyntaxも未決定である。Typeの対応付けでは、少なくとも次を表現できる必要がある。
|
||||
|
||||
- Unit、Boolean、Integer、Number、String、Bytes、Json、Entry。
|
||||
- Record、List、Enum、Union。
|
||||
@@ -229,15 +229,15 @@ enum ReadResult {
|
||||
- Requiredとoptionalなfieldおよびparameter。
|
||||
- Documentation。
|
||||
|
||||
Rustの`Option<T>`をoptional field / parameter以外で許可するか、enumをProtocol EnumまたはUnionへどう対応付けるか、newtypeをどのように扱うかは未決定である。
|
||||
Rustの`Option<T>`をoptional field / parameter以外でも許可するかは、まだ決めていない。EnumをProtocol EnumまたはUnionへどう対応付けるか、newtypeをどう扱うかも未決定である。
|
||||
|
||||
Rust SDKは、integerのProtocol相互運用範囲、finite number、unknown field、Union shape、Entry path等をProtocol boundaryで検証しなければならない。
|
||||
型の対応付けとは別に、Protocol boundaryでの検証も必要となる。Rust SDKは、integerのProtocol相互運用範囲、finite number、unknown field、Union shape、Entry path等をそこで検証しなければならない。
|
||||
|
||||
## Dynamic Worldspaceでのlifecycle
|
||||
|
||||
### `observe`
|
||||
|
||||
Projection implementationはrequest時にbackend dataを解決し、struct instanceを生成する。
|
||||
Projection implementationはrequest時にbackend dataを解決し、その時点のstruct instanceを生成する。
|
||||
|
||||
```rust
|
||||
async fn resolve_file(path: &WipPath) -> Result<PublishedObject> {
|
||||
@@ -255,9 +255,9 @@ async fn resolve_file(path: &WipPath) -> Result<PublishedObject> {
|
||||
}
|
||||
```
|
||||
|
||||
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Response生成後にこの`File` instanceを破棄してよく、Worldspace内の全fileに対応するinstanceを保持しない。
|
||||
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Responseを生成した後は、この`File` instanceを破棄してよい。Worldspace内の全fileに対応するinstanceを保持する必要はない。
|
||||
|
||||
Requested depthが正の場合、Directory listingで発見した各entryについて、その時点のstruct instanceを生成して公開できる。Providerがdirectory全体を先に収集してから`Vec`として返すことは要求しないが、一つのparentのobservationを成功させるには公開されたindexable childrenをclean exhaustionまで列挙しなければならない。
|
||||
Requested depthが正の場合は、Directory listingで発見した各entryについて、その時点のstruct instanceを生成して公開できる。Providerがdirectory全体を先に収集し、`Vec`として返すことは要求しない。ただし、一つのparentのobservationを成功させるには、公開されたindexable childrenをclean exhaustionまで列挙する必要がある。
|
||||
|
||||
```rust
|
||||
let mut entries = filesystem.discover_children(path, budget).await?;
|
||||
@@ -274,7 +274,7 @@ while let Some(entry) = entries.next().await? {
|
||||
}
|
||||
```
|
||||
|
||||
`discover_children`、`budget`、`observation`はconceptualであり、具体APIではない。必要なsemanticsは次である。
|
||||
`discover_children`、`budget`、`observation`は具体APIではなく、conceptualな表記である。Childの発見と公開には、次のsemanticsを要求する。
|
||||
|
||||
- 各childを現在の主体についてprojectし、非公開Objectとそのsubtreeを返さない。
|
||||
- 公開されたindexable childrenをすべて列挙し、clean exhaustionで終了する。
|
||||
@@ -286,7 +286,7 @@ while let Some(entry) = entries.next().await? {
|
||||
|
||||
### `call_operation`
|
||||
|
||||
Hostはcall時に、requestのTargetと`InterfaceTarget`をHost Runtimeへ渡す。Runtimeは一つのatomic execution boundaryへ入ってから`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
|
||||
Call時には現在のObjectを解決し直す。HostはrequestのTargetと`InterfaceTarget`をHost Runtimeへ渡し、Runtimeは一つのatomic execution boundaryに入ってから、`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
|
||||
|
||||
```rust
|
||||
runtime.call_current(
|
||||
@@ -299,7 +299,7 @@ runtime.call_current(
|
||||
).await
|
||||
```
|
||||
|
||||
`resolve_current_projection`と`runtime.call_current`というAPIを採用することは決定しない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、返す値はそのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む必要がある。このexampleが示す要件は次である。
|
||||
`resolve_current_projection`と`runtime.call_current`を実際のAPIとして採用するかは決めていない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、そのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む値を返す必要がある。上のexampleは、次の要件を表す。
|
||||
|
||||
- 過去の`observe`で作成したstruct instanceを保持していなくてもOperationを実行できる。
|
||||
- Call時の現在の主体、Object visibility、Object metadata、Interface集合を同じProjection pathで再解決し、Objectが非公開なら`NotFound`を返す。
|
||||
@@ -315,15 +315,15 @@ runtime.call_current(
|
||||
- Macro-generated dispatchが、選択されたInterface traitのmethodを現在のstruct instanceに対して呼び出す。異なるInterfaceの同名Operationをmergeまたは曖昧に解決しない。
|
||||
- Operation実行後の現在状態に対応するvalidatorを、必要に応じて`CallOperationResponse`へ返せる。
|
||||
|
||||
Object validatorをObject identityへ結び付けるためにClient-facingな`ref`を要求しない。ProviderまたはHostはHost-privateなidentityを使用できるが、そのidentity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとOperation implementationの固定、authorization、Operation実行を一つのatomic boundaryで行う。
|
||||
Object validatorとObject identityの関連付けに、Client-facingな`ref`は必須ではない。ProviderまたはHostはHost-privateなidentityを使用できる。ただし、identity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとOperation implementationの固定、authorization、Operation実行は、一つのatomic boundaryで行う。
|
||||
|
||||
Operation実行後validatorを、同じstruct instanceから再計算するか、Operation resultとともに返すか、backendを再観測するかは未決定である。どの方式でも、resultを生成した実行後状態とvalidatorを対応させなければならない。
|
||||
実行後のvalidatorをどこから取得するかも未決定である。同じstruct instanceから再計算する方式、Operation resultとともに返す方式、backendを再観測する方式が考えられるが、いずれもresultを生成した実行後状態とvalidatorを対応させる必要がある。
|
||||
|
||||
Structが`PathBuf`だけを保持し、validator比較後にpathを無条件で開き直す実装は、対象差し替えに対するatomicityを保証できない場合がある。Rust APIは、file descriptor、transaction、conditional update、lock等を利用してbackend固有のatomicityを実現できる必要があるが、その抽象化は未決定である。
|
||||
Structが`PathBuf`だけを保持している場合、validator比較後にpathを無条件で開き直すと、対象差し替えに対するatomicityを保証できないことがある。Rust APIには、file descriptor、transaction、conditional update、lock等でbackend固有のatomicityを実現できることを求める。そのための抽象化は未決定である。
|
||||
|
||||
## 複数Interfaceの実装
|
||||
|
||||
一つのstructは複数のInterface traitを実装できる。
|
||||
一つのstructは、複数のInterface traitを実装できる。
|
||||
|
||||
```rust
|
||||
impl ReadOnlyFileInterface for File {
|
||||
@@ -335,7 +335,7 @@ impl WritableFileInterface for File {
|
||||
}
|
||||
```
|
||||
|
||||
Publication時に、現在の主体へ公開する0個以上のInterfaceを選択し、表示したい順で追加する。
|
||||
そのうち、現在の主体へ公開する0個以上のInterfaceをpublication時に選び、表示したい順に追加する。
|
||||
|
||||
```rust
|
||||
let mut object = PublishedObject::new(file)
|
||||
@@ -348,15 +348,15 @@ if authorization.can_write() {
|
||||
object
|
||||
```
|
||||
|
||||
Protocol Objectの`interfaces`は追加順を保持するordered setである。同じInterface参照の重複は拒否する。各Interface Descriptorは独立したOperation集合を宣言し、複数trait implementationを一つのDescriptorへ暗黙にmergeしない。
|
||||
Protocol Objectの`interfaces`は追加順を保持するordered setであり、同じInterface参照の重複は拒否する。各Interface Descriptorは独立したOperation集合を宣言するため、複数のtrait implementationを一つのDescriptorへ暗黙にmergeしない。
|
||||
|
||||
異なるInterfaceは同じOperation名を宣言できる。Dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まり、表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従う。Signature全体をProtocol request fieldへparseし直さない。
|
||||
異なるInterfaceが同じOperation名を宣言しても、dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まる。表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従い、signature全体をProtocol request fieldへparseし直さない。
|
||||
|
||||
Rust traitのsupertrait、trait alias、複数traitの組み合わせをDescriptor生成へどう対応付けるかは未決定であり、Protocol上のInterface inheritanceを暗黙に導入しない。
|
||||
Rust traitのsupertrait、trait alias、複数traitの組み合わせをDescriptor生成にどう対応付けるかは未決定である。これらによって、Protocol上のInterface inheritanceを暗黙に導入することはしない。
|
||||
|
||||
## 固定Interface向けのsugar
|
||||
|
||||
一つのRust typeを常に同じInterface集合で公開する場合、次のようなsugarを追加してよい。
|
||||
一つのRust typeを常に同じInterface集合で公開する場合は、次のようなsugarを追加してよい。
|
||||
|
||||
```rust
|
||||
#[wip::object(interfaces = [ReadOnlyFileInterface, WritableFileInterface])]
|
||||
@@ -365,19 +365,19 @@ struct File {
|
||||
}
|
||||
```
|
||||
|
||||
または、conceptualには`WipObject`のassociated itemとしてdefault Interface集合を指定できる。
|
||||
別のconceptualな形として、`WipObject`のassociated itemにdefault Interface集合を指定することも考えられる。
|
||||
|
||||
ただし、固定Interface集合をcore modelにはしない。主体、policy、resource kind等に基づいて同じstructへ異なるInterface subsetを追加できるexplicit publication modelを基礎とする。
|
||||
ただし、core modelの基礎はexplicit publicationとする。主体、policy、resource kind等によって、同じstructへ異なるInterface subsetを追加できる必要があるため、固定Interface集合をcore modelにはしない。
|
||||
|
||||
Sugarを使用する場合も、対象typeが指定されたすべてのInterface traitを実装していることと、同じInterfaceを重複していないことを確認しなければならない。
|
||||
Sugarを使う場合も、対象typeが指定したすべてのInterface traitを実装していることと、同じInterfaceを重複していないことを確認する必要がある。
|
||||
|
||||
## HostへのInterface登録
|
||||
|
||||
Generated Interface DefinitionをHostへ登録し、構造化されたInterface参照を割り当てる必要がある。
|
||||
Generated Interface Definitionには、Hostへの登録を通じて構造化されたInterface参照を割り当てる必要がある。参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。
|
||||
|
||||
参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。以下のconceptual API例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めるものではない。登録時のcontextと引数の具体APIは引き続き未決定である。Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証し、`ref`がない場合のidentity追跡不能も許容する。Scopeの移動追跡や独立したscope validatorを導入しない。
|
||||
Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証する。`ref`がなければidentityを追跡できないことも許容し、scopeの移動追跡や独立したscope validatorは導入しない。
|
||||
|
||||
Conceptualには、eager registrationとlazy registrationの両方が考えられる。
|
||||
登録方法としては、conceptualにはeager registrationとlazy registrationの両方が考えられる。次の例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めてはいない。登録時のcontextと引数の具体APIも引き続き未決定である。
|
||||
|
||||
```rust
|
||||
let file_read_interface = host.register_interface(ReadOnlyFileInterfaceDefinition)?;
|
||||
@@ -387,9 +387,7 @@ let object = PublishedObject::new(file)
|
||||
.expose(file_write_interface);
|
||||
```
|
||||
|
||||
または、Hostが最初のpublication時に各definitionをinternしてよい。
|
||||
|
||||
どちらの場合も次を守る。
|
||||
また、Hostが最初のpublication時に各definitionをinternする方式でもよい。どちらの登録方法でも、次の条件を満たす必要がある。
|
||||
|
||||
- MutableなInterface参照では`fetch_interface`がvalidatorを返し、同じ参照とvalidatorの組から異なるDescriptorを返さない。
|
||||
- Validatorを返さないInterface参照は、その参照の有効期間中Descriptorをimmutableにする。
|
||||
@@ -401,7 +399,7 @@ let object = PublishedObject::new(file)
|
||||
|
||||
## Request contextとauthorization
|
||||
|
||||
Operation implementationは、Object instance以外にrequest contextを必要とし得る。
|
||||
Operation implementationが必要とする情報は、Object instanceだけとは限らない。Request contextとして、次の情報も必要になり得る。
|
||||
|
||||
- 現在の主体。
|
||||
- Cancellationとdeadline。
|
||||
@@ -409,30 +407,30 @@ Operation implementationは、Object instance以外にrequest contextを必要
|
||||
- Host serviceやbackend connectionへのaccess。
|
||||
- Resource limit。
|
||||
|
||||
これらをmethod parameter、receiver wrapper、generated context、task-local stateのどれで渡すかは未決定である。Protocol parameterとして宣言された値と、Hostが注入するcontextを明確に区別しなければならない。
|
||||
このcontextをmethod parameter、receiver wrapper、generated context、task-local stateのどれで渡すかは未決定である。どの形でも、Protocol parameterとして宣言された値とHostが注入するcontextは明確に区別する必要がある。
|
||||
|
||||
Object publication時のInterface集合の選択と、Operation call時のmembership、Interface validator、authorizationの再評価を実装できる必要がある。以前の`observe`で公開されたInterface集合だけを根拠に、現在のOperation実行を許可してはならない。
|
||||
Interface集合はObject publication時に選択するだけでなく、Operation call時にもmembership、Interface validator、authorizationを再評価できなければならない。以前の`observe`で公開したInterface集合だけを根拠に、現在のOperation実行を許可することはできない。
|
||||
|
||||
Operation resultのRecord、List、Union等へnestedしたすべての`Entry`位置について、Hostは現在の主体にそのpathを認識させてよいことを再帰的に確認できなければならない。通常のstructural Value validationだけではこのvisibility checkを満たさない。Macro-generated code、Projection、Host Runtimeのどこで確認するかは未決定である。
|
||||
Resultのvisibility checkも、通常のstructural Value validationとは別に必要となる。Hostは、Operation resultのRecord、List、Union等にnestedしたすべての`Entry`について、現在の主体にそのpathを認識させてよいかを再帰的に確認できなければならない。この確認をMacro-generated code、Projection、Host Runtimeのどこで行うかは未決定である。
|
||||
|
||||
Operation argumentとして`Entry` pathを受け取った場合も、pathの所持をauthorizationの証明として扱わず、参照先へ作用する時点で現在の主体について認可する。
|
||||
Argumentとして受け取った`Entry` pathについても、pathの所持をauthorizationの証明にはしない。参照先へ作用する時点で、現在の主体について認可する。
|
||||
|
||||
## Error model
|
||||
|
||||
Rust methodのerror表現は、次の四種類を区別できなければならない。
|
||||
Rust methodのerror表現には、次の四種類を区別できることを求める。
|
||||
|
||||
- Protocol validationまたはdispatch failure。
|
||||
- Effectがcommitされていないと保証できるHost / backend implementation failure。
|
||||
- Operationの未実行またはrollbackを保証できない`OperationOutcomeUnknown`。
|
||||
- Interfaceがreturn typeとして宣言したdomain failure。
|
||||
|
||||
現在のProtocolでは、domain failureはOperation resultのUnion caseとして表す。Rustの`Result<T, E>`をdomain Union、Host error、または両方のどれへ対応付けるかは未決定である。
|
||||
現在のProtocolはdomain failureをOperation resultのUnion caseとして表す。Rustの`Result<T, E>`をdomain Union、Host error、またはその両方のどれに対応付けるかは未決定である。
|
||||
|
||||
MacroがRust panic、result encode failure、宣言型に違反するimplementation resultをdomain failureへ自動変換してはならない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できない場合は`OperationOutcomeUnknown`へmappingする。Clientへ送信済みか不明なtransport切断も自動retryしない。
|
||||
Rust panic、result encode failure、宣言型に違反するimplementation resultを、Macroがdomain failureへ自動変換することは認めない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できなければ`OperationOutcomeUnknown`へmappingする。Clientへ送信済みかどうか不明なtransport切断についても、自動retryはしない。
|
||||
|
||||
## 要件
|
||||
|
||||
Rust API modelは少なくとも次を満たす。
|
||||
このdraftのRust API modelに求める要件は、少なくとも次のとおりである。
|
||||
|
||||
- Interface Descriptorをtrait declarationから生成し、trait implementationごとに変化させない。
|
||||
- Structが`WipObject`と、追加する各Interface traitを実装していることをcompile timeに確認する。
|
||||
@@ -459,7 +457,7 @@ Rust API modelは少なくとも次を満たす。
|
||||
|
||||
## 非目標
|
||||
|
||||
このdraftは次を決定しない。
|
||||
次の事項は、このdraftでは決定しない。
|
||||
|
||||
- 最終的なcrate、module、trait、attribute、deriveの名前。
|
||||
- Proc macroの内部実装。
|
||||
@@ -495,4 +493,4 @@ Rust API modelは少なくとも次を満たす。
|
||||
- 主体ごとに異なるInterface combinationを追加したPublished Objectのconcrete return typeをどう統一するか。
|
||||
- Rust client APIを同じtrait declarationから生成するか。
|
||||
|
||||
これらを決定する際は、静的service objectだけでなく、Filesystem、database row、virtual aggregate、主体別Interface compositionを同じAPIで実装できるか評価する。
|
||||
これらの選択は、静的service objectに使えるだけでは足りない。Filesystem、database row、virtual aggregate、主体別Interface compositionも、同じAPIで実装できるかを評価して決定する。
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
## Status
|
||||
|
||||
この文書は、WIP HostをTypeScriptで実装するための概念的なAPI modelを整理するdraftである。
|
||||
TypeScriptの型は、通常のJavaScript outputには残らない。WIP Hostがruntimeに必要とするInterface Descriptorやvalidationをどう定義するか。このdraftは、TypeScriptでHostを実装するための概念的なAPI modelを提案する。
|
||||
|
||||
このdraftで示すfunction、object shape、generic type、class、method signatureは説明用であり、具体的なTypeScript API syntaxとして確定しない。Package構成、schema builderの最終名称、ownership、async context、error type、bundler integrationも未決定である。
|
||||
Function、object shape、generic type、class、method signatureは説明用であり、具体的なTypeScript API syntaxは確定していない。Package構成、schema builderの最終名称、ownership、async context、error type、bundler integrationも未決定である。
|
||||
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)を参照する。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するRust modelは[Rust API Model](rust-api-model.md)を参照する。
|
||||
Protocol上の確定事項は[Core Model](../2-core-model.md)、[Object tree / Schema](../2.1-object-tree-schema.md)、[Operation and Interface](../2.2-operation-and-interface.md)、[Protocol](../3-protocol.md)に従う。動的なObject projectionの運用要件は[Dynamic Worldspace Projection](dynamic-worldspace-projection.md)、対応するRust modelは[Rust API Model](rust-api-model.md)を参照する。
|
||||
|
||||
## 目的
|
||||
|
||||
TypeScript APIでは、次のmodelを自然に表現できるようにする。
|
||||
TypeScript APIでは、runtimeに残るdefinition objectを使い、Protocol上の宣言とTypeScript型の推論を対応付けるmodelを自然に表現できるようにする。Objectの実装と、ある時点で公開するInterfaceの選択は分けて扱う。
|
||||
|
||||
1. Runtimeに残るdefinition objectでWIP Interfaceを宣言する。
|
||||
2. 同じdefinition objectからInterface Descriptor、Value codec、validationを構築する。
|
||||
@@ -20,11 +20,11 @@ TypeScript APIでは、次のmodelを自然に表現できるようにする。
|
||||
6. Object instanceをWorldspace全体について常駐させず、`observe`と`call_operation`の解決時にdata-drivenに生成できる。
|
||||
7. Custom transpiler、TypeScript compiler plugin、decorator metadataをcore APIの前提にしない。
|
||||
|
||||
このmodelでは、Protocol上のObjectとInterfaceの関連付けは`Object.interfaces`だけで表す。Operation implementationへ到達するためのTypeScript / JavaScript内部codeはSDK / Host Runtimeの実装詳細であり、新しいProtocol conceptを導入しない。
|
||||
Protocol上でObjectとInterfaceを関連付けるのは`Object.interfaces`だけである。Operation implementationを呼び出すためのTypeScript / JavaScript内部codeはSDK / Host Runtimeの実装詳細として扱い、新しいProtocol conceptは導入しない。
|
||||
|
||||
## TypeScriptの型消去
|
||||
|
||||
TypeScriptの`interface`、`type`、generic type argumentは、通常のJavaScript outputには残らない。
|
||||
TypeScriptの`interface`、`type`、generic type argumentは、通常のJavaScript outputには残らない。たとえば、次のdeclarationだけからruntimeにInterface Descriptorを取得することはできない。
|
||||
|
||||
```ts
|
||||
interface FileOperations {
|
||||
@@ -32,13 +32,11 @@ interface FileOperations {
|
||||
}
|
||||
```
|
||||
|
||||
このdeclarationだけから、runtimeにInterface Descriptorを取得することはできない。
|
||||
|
||||
```ts
|
||||
host.registerInterface(FileOperations); // runtime valueではない
|
||||
```
|
||||
|
||||
そのため、TypeScript APIではruntime valueをsource of truthにする。
|
||||
そこで、TypeScript APIではruntime valueをsource of truthにする。
|
||||
|
||||
```ts
|
||||
const FileInterface = wip.interface({
|
||||
@@ -46,13 +44,13 @@ const FileInterface = wip.interface({
|
||||
});
|
||||
```
|
||||
|
||||
このobjectは通常のJavaScript valueとしてtranspile後も残る。TypeScript型は、このruntime definitionから推論する。
|
||||
このobjectは、通常のJavaScript valueとしてtranspile後も残る。TypeScript型は、このruntime definitionから推論する。
|
||||
|
||||
## Conceptual model
|
||||
|
||||
### Type definition
|
||||
|
||||
Record、Enum、Union等もruntime definition objectとして宣言する。
|
||||
Record、Enum、Union等の型も、runtime definition objectとして宣言する。
|
||||
|
||||
```ts
|
||||
const WriteResult = wip.union({
|
||||
@@ -70,17 +68,17 @@ const WriteResult = wip.union({
|
||||
});
|
||||
```
|
||||
|
||||
TypeScript型はdefinitionから推論する。
|
||||
このdefinitionから、TypeScript型を推論する。
|
||||
|
||||
```ts
|
||||
type WriteResult = wip.Infer<typeof WriteResult>;
|
||||
```
|
||||
|
||||
`wip.Infer`の具体的な型実装と、Union DTOのTypeScript representationは未決定である。Runtime definitionと推論された型が、同じProtocol `TypeExpr`および`Value` semanticsを表すことが要件である。
|
||||
`wip.Infer`の具体的な型実装とUnion DTOのTypeScript representationは、まだ決めていない。Runtime definitionと推論した型が、同じProtocol `TypeExpr`および`Value` semanticsを表すことを要件とする。
|
||||
|
||||
### Interface definition
|
||||
|
||||
WIP Interfaceはruntime definition objectとして宣言する。
|
||||
WIP Interfaceも、runtime definition objectとして宣言する。
|
||||
|
||||
```ts
|
||||
const FileInterface = wip.interface({
|
||||
@@ -125,9 +123,9 @@ const FileInterface = wip.interface({
|
||||
});
|
||||
```
|
||||
|
||||
このsyntaxはconceptualである。Definition objectのproperty名、documentationの指定方法、Named typeの参照方法、`optional`の表現は未決定である。
|
||||
このsyntaxはconceptualであり、具体的なAPIとして確定したものではない。Definition objectのproperty名、documentationの指定方法、Named typeの参照方法、`optional`の表現は未決定である。
|
||||
|
||||
Interface definitionは、次のlogical declarationに対応する。
|
||||
Interface definitionとProtocol上の宣言は、次のように対応付ける。
|
||||
|
||||
- 一つのruntime definition objectを、一つのInterface Descriptorを構築するTypeScript側definitionとして扱う。
|
||||
- JavaScript variable名`FileInterface`はlocal code上の識別子であり、Protocol `InterfaceDescriptor`のfieldや構造化されたInterface参照としてそのまま公開しない。
|
||||
@@ -137,22 +135,24 @@ Interface definitionは、次のlogical declarationに対応する。
|
||||
- Runtime type definitionをDescriptorの`TypeExpr`とProtocol `Value`へ対応付ける。
|
||||
- DocumentationをInterface、Operation、parameter、return、type、field、caseへ指定できるようにする。
|
||||
|
||||
Descriptorのshapeはruntime definition objectによって決まり、各classまたはplain objectのimplementationによって変化しない。
|
||||
Descriptorのshapeを決めるのはruntime definition objectである。各classまたはplain objectがどう実装するかによって、Descriptorは変化しない。
|
||||
|
||||
Operation、parameter、type、field、caseのProtocol名はfinalized definition内のstableなstring dataとして保持する。JavaScript variable名、constructor名、functionの`.name`、prototype上のmethod列挙から推測しない。Hostはincoming Operation名をfinalized dispatch table上のinternal tokenまたはaccessorへ解決し、Clientから受け取った名前をそのままobject property lookupへ使用しない。Object-literal keyをauthoring sugarとして使う場合にproperty manglingからどう保護するかは未決定である。
|
||||
Operation、parameter、type、field、caseのProtocol名は、finalized definition内にstableなstring dataとして保持する。JavaScript variable名、constructor名、functionの`.name`、prototype上のmethod列挙から推測することはしない。
|
||||
|
||||
Definition objectはHostへの登録時に一つのimmutableなartifactとしてfinalizeする。MutableなProtocol Interface参照を提供する場合は、同じ参照へ新しいvalidatorと新しいfinalized artifactを対応付け、同じ参照とvalidatorの組から異なるDescriptorを返してはならない。
|
||||
Hostはincoming Operation名を、finalized dispatch table上のinternal tokenまたはaccessorへ解決する。Clientから受け取った名前をそのままobject property lookupに使うことはしない。Object-literal keyをauthoring sugarとして使う場合、property manglingからどう保護するかは未決定である。
|
||||
|
||||
Definition objectは、Hostへの登録時に一つのimmutableなartifactとしてfinalizeする。MutableなProtocol Interface参照を提供する場合は、同じ参照へ新しいvalidatorと新しいfinalized artifactを対応付ける。同じ参照とvalidatorの組から異なるDescriptorを返すことは認めない。
|
||||
|
||||
### Operation implementation type
|
||||
|
||||
Interface definitionから、必要なOperation implementationのTypeScript型を推論する。
|
||||
必要なOperation implementationのTypeScript型は、Interface definitionから推論する。
|
||||
|
||||
```ts
|
||||
type FileOperations =
|
||||
wip.Implementation<typeof FileInterface>;
|
||||
```
|
||||
|
||||
Conceptualには、次のようなobject typeへ展開される。
|
||||
概念的には、次のようなobject typeへ展開される。
|
||||
|
||||
```ts
|
||||
type FileOperations = {
|
||||
@@ -167,9 +167,9 @@ type FileOperations = {
|
||||
};
|
||||
```
|
||||
|
||||
Function-valued propertyを基本形とし、`strictFunctionTypes`を含むstrictなcompiler settingsの下でparameterをcontravariantに検査できるようにする。通常のclass method parameterはTypeScriptのassignabilityでbivariantに扱われる場合があるため、method-shapedな`implements`だけを「すべてのschema-valid argumentを安全に受け取れる」ことの完全な証明としては扱わない。
|
||||
Function-valued propertyを基本形とし、`strictFunctionTypes`を含むstrictなcompiler settingsの下でparameterをcontravariantに検査できるようにする。通常のclass method parameterは、TypeScriptのassignabilityでbivariantに扱われる場合がある。そのため、method-shapedな`implements`だけを「すべてのschema-valid argumentを安全に受け取れる」ことの完全な証明にはしない。
|
||||
|
||||
Definition-awareなbuilderでimplementationをcontextual typingする形も考えられる。
|
||||
Definition-awareなbuilderによって、implementationをcontextual typingする形も考えられる。
|
||||
|
||||
```ts
|
||||
const operations = FileInterface.implement({
|
||||
@@ -183,13 +183,13 @@ const operations = FileInterface.implement({
|
||||
});
|
||||
```
|
||||
|
||||
`implement`の採用は未決定である。どの形でもruntime validationとcallable checkをauthorityとし、TypeScript型はdeveloper feedbackとして扱う。
|
||||
`implement`を採用するかは未決定である。どの形でも、実行時の判定はruntime validationとcallable checkをauthorityとし、TypeScript型はdeveloper feedbackとして扱う。
|
||||
|
||||
このfunction property shapeは説明用である。Operation parameterを一つのarguments objectとして渡すか、request contextを別parameterにするか、sync returnを許可するかは未決定である。
|
||||
上のfunction property shapeも説明用である。Operation parameterを一つのarguments objectとして渡すか、request contextを別parameterにするか、sync returnを許可するかは、まだ決めていない。
|
||||
|
||||
### Object implementation
|
||||
|
||||
Classは、その時点でWorldspaceへ投影するObjectをHost内部で表現できる。
|
||||
その時点でWorldspaceへ投影するObjectは、Host内部ではclassとして表現できる。
|
||||
|
||||
```ts
|
||||
class File implements WipObject, FileOperations {
|
||||
@@ -218,7 +218,7 @@ class File implements WipObject, FileOperations {
|
||||
}
|
||||
```
|
||||
|
||||
`WipObject`と`WipObjectMetadata`の具体的なshapeは未決定である。概念的にはProtocol Objectのうち、publication時に選択するInterface集合以外の公開metadataを提供する。
|
||||
`WipObject`と`WipObjectMetadata`は、Protocol Objectの公開metadataのうち、publication時に選ぶInterface集合以外を提供するための概念的な型である。具体的なshapeは未決定である。
|
||||
|
||||
```ts
|
||||
interface WipObject {
|
||||
@@ -233,16 +233,16 @@ interface WipObjectMetadata {
|
||||
}
|
||||
```
|
||||
|
||||
`WipObjectMetadata`へ次を含めない。これらをimplementing classのprivate fieldとして保持することは禁止しない。
|
||||
Classが保持する情報のすべてを公開metadataにするわけではない。次の情報は`WipObjectMetadata`に含めないが、implementing classのprivate fieldとして保持してよい。
|
||||
|
||||
- Absolute path。PathはObjectのfieldではなく、Worldspace resolutionのcontextである。
|
||||
- Children。ChildrenはTree上の配置contextである。
|
||||
- 固定されたInterface集合。InterfaceはObjectを公開する時点で追加する。
|
||||
- Backend connection、file descriptor、credential等のHost-private state。
|
||||
|
||||
Classが保持するpathやbackend handle等をOperation implementationに使用してよいが、Object metadataまたはProtocol Objectへ自動的にserializeしない。
|
||||
Classのpathやbackend handleはOperation implementationで使用できる。ただし、Object metadataやProtocol Objectへ自動的にserializeする対象にはしない。
|
||||
|
||||
Classの使用は必須ではない。Structural typingを利用してplain objectも使用できる。
|
||||
また、classの使用は必須ではない。Structural typingを利用し、plain objectを使うこともできる。
|
||||
|
||||
```ts
|
||||
const file = {
|
||||
@@ -262,7 +262,7 @@ const file = {
|
||||
|
||||
### Object publication
|
||||
|
||||
ObjectをWorldspaceへ返す時点で、object instanceと公開する0個以上のInterface definitionを明示的に組み合わせる。Interfaceは追加順を保持するordered setであり、同じdefinitionまたは同じ登録済み参照を重複して追加しない。
|
||||
ObjectをWorldspaceへ返す時点で、object instanceと、公開する0個以上のInterface definitionを明示的に組み合わせる。Interfaceは追加順を保持するordered setとし、同じdefinitionまたは同じ登録済み参照の重複追加は認めない。
|
||||
|
||||
```ts
|
||||
const file = new File(path, objectMetadata);
|
||||
@@ -270,7 +270,7 @@ const object = wip.publish(file)
|
||||
.expose(FileInterface, file);
|
||||
```
|
||||
|
||||
Publication APIはconceptualに、追加する各definitionと、そのImplementation型を満たすbindingを受け取る。
|
||||
Publication APIは、概念的には各definitionと、そのImplementation型を満たすbindingを受け取る。
|
||||
|
||||
```ts
|
||||
interface WipInterfaceDefinition<Implementation extends object> {
|
||||
@@ -285,11 +285,13 @@ interface PublishedObject<T extends WipObject> {
|
||||
}
|
||||
```
|
||||
|
||||
実際のTypeScript generic表現は未決定である。このconstraintは、strictなcompiler settingsとfunction-valued property shapeを使用する場合に、追加する各Interfaceへbindした値が必要なOperation functionを提供するか検査する。Object instance自身をimplementationとして渡しても、Interface専用のadapter objectを渡してもよく、どのInterfaceも追加しないObjectも表現できる。通常のclass methodやtype assertion等で検査を弱められるため、各Interfaceを追加する時点とdispatch時のruntime callable check、およびValue validationは常に必要である。
|
||||
実際のTypeScript generic表現は未決定である。このconstraintは、strictなcompiler settingsとfunction-valued property shapeを使用した場合に、各Interfaceへbindする値が必要なOperation functionを提供するかを検査するためのものである。
|
||||
|
||||
Host Runtimeは各bindingを登録済みInterface参照と対応付ける。異なるInterfaceが同名Operationを宣言しても、選択されたInterface参照に対応するbindingだけをdispatch対象とし、単一object上の同名propertyへmergeしない。
|
||||
ImplementationにはObject instance自身を渡しても、Interface専用のadapter objectを渡してもよい。Interfaceを一つも追加しないObjectも表現できる。ただし、通常のclass methodやtype assertion等で型の検査を弱められるため、各Interfaceの追加時とdispatch時にはruntime callable checkを行い、Value validationも常に行う必要がある。
|
||||
|
||||
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeとして追加しない。Host Runtimeはこれを使用して次を構築する。
|
||||
Host Runtimeは、各bindingを登録済みInterface参照と対応付ける。異なるInterfaceが同名Operationを宣言していても、dispatch対象は選択されたInterface参照に対応するbindingだけであり、単一object上の同名propertyへmergeしない。
|
||||
|
||||
`PublishedObject`はHost SDK内のconceptual typeであり、Protocol typeには追加しない。Host Runtimeはこの値からProtocol Objectを構築する。
|
||||
|
||||
```ts
|
||||
const protocolObject = {
|
||||
@@ -301,15 +303,17 @@ const protocolObject = {
|
||||
};
|
||||
```
|
||||
|
||||
Optional propertyの`undefined`はwireへ出力せず、field省略として扱う。`null`へ自動変換しない。
|
||||
Optional propertyの`undefined`はwireへ出力せず、fieldの省略として扱う。`null`へ自動変換することはしない。
|
||||
|
||||
`selectedInterfaceReferences`は、Hostが各runtime Interface definitionを登録または公開するときに割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べたものである。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Variable名やJavaScript object identityをportableなProtocol参照としてそのまま使用することは要求しない。
|
||||
`selectedInterfaceReferences`には、Hostが各runtime Interface definitionの登録または公開時に割り当てる構造化参照`{ scope, name }`を、publication APIへの追加順で並べる。同じ`(scope, name)`の重複は拒否し、Objectの配置pathに対する祖先制約も検証する。Variable名やJavaScript object identityを、そのままportableなProtocol参照として使用することは要求しない。
|
||||
|
||||
`observe`はDescriptor自体をObjectへ埋め込まず、このInterface参照のordered setだけを返す。Clientが各参照を`fetch_interface`したとき、Host Runtimeはruntime definition objectから構築したDescriptorと、存在する場合はInterface validatorを返す。同じ参照とvalidatorの組のDescriptorはHost上で共有およびcacheできるため、Object instanceごとにDescriptorを再生成または再送する必要はない。
|
||||
`observe`でObjectに含めるのは、Descriptor自体ではなく、このInterface参照のordered setだけである。Clientが各参照を`fetch_interface`すると、Host Runtimeはruntime definition objectから構築したDescriptorと、存在する場合はInterface validatorを返す。
|
||||
|
||||
同じ参照とvalidatorの組に対応するDescriptorは、Host上で共有およびcacheできる。このため、Object instanceごとにDescriptorを再生成したり再送したりする必要はない。
|
||||
|
||||
## Runtime definitionの責務
|
||||
|
||||
`wip.interface(...)`が返すdefinition objectは、conceptualには次を生成または提供する。
|
||||
`wip.interface(...)`が返すdefinition objectには、Descriptorの構築に加えて、Valueの変換・検証とInterfaceごとのdispatchに必要な情報を提供する役割を想定する。
|
||||
|
||||
- Interface Descriptorを構築するruntime definition。
|
||||
- Operation propertyとOperation Declarationの対応情報。
|
||||
@@ -320,7 +324,7 @@ Optional propertyの`undefined`はwireへ出力せず、field省略として扱
|
||||
- 各Interfaceの推論されたImplementation型を満たす値を、そのInterface参照へbindするtyped entry point。
|
||||
- HostがInterface参照、optional validator、Descriptorを登録、取得、cacheするためのlocal identity。
|
||||
|
||||
TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである。Runtimeでは少なくとも次を検証する。
|
||||
TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである。Runtimeでは、少なくとも次を検証する必要がある。
|
||||
|
||||
- Object metadataがProtocol上有効である。
|
||||
- 追加する各InterfaceへbindしたOperation implementationが呼び出し可能である。
|
||||
@@ -329,13 +333,11 @@ TypeScriptのstructural type checkはcompile-timeのdeveloper feedbackである
|
||||
- ResultがDescriptorに従っている。
|
||||
- Integer、Number、Entry、Record、Union等の追加制約を満たす。
|
||||
|
||||
Generatedまたはgenericなdispatch codeはTypeScript SDK内部の実装詳細である。Host内部のdispatch mechanism、class名、prototype、constructor等をProtocolへ公開しない。
|
||||
Generatedまたはgenericなdispatch codeは、TypeScript SDK内部の実装詳細である。Host内部のdispatch mechanism、class名、prototype、constructor等はProtocolへ公開しない。
|
||||
|
||||
## TypeScript typeとProtocol type
|
||||
|
||||
Runtime definitionは、Descriptorの`TypeExpr`、Protocol `Value`、TypeScript static typeの三つを対応付ける。
|
||||
|
||||
Conceptualな対応例は次のとおりである。
|
||||
Runtime definitionは、Descriptorの`TypeExpr`、Protocol `Value`、TypeScript static typeの三つを対応付ける。次の表はconceptualな対応例であり、具体的なpublic typeは未決定である。
|
||||
|
||||
| WIP definition | TypeScript representation | Runtime validation |
|
||||
| --- | --- | --- |
|
||||
@@ -352,21 +354,19 @@ Conceptualな対応例は次のとおりである。
|
||||
| `wip.enum(...)` | String literal union | 宣言caseのみ |
|
||||
| `wip.union(...)` | Discriminated union | Case、payload、shape |
|
||||
|
||||
この表の具体的なpublic typeは未決定である。
|
||||
`wip.json()`が受け付けるのは、null、boolean、finite number、string、Array、およびstring-keyedなplain objectから再帰的に構成されるJSON-compatible valueだけである。`undefined`、`bigint`、`symbol`、function、`Uint8Array`、`Date`、`Map`、`Set`、class instance、cyclic object graph、NaN、正負Infinity、sparse array等は、暗黙にJsonへ変換せずvalidation failureとする。Integerとして表現する値にも、Protocolの相互運用範囲を適用する。
|
||||
|
||||
`wip.json()`が受け付けるのは、null、boolean、finite number、string、Array、およびstring-keyedなplain objectから再帰的に構成されるJSON-compatible valueだけである。`undefined`、`bigint`、`symbol`、function、`Uint8Array`、`Date`、`Map`、`Set`、class instance、cyclic object graph、NaN、正負Infinity、sparse array等を暗黙にJsonへ変換せず、validation failureとする。Integerとして表現する値にもProtocolの相互運用範囲を適用する。
|
||||
TypeScriptの`number`はIntegerにもNumberにも使えるため、runtime schemaの位置に基づいて検証する。`wip.integer()`ではProtocolの相互運用範囲を超える値を拒否し、`bigint`を暗黙にIntegerへ変換しない。
|
||||
|
||||
TypeScriptの`number`はIntegerとNumberの両方に使用できるため、runtime schemaの位置に基づいて検証する。`wip.integer()`はProtocolの相互運用範囲を超える値を拒否する。`bigint`を暗黙にIntegerへ変換しない。
|
||||
Protocol `Unit`には、たとえば`wip.unitValue`のような専用singleton / sentinelを使い、`undefined`は使わない。RequiredなUnit fieldではsentinelを明示する。OptionalなUnit fieldでは、sentinelがpresent Unitを表し、property欠落またはoptional positionの`undefined`が省略を表す。
|
||||
|
||||
Protocol `Unit`は、例えば`wip.unitValue`のような専用singleton / sentinelで表す。`undefined`をUnitとして使用しない。RequiredなUnit fieldはsentinelを明示し、optionalなUnit fieldではsentinelがpresent Unit、property欠落またはoptional positionの`undefined`が省略を表す。
|
||||
|
||||
`wip.optional(T)`はfieldまたはparameterの省略を表し、`null`を許可する意味ではない。Implementationへ渡すarguments objectではproperty欠落を省略とし、optional positionへ明示された`undefined`をSDK convenienceとして省略へnormalizeしてよい。`undefined`自体をProtocol Valueとしてencodeせず、required positionの`undefined`はvalidation failureとする。
|
||||
同様に、`wip.optional(T)`はfieldまたはparameterの省略を表すものであり、`null`を許可する意味ではない。Implementationへ渡すarguments objectではproperty欠落を省略として扱う。Optional positionに明示した`undefined`は、SDK convenienceとして省略へnormalizeしてよいが、`undefined`自体をProtocol Valueとしてencodeすることはしない。Required positionの`undefined`はvalidation failureとする。
|
||||
|
||||
## Dynamic Worldspaceでのlifecycle
|
||||
|
||||
### `observe`
|
||||
|
||||
Projection implementationはrequest時にbackend dataを解決し、classまたはplain object instanceを生成する。
|
||||
Projection implementationはrequest時にbackend dataを解決し、その時点のclassまたはplain object instanceを生成する。
|
||||
|
||||
```ts
|
||||
async function resolveFile(
|
||||
@@ -399,9 +399,9 @@ async function resolveFile(
|
||||
}
|
||||
```
|
||||
|
||||
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Response生成後にこの`File` instanceを破棄してよく、Worldspace内の全fileに対応するinstanceを保持しない。
|
||||
Host Runtimeは`PublishedObject`からProtocol Objectを返す。Responseを生成した後は、この`File` instanceを破棄してよい。Worldspace内の全fileに対応するinstanceを保持する必要はない。
|
||||
|
||||
Requested depthが正の場合、Providerはdirect childrenをlazyに発見できる。Directory全体を先に収集してArrayとして返すことは要求しないが、一つのparentのobservationを成功させるには公開されたindexable childrenをclean exhaustionまで列挙しなければならない。ConceptualにはAsync Iterable等を利用できる。
|
||||
Requested depthが正の場合、Providerはdirect childrenをlazyに発見できる。Directory全体を先に収集し、Arrayとして返すことは要求しない。ただし、一つのparentのobservationを成功させるには、公開されたindexable childrenをclean exhaustionまで列挙する必要がある。概念的には、Async Iterable等を利用できる。
|
||||
|
||||
```ts
|
||||
const entries = filesystem.discoverChildren(path, budget);
|
||||
@@ -420,7 +420,7 @@ for await (const entry of entries) {
|
||||
}
|
||||
```
|
||||
|
||||
`discoverChildren`、`budget`、`observation`はconceptualであり、具体APIではない。必要なsemanticsは次である。
|
||||
`discoverChildren`、`budget`、`observation`は具体APIではなく、conceptualな表記である。Childの発見と公開には、次のsemanticsを要求する。
|
||||
|
||||
- 各childを現在の主体についてprojectし、非公開Objectとそのsubtreeを返さない。
|
||||
- 公開されたindexable childrenをすべて列挙し、clean exhaustionで終了する。
|
||||
@@ -432,7 +432,7 @@ for await (const entry of entries) {
|
||||
|
||||
### `call_operation`
|
||||
|
||||
Hostはcall時に、requestのTargetと`InterfaceTarget`をHost Runtimeへ渡す。Runtimeは一つのatomic execution boundaryへ入ってから`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
|
||||
Call時には現在のObjectを解決し直す。HostはrequestのTargetと`InterfaceTarget`をHost Runtimeへ渡し、Runtimeは一つのatomic execution boundaryに入ってから、`target.path`を現在のObject implementationとstableなbackend対象へ解決する。
|
||||
|
||||
```ts
|
||||
await runtime.callCurrent(
|
||||
@@ -445,7 +445,7 @@ await runtime.callCurrent(
|
||||
);
|
||||
```
|
||||
|
||||
`resolveCurrentProjection`と`runtime.callCurrent`というAPIを採用することは決定しない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、返す値はそのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む必要がある。このexampleが示す要件は次である。
|
||||
`resolveCurrentProjection`と`runtime.callCurrent`を実際のAPIとして採用するかは決めていない。ResolverはRuntimeが開始したexecution boundary内で呼ばれ、そのboundary中にObject identityとbackend対象を安定して保持するhandleまたはtransaction contextを含む値を返す必要がある。上のexampleは、次の要件を表す。
|
||||
|
||||
- 過去の`observe`で作成したobject instanceを保持していなくてもOperationを実行できる。
|
||||
- Call時の現在の主体、Object visibility、Object metadata、Interface集合を同じProjection pathで再解決し、Objectが非公開なら`NotFound`を返す。
|
||||
@@ -461,15 +461,15 @@ await runtime.callCurrent(
|
||||
- Runtime dispatchが、選択されたInterface definitionへbindしたOperation implementationを現在のObject contextへ適用する。異なるInterfaceの同名Operationをmergeまたは曖昧に解決しない。
|
||||
- Operation実行後の現在状態に対応するvalidatorを、必要に応じて`CallOperationResponse`へ返せる。
|
||||
|
||||
Object validatorをObject identityへ結び付けるためにClient-facingな`ref`を要求しない。ProviderまたはHostはHost-privateなidentityを使用できるが、そのidentity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとInterface-specific implementation bindingの固定、authorization、Operation実行を一つのatomic boundaryで行う。
|
||||
Object validatorとObject identityの関連付けに、Client-facingな`ref`は必須ではない。ProviderまたはHostはHost-privateなidentityを使用できる。ただし、identity confirmation、Object validator比較、Interface membershipとvalidator比較、DescriptorとInterface-specific implementation bindingの固定、authorization、Operation実行は、一つのatomic boundaryで行う。
|
||||
|
||||
Operation実行後validatorを、同じobject instanceから再計算するか、Operation resultとともに返すか、backendを再観測するかは未決定である。どの方式でも、resultを生成した実行後状態とvalidatorを対応させなければならない。
|
||||
実行後のvalidatorをどこから取得するかも未決定である。同じobject instanceから再計算する方式、Operation resultとともに返す方式、backendを再観測する方式が考えられるが、いずれもresultを生成した実行後状態とvalidatorを対応させる必要がある。
|
||||
|
||||
Object instanceがpath文字列だけを保持し、validator比較後にpathを無条件で開き直す実装は、対象差し替えに対するatomicityを保証できない場合がある。TypeScript APIは、transaction、conditional update、backend handle、lock等を利用してbackend固有のatomicityを実現できる必要があるが、その抽象化は未決定である。
|
||||
Object instanceがpath文字列だけを保持している場合、validator比較後にpathを無条件で開き直すと、対象差し替えに対するatomicityを保証できないことがある。TypeScript APIには、transaction、conditional update、backend handle、lock等でbackend固有のatomicityを実現できることを求める。そのための抽象化は未決定である。
|
||||
|
||||
## 複数Interfaceの実装
|
||||
|
||||
一つのclassまたはplain objectは複数のInterface implementation typeを満たせる。Property名が衝突する場合やInterfaceごとに異なるbehaviorを提供する場合は、Interfaceごとのadapter objectをbindできる。
|
||||
一つのclassまたはplain objectは、複数のInterface implementation typeを満たせる。Property名が衝突する場合や、Interfaceごとに異なるbehaviorを提供する場合は、Interfaceごとのadapter objectをbindできる。
|
||||
|
||||
```ts
|
||||
type ReadOnlyFileOperations =
|
||||
@@ -488,7 +488,7 @@ class File
|
||||
}
|
||||
```
|
||||
|
||||
Publication時に、現在の主体へ公開する0個以上のInterfaceを選択し、表示したい順で追加する。
|
||||
現在の主体へ公開する0個以上のInterfaceはpublication時に選び、表示したい順に追加する。
|
||||
|
||||
```ts
|
||||
let object = wip.publish(file)
|
||||
@@ -505,9 +505,9 @@ if (authorization.canWrite) {
|
||||
return object;
|
||||
```
|
||||
|
||||
Protocol Objectの`interfaces`は追加順を保持するordered setである。同じInterface参照の重複は拒否する。複数のImplementation bindingを一つのDescriptorやdispatch tableへ暗黙にmergeせず、各Interface Descriptorとbindingは独立したOperation集合およびbehaviorを提供する。
|
||||
Protocol Objectの`interfaces`は追加順を保持するordered setであり、同じInterface参照の重複は拒否する。各Interface Descriptorとbindingは、それぞれ独立したOperation集合およびbehaviorを提供する。複数のImplementation bindingを一つのDescriptorやdispatch tableへ暗黙にmergeすることはしない。
|
||||
|
||||
異なるInterfaceは同じOperation名を宣言できる。Dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まり、そのInterfaceへbindしたimplementationを使用するため、同じObjectに意味の異なる同名Operationを実装できる。
|
||||
異なるInterfaceが同じOperation名を宣言しても、dispatchはrequestの`InterfaceTarget.reference`とOperation名の組で一意に決まる。そのInterfaceへbindしたimplementationを使うため、同じObjectに意味の異なる同名Operationを実装できる。
|
||||
|
||||
```ts
|
||||
const object = wip.publish(file)
|
||||
@@ -519,17 +519,17 @@ const object = wip.publish(file)
|
||||
});
|
||||
```
|
||||
|
||||
表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従う。Signature全体をProtocol request fieldへparseし直さない。
|
||||
表示上のqualified表記は[Text Viewの参照表記](../4.2-text-view.md#参照表記)に従い、signature全体をProtocol request fieldへparseし直さない。
|
||||
|
||||
Intersection type、interface extension、mixin等をDescriptorのcompositionへ自動変換しない。Protocol上のInterface inheritanceを暗黙に導入しない。
|
||||
Intersection type、interface extension、mixin等をDescriptorのcompositionへ自動変換することはしない。これらによって、Protocol上のInterface inheritanceを暗黙に導入することもない。
|
||||
|
||||
## HostへのInterface登録
|
||||
|
||||
Runtime Interface definitionをHostへ登録し、構造化されたInterface参照を割り当てる必要がある。
|
||||
Runtime Interface definitionには、Hostへの登録を通じて構造化されたInterface参照を割り当てる必要がある。参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。
|
||||
|
||||
参照の絶対scopeとlocal name、および配置pathへの祖先制約は[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)に従う。以下のconceptual API例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めるものではない。登録時のcontextと引数の具体APIは引き続き未決定である。Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証し、`ref`がない場合のidentity追跡不能も許容する。Scopeの移動追跡や独立したscope validatorを導入しない。
|
||||
Self-scopeは許可され、scopeはそのpathのObjectに紐づく。Scope Objectのoptionalな`ref`はProtocolの`scope_ref`として観測・検証する。`ref`がなければidentityを追跡できないことも許容し、scopeの移動追跡や独立したscope validatorは導入しない。
|
||||
|
||||
Conceptualには、eager registrationとlazy registrationの両方が考えられる。
|
||||
登録方法としては、conceptualにはeager registrationとlazy registrationの両方が考えられる。次の例はscope / nameを渡す具体構文を省略しており、暗黙のroot scopeを定めてはいない。登録時のcontextと引数の具体APIも引き続き未決定である。
|
||||
|
||||
```ts
|
||||
const readInterface = host.registerInterface(ReadOnlyFileInterface);
|
||||
@@ -543,9 +543,7 @@ const object = wip.publish(file)
|
||||
});
|
||||
```
|
||||
|
||||
または、Hostが最初のpublication時に各definitionをinternしてよい。
|
||||
|
||||
どちらの場合も次を守る。
|
||||
また、Hostが最初のpublication時に各definitionをinternする方式でもよい。どちらの登録方法でも、次の条件を満たす必要がある。
|
||||
|
||||
- MutableなInterface参照では`fetch_interface`がvalidatorを返し、同じ参照とvalidatorの組から異なるDescriptorを返さない。
|
||||
- Validatorを返さないInterface参照は、その参照の有効期間中Descriptorをimmutableにする。
|
||||
@@ -556,11 +554,13 @@ const object = wip.publish(file)
|
||||
- Variable名、module path、JavaScript object address等を、そのままportableなProtocol semanticsとして扱わない。
|
||||
- 一つのfinalized artifactを後からmutationしてDescriptorを変化させない。Hostはdefinitionをfreezeするか、検証済みのimmutable snapshotを保持できなければならない。
|
||||
|
||||
Registrationまたは最初のpublicationで、Descriptor、type codec、validator、Operation dispatch tableを一つのfinalized artifactとして再帰的に検証および固定する。`fetch_interface`、arguments / result validation、Operation dispatchはすべて同じartifactを使用する。Descriptorだけをsnapshotし、dispatch時にはmutation可能な元definitionを読み直す実装にはしない。Finalization後のmutationは拒否するか、既存artifactへ影響しないものとして扱う。
|
||||
Registrationまたは最初のpublicationでは、Descriptor、type codec、validator、Operation dispatch tableを一つのfinalized artifactとして再帰的に検証し、固定する。`fetch_interface`、arguments / result validation、Operation dispatchは、すべて同じartifactを使う。
|
||||
|
||||
Descriptorだけをsnapshotし、dispatch時にmutation可能な元definitionを読み直す方式では、この固定を満たせない。Finalization後のmutationは拒否するか、既存artifactに影響しないものとして扱う。
|
||||
|
||||
## Request contextとauthorization
|
||||
|
||||
Operation implementationは、Object instance以外にrequest contextを必要とし得る。
|
||||
Operation implementationが必要とする情報は、Object instanceだけとは限らない。Request contextとして、次の情報も必要になり得る。
|
||||
|
||||
- 現在の主体。
|
||||
- `AbortSignal`等のcancellation。
|
||||
@@ -569,34 +569,34 @@ Operation implementationは、Object instance以外にrequest contextを必要
|
||||
- Host serviceやbackend connectionへのaccess。
|
||||
- Resource limit。
|
||||
|
||||
これらをmethod parameter、wrapper object、AsyncLocalStorage、closure等のどれで渡すかは未決定である。Protocol parameterとして宣言された値と、Hostが注入するcontextを明確に区別しなければならない。
|
||||
このcontextをmethod parameter、wrapper object、AsyncLocalStorage、closure等のどれで渡すかは未決定である。どの形でも、Protocol parameterとして宣言された値とHostが注入するcontextは明確に区別する必要がある。
|
||||
|
||||
Object publication時のInterface集合の選択と、Operation call時のmembership、Interface validator、authorizationの再評価を実装できる必要がある。以前の`observe`で公開されたInterface集合だけを根拠に、現在のOperation実行を許可してはならない。
|
||||
Interface集合はObject publication時に選択するだけでなく、Operation call時にもmembership、Interface validator、authorizationを再評価できなければならない。以前の`observe`で公開したInterface集合だけを根拠に、現在のOperation実行を許可することはできない。
|
||||
|
||||
Operation resultのRecord、List、Union等へnestedしたすべての`Entry`位置について、Hostは現在の主体にそのpathを認識させてよいことを再帰的に確認できなければならない。通常のstructural Value validationだけではこのvisibility checkを満たさない。Runtime definition、Projection、Host Runtimeのどこで確認するかは未決定である。
|
||||
Resultのvisibility checkも、通常のstructural Value validationとは別に必要となる。Hostは、Operation resultのRecord、List、Union等にnestedしたすべての`Entry`について、現在の主体にそのpathを認識させてよいかを再帰的に確認できなければならない。この確認をRuntime definition、Projection、Host Runtimeのどこで行うかは未決定である。
|
||||
|
||||
Operation argumentとして`Entry` pathを受け取った場合も、pathの所持をauthorizationの証明として扱わず、参照先へ作用する時点で現在の主体について認可する。
|
||||
Argumentとして受け取った`Entry` pathについても、pathの所持をauthorizationの証明にはしない。参照先へ作用する時点で、現在の主体について認可する。
|
||||
|
||||
## Error model
|
||||
|
||||
TypeScript methodのerror表現は、次の四種類を区別できなければならない。
|
||||
TypeScript methodのerror表現には、次の四種類を区別できることを求める。
|
||||
|
||||
- Protocol validationまたはdispatch failure。
|
||||
- Effectがcommitされていないと保証できるHost / backend implementation failure。
|
||||
- Operationの未実行またはrollbackを保証できない`OperationOutcomeUnknown`。
|
||||
- Interfaceがreturn typeとして宣言したdomain failure。
|
||||
|
||||
現在のProtocolでは、domain failureはOperation resultのUnion caseとして表す。Thrown value、rejected Promise、explicit result objectをdomain resultまたはHost errorへどう対応付けるかは、Interface authoring APIで明示しなければならない。
|
||||
現在のProtocolはdomain failureをOperation resultのUnion caseとして表す。Thrown value、rejected Promise、explicit result objectをdomain resultまたはHost errorへどう対応付けるかは、Interface authoring APIで明示する必要がある。
|
||||
|
||||
Arbitrary thrown value、Promise rejection、result encode failure、宣言型に違反するimplementation resultをdomain failureへ自動変換してはならない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できない場合は`OperationOutcomeUnknown`へmappingする。Abortやtransport切断を未実行の証明として扱わず、自動retryしない。
|
||||
Arbitrary thrown value、Promise rejection、result encode failure、宣言型に違反するimplementation resultを、domain failureへ自動変換することは認めない。Host Runtimeは、effectがcommitされていないと保証できる場合だけ`Internal`へmappingし、保証できなければ`OperationOutcomeUnknown`へmappingする。Abortやtransport切断は未実行の証明とはならず、自動retryはしない。
|
||||
|
||||
## Custom transpilerを必須にしない
|
||||
|
||||
通常のTypeScript `interface`または`type`をsource of truthにしてInterface Descriptorを生成するには、TypeScript Compiler API、custom transformer、code generator等が必要になる。
|
||||
通常のTypeScript `interface`または`type`をsource of truthとしてInterface Descriptorを生成するには、TypeScript Compiler API、custom transformer、code generator等が必要になる。
|
||||
|
||||
Core APIはこれを要求しない。Runtime definition objectをsource of truthにすることで、通常の`tsc`、bundler、JavaScript runtimeで動作できるようにする。
|
||||
Core APIでは、これらを必須にしない。Runtime definition objectをsource of truthとすることで、通常の`tsc`、bundler、JavaScript runtimeで動作できるようにする。
|
||||
|
||||
Build-time toolingはoptionalなauthoring layerとして追加してよい。
|
||||
Build-time toolingは、optionalなauthoring layerとして追加してよい。
|
||||
|
||||
```ts
|
||||
/** @wip-interface */
|
||||
@@ -605,9 +605,9 @@ interface FileOperations {
|
||||
}
|
||||
```
|
||||
|
||||
Toolingがこのdeclarationからruntime definition moduleを生成することはできるが、生成物はcore APIと同じruntime definition semanticsを満たさなければならない。
|
||||
Toolingによってこのdeclarationからruntime definition moduleを生成することはできる。ただし、その生成物もcore APIと同じruntime definition semanticsを満たす必要がある。
|
||||
|
||||
Build-time toolingには少なくとも次の課題がある。
|
||||
Build-time toolingには、少なくとも次の課題がある。
|
||||
|
||||
- TypeScript compiler versionとCompiler APIへの依存。
|
||||
- Bundler、incremental build、package boundaryとの統合。
|
||||
@@ -618,15 +618,15 @@ Build-time toolingには少なくとも次の課題がある。
|
||||
|
||||
## Decoratorをcoreにしない
|
||||
|
||||
Decoratorだけでは、通常はUnion case、Record field、optional、Entry、Integer、nested type、generic、documentation等を完全なruntime schemaとして取得できない。
|
||||
Decoratorだけでは通常、Union case、Record field、optional、Entry、Integer、nested type、generic、documentation等を、完全なruntime schemaとして取得できない。
|
||||
|
||||
`emitDecoratorMetadata`等が提供するconstructor-level metadataだけでは、WIP Interface DescriptorとValue validationを再構築するには不足する。Decoratorをoptional sugarとして提供する場合も、明示的なruntime definitionまたはbuild-time generationへ接続する。
|
||||
`emitDecoratorMetadata`等が提供するconstructor-level metadataも、WIP Interface DescriptorとValue validationを再構築するには不足する。Decoratorをoptional sugarとして提供する場合には、明示的なruntime definitionまたはbuild-time generationへ接続する。
|
||||
|
||||
Class inheritanceをInterface declarationの基本形にすると、複数Interface implementation、plain object、data-drivenなpublicationが不必要に制限されるため、runtime definition objectをcore modelとする。
|
||||
また、class inheritanceをInterface declarationの基本形にすると、複数Interface implementation、plain object、data-drivenなpublicationを不必要に制限することになる。このため、runtime definition objectをcore modelとする。
|
||||
|
||||
## 要件
|
||||
|
||||
TypeScript API modelは少なくとも次を満たす。
|
||||
このdraftのTypeScript API modelに求める要件は、少なくとも次のとおりである。
|
||||
|
||||
- Runtime definition objectをInterface Descriptorとruntime validationのsource of truthにする。
|
||||
- 同じdefinitionからTypeScript implementation typeを推論できる。
|
||||
@@ -656,7 +656,7 @@ TypeScript API modelは少なくとも次を満たす。
|
||||
|
||||
## 非目標
|
||||
|
||||
このdraftは次を決定しない。
|
||||
次の事項は、このdraftでは決定しない。
|
||||
|
||||
- 最終的なpackage、module、function、generic type、class、methodの名前。
|
||||
- 特定のschema libraryまたはvalidation libraryの採用。
|
||||
@@ -698,4 +698,4 @@ TypeScript API modelは少なくとも次を満たす。
|
||||
- TypeScript client APIを同じruntime definitionから生成するか。
|
||||
- Build-time code generationをoptional packageとして提供するか。
|
||||
|
||||
これらを決定する際は、静的service objectだけでなく、Filesystem、database row、virtual aggregate、主体別Interface compositionを同じAPIで実装できるか評価する。
|
||||
これらの選択は、静的service objectに使えるだけでは足りない。Filesystem、database row、virtual aggregate、主体別Interface compositionも、同じAPIで実装できるかを評価して決定する。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 未解決事項
|
||||
|
||||
主要な未解決事項を、canonicalなCore文書へのindexとしてまとめる。
|
||||
主要な未解決事項と、対応するcanonicalなCore文書への参照をまとめる。
|
||||
|
||||
## 2.2. Operation and Interface
|
||||
|
||||
@@ -19,16 +19,18 @@
|
||||
|
||||
### Interface scopeとcomposition
|
||||
|
||||
構造化参照と絶対scopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)、fieldとHost変換は[3. Protocol](../3-protocol.md#worldspace-composition)、短縮表記は[4.2. Text View](../4.2-text-view.md#参照表記)、JSON encodingは[5.1. WIP over HTTP](../5.1-wip-over-http.md#interface-reference)へ統合済み。
|
||||
Interface scopeとcompositionの基本仕様は、すでに各文書へ統合されている。構造化参照と絶対scopeは[2.2. Operation and Interface](../2.2-operation-and-interface.md#interfaceの識別とscope)、fieldとHost変換は[3. Protocol](../3-protocol.md#worldspace-composition)、短縮表記は[4.2. Text View](../4.2-text-view.md#参照表記)、JSON encodingは[5.1. WIP over HTTP](../5.1-wip-over-http.md#interface-reference)に従う。
|
||||
|
||||
Self-scopeとroot scope `/`の利用は許可する。ScopeはそのpathのObjectに紐づき、optionalな`ref`で紐付きを確認する。`ref`なしの差し替えをidentityで追跡できないことは仕様上許容する。Scopeが消えれば旧参照の有効期間は終了し、Clientは不要なcacheを破棄できる。移動先は別参照であり、Clientの移動追跡は要求しない。詳細は[Scope Objectと有効期間](../2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocolの紐付き確認](../3-protocol.md#scope-objectの紐付き)に従う。
|
||||
Self-scopeとroot scope `/` の利用は許可する。ScopeはそのpathのObjectに紐づき、optionalな`ref`で紐付きを確認する。`ref`がない場合、Objectの差し替えをidentityで追跡できないことは仕様上許容する。
|
||||
|
||||
残る論点:
|
||||
Scopeが消えると旧参照の有効期間は終了し、Clientは不要なcacheを破棄できる。移動先は別参照となるため、Clientに移動追跡は要求しない。詳細は[Scope Objectと有効期間](../2.2-operation-and-interface.md#scope-objectと有効期間)および[Protocolの紐付き確認](../3-protocol.md#scope-objectの紐付き)に従う。
|
||||
|
||||
これらの仕様を前提として、次の論点が残る。
|
||||
|
||||
- **複数配置とidentity**:同じUpstream Objectを複数scopeへ投影する場合の共通祖先scopeでの共有やprojectionごとの`ref`・validator。同じ`ref`とvalidatorで異なるrepresentationを返せるようにはしない。
|
||||
- **部分合成と拒否条件**:公開subtree外のscope・typed `entry`への対応付け、対応不能時の公開・実行拒否とerror mapping。非公開情報の秘匿と既存のerror precedenceを維持し、effectがcommit済みか不明なcallを未実行保証のerrorへ置き換えない。
|
||||
|
||||
Host内部のmount API、Provider登録API、合成設定の共通data structureは引き続きHost API draftで検討する。
|
||||
Host内部のmount API、Provider登録API、合成設定の共通data structureも引き続き検討対象であり、Host API draftで扱う。
|
||||
|
||||
### Type / Value
|
||||
|
||||
|
||||
Reference in New Issue
Block a user