Metadata
IRPの最後の特徴は、データベース・システムのカタログのように、メタデータAPIを使って自己記述的に表現することです。メタデータAPIは、例えば、クエリ可能なコレクションとして公開されます。
The final aspect of IRP is its self-descriptive nature using metadata APIs, similar to a catalog in a database system. Metadata APIs are exposed as queryable collections, for example:
code:C#
IAsyncQueryable<ObservableDefinition> Observables { get; }
IAsyncQueryable<ObserverDefinition> Observers { get; }
IAsyncQueryable<SubscriptionProcess> Subscriptions { get; }
...
ホットアーティファクトはProcessという接尾辞を持つエンティティを使用して表現され、コールドアーティファクトはDefinitionという接尾辞を使用して表現されます。これらのエンティティには、Id、Expression、CreationTimeなどのプロパティが含まれ、構造型として扱われます。これにより、IRPに準拠したサービスの具体的な実装では、好みのプロパティ(セキュリティ情報、所有者など)を追加することができます。
Hot artifacts are represented using entities with a Process suffix, while cold artifacts used a Definition suffix. These entities contain properies such as Id, Expression, CreationTime, etc. and are treated as structural types. This enables concrete implementation of IRP-compliant service to add more properties of their choice (e.g. security information, owners, etc.).
上記のコレクションタイプは、IRPが作成された時点では存在しなかったIQueryable<T>の非同期型を使用していることに注意してください。C#の将来のリリースでは、非同期の列挙型をサポートするための作業が進められており、上記のコードフラグメントは、APIの最終的な形を示しています。現在のAPIを閲覧していると、同期型インターフェースの痕跡が見つかることがあります。
Note that the collection types shown above use the asynchronous equivalent of IQueryable<T> which didn’t exist at the time of the creation of IRP. Work is underway to have asynchronous enumerable support in future releases of C# and the code fragment above shows the ultimate shape of the API. When browsing current APIs, traces of synchronous interfaces may be found.
IRPメタデータ・インターフェースの現在の実装では、問い合わせ可能な辞書型も使用しています。これは、インデックス構文を使って識別子による問い合わせを容易にするための言語投影の選択に過ぎません。メタデータの本質は、問い合わせ可能なコレクションにありますが、例えば、識別子によってインデックスを作成し、そのような組織を辞書として公開するなど、より多くの構造を成果物のセットの上に課すことができます。
The current implementation of the IRP metadata interfaces also uses queryable dictionary types. This is merely a choice of a language projection to make querying by an identifier easier using indexing syntax. The essence of metadata is in queryable collections but more structure can be imposed on top of the set of artifacts, e.g. to index by identifier and expose such organization as a dictionary.
これらのクエリ可能なコレクションは、メタデータのクエリを形成するために使用することができ、既知の識別子を使用して成果物を単純に選択することから、それらの定義または作成に使用された表現ツリーを検査することまで可能です。例えば
These queryable collections can be used to formulate metadata queries, ranging from simple selections of artifacts using known identifiers to inspection of the expression trees used for their definition or creation. For example:
code:C#
var filter = await ctx.Observables.SingleAsync(o => o.Id == new Uri("rx://operators/filter"));
Console.WriteLine(filter.Expression);
var allOperators = ctx.Observables.Where(o => o.Id.Schema == "rx");
foreach await (var op in allOperators)
{
Console.WriteLine(op);
}
var allSubscriptionsOnWeather = from s in ctx.Subscriptions
let vs = s.Expression.FindFreeVariables()
where vs.Any(v => v.Name == "bing://streams/weather")
select s.Id;
foreach await (var subId in allSubscriptionsOnWeather)
{
Console.WriteLine(subId);
}
上に示した最後の例では、FindFreeVariablesは、この機能のサービス側の実装を参照するためにKnownResource属性でアノテーションされたExpressionSlimの拡張メソッドとして定義されています。式から参照されるすべてのアーティファクトが結合されていないパラメータとして表現されていることから、FindFreeVariablesを使用して依存性分析を行うことができます。このクエリは完全にサービスサイドで実行されることに注意することが重要です。
In the last example shown above, FindFreeVariables is defined as an extension method on ExpressionSlim annotated with a KnownResource attribute to refer to a service-side implementation of this functionality. Given that all artifacts referenced from an expression are represented as unbound parameters, FindFreeVariables can be used to perform dependency analysis. It’s important to note that this query is entirely executed service-side.
IRPの構想時には、すべてのアーティファクトがグラフデータベースに格納され、エッジとしての依存関係のトラバーサルがかなり簡単になることが想定されていました。これは、IRPとグラフデータベースの取り組みとの共通のルーツであり、さらには、この文書の初期段階で言及された他のCloud Programmability Teamのプロジェクトにも通じるものです。
At the time of conception of IRP, it was envisioned that all artifacts would be stored in a graph database, making the traversal of dependencies as edges rather straightforward. This goes back to the common roots between IRP and the graph database effort, and even further to other Cloud Programmability Team projects mentioned early on in this document.
IRPメタデータをうまくサポートするためには、サービスが使用する基礎的なメタデータストアの選択が重要です。IRPへの取り組みが始まった頃、いくつかのメタデータストアはAzure TableやAzure Blob(大きなBonsaiを保存するため)で実装されていましたが、これらは非常に限られたクエリ機能しか提供していませんでした。今日の世界では、豊富なクエリ機能をサポートするための自然な選択は、サービスサイドのストアドプロシージャと、Bonsai表現を操作するよく知られたユーザー定義関数(FindFreeVariablesなど)のセットを備えたAzure CosmosDBの使用ですが、おそらく新しいドキュメントの挿入時に適用されるさまざまなインデックススキームを備えています。
In order to support IRP metadata well, the choice of the underlying metadata store used by a service is critical. When work on IRP started, some metadata stores were implemented in Azure Table or Azure Blob (to store larger Bonsai trees), which provide very limited query capability. In today’s world, a natural choice to support rich query capabilities is the use of Azure CosmosDB with service-side stored procedures and a set of well-known user defined functions (such as FindFreeVariables) that operate on the Bonsai representation, possibly with various indexing schemes that are applied upon insertion of new documents.
メタデータの最もわかりやすい使用例は
The most straightforward use cases of metadata are:
非アトミックな "check-before-create "操作を行う。
Perform (non-atomic) “check-before-create” operations.
テナント、ユーザー、シナリオなどの追加のメタデータに基づいてアーティファクトを照会する。
Query artifacts based on additional metadata, e.g. a tenant, a user, a scenario, etc.
オフラインでの分析のための成果物のエクスポート
Export of artifacts for offline analysis.
しかし、これらに加えて、IRPが公開するファーストクラスのメタデータAPIの主な動機は2つあります。
However, in addition to these, the main motivations for a first-class metadata API exposed by IRP are twofold:
リッチなデベロッパーツールの作成を可能にする。
Enabling the creation of rich developer tooling.
IRPに準拠したシステム間の相互運用性をサポートします。
Support for interoperability between IRP-compliant systems.
後者については、このドキュメントの後半で個別に取り上げます。デベロッパーツールに関しては、メタデータはSQL ServerなどのRDBMSにおけるカタログに相当するもので、O/Rマッパーなどのツールを作成することができると考えるのがベストでしょう。
We’ll focus on the latter separately further on in this document. With regards to developer tooling, the best way to think of metadata is the equivalent to a catalog in an RDBMS such as SQL Server, enabling the creation of tools such as O/R mappers.
特にIRPでは、「Reactive Extensions Meta Language」のrxmetalというツールをサポートしており、これは実質的にO/E(オブジェクト/イベント)マッパーです。これは、LINQ to SQLのsqlmetalがO/R(オブジェクト/リレーショナル)マッパーであるのと同じです。
In particular, IRP supports a tool called rxmetal for “Reactive Extensions Meta Language” which is effectively an O/E (object/event) mapper. It’s the equivalent to sqlmetal in LINQ to SQL which is an O/R (object/relational) mapper.
このようなツールは、Visual Studioの「Server Explorer」のような体験を提供し、IRPインスタンスに接続してさまざまなアーティファクト・タイプを参照することができます。典型的な例としては、利用可能なストリーム(テーブル)やオブザーバブル(ビュー、ストアドプロシージャ)などの発見が挙げられます。デザイナー・サーフェスへのドラッグ・アンド・ドロップにより、オブジェクト・モデルのコード生成が可能になります。
Such tools can power experiences a la “Server Explorer” in Visual Studio, enabling one to connect to an IRP instance and browse the different artifact types. A typical example of this is discovery of streams (~ tables), the discovery of observables (~ views, stored procedures), etc. that are available. A drag-and-drop experience to a designer surface can then trigger code-generation of an object model.
rxmetalツールは、RXML(sqlmetalのDBMLに相当)と呼ばれるXMLベースのフォーマットで成果物の説明を出力し、そこからC#やVBのコードを生成することができます。生成されたコードは、インポートされたアーティファクトへの簡単なアクセサを提供するderivesクライアント・コンテキストを定義します。
The rxmetal tool emits a description of the artifacts in an XML-based format called RXML (analogous to DBML in sqlmetal) from which C# or VB code can be generated. The generated code defines a derives client context that provides easy accessors to the imported artifacts, e.g.:
code:C#
class MyClientContext : ClientContext
{
public IAsyncReactiveQubject<WeatherInfo> Weather { get; } = ...
}
class WeatherInfo
{
public string City { get; set; }
public double Temperature { get; set; }
}
これにより、ユーザーはGetObservable<T>などの呼び出しを使わずに、簡単なクエリを書くことができます。
This enables users to write straightforward queries without having to use calls to GetObservable<T> etc.
code:C#
var ctx = new MyClientContext(...);
var res = from weather in ctx.Weather
group weather by weather.City into g
from hourly in weather.Window(TimeSpan.FromHours(1))
from avg in hourly.Average()
select new { City = weather.City, AvgTemperature = avg };
await res.SubscribeAsync(...);
IRPには、組み込みの問い合わせ演算子がないことに注意してください。このため、rxmetal のようなツールでは、他の(ユーザー定義の)アーティファクトと同様に、クエリ演算子の定義を拡張メソッドとしてエクスポートすることができます。これにより、サポートされているすべてのサービスサイドのクエリ演算子がAPIとして存在するクライアントライブラリを出荷する必要がなくなります。なぜなら、ユーザーは利用可能なアーティファクトのカタログを参照しながらこれらのメソッドを生成できるからです。
Note that IRP does not have any built-in query operators. Because of this, tools like rxmetal can export the definition of query operators as extension methods just like any other (user-defined) artifact. This eliminates the need to ship a client library where all supported service-side query operators have an API presence, because users can generate these methods as they browse the catalog of available artifacts.
例えば、WhereとSelectの演算子は、WhenTemperatureIsHighのようなユーザー定義の演算子と一緒に表示されます。言うまでもなく、追加のメタデータ(分類のための#タグと所有者やテナント情報のための@タグを持つタグクラウドなど)を使用して、演算子をより構造的かつ階層的に表示することができます。また、IRPシステムでは、名前空間の概念を導入して、成果物に使用される識別子に構造を課すこともできます(例:rx://は汎用のクエリ演算子用に予約されています)。データベースシステムのカタログで活用されている構造(SQL Serverのスキーマやオーナーなど)と同様の構造を、ポリシーと同様にIRPでも適用することができます。IRPにおけるメタデータは、単に発見のためのメカニズムを提供するものです。
For example, the Where and Select operators would show up right alongside user-defined operators such as WhenTemperatureIsHigh. It goes without saying that extra metadata (such as tag clouds, with # tags for classification and @ tags for owner or tenant info) could be used to present operators in a more structured and hierarchical way. Alternatively, an IRP system may impose a structure on the identifiers used for artifacts, introducing the concept of namespaces (e.g. rx:// is reserved for general purpose query operators). Strucutures similar to those leveraged by catalogs in database systems (e.g. schemas and owners in SQL Server) can be applied in IRP as well as a policy. Metadata in IRP merely provides a mechanism for discovery.