エンティティ関数Entity functions

エンティティ関数では、"持続エンティティ" と呼ばれる小さい状態の読み取りと更新のための操作が定義されています。Entity functions define operations for reading and updating small pieces of state, known as durable entities. オーケストレーター関数と同様、エンティティ関数は特殊なトリガー型であるエンティティ トリガーを含む関数です。Like orchestrator functions, entity functions are functions with a special trigger type, the entity trigger. オーケストレーター関数とは異なり、エンティティ関数では、制御フローを介して状態を暗黙的に表すのではなく、エンティティの状態を明示的に管理します。Unlike orchestrator functions, entity functions manage the state of an entity explicitly, rather than implicitly representing state via control flow. エンティティは、それぞれが適度なサイズの状態を備えた多数のエンティティ全体に作業を分散することにより、アプリケーションをスケールアウトする手段を提供します。Entities provide a means for scaling out applications by distributing the work across many entities, each with a modestly sized state.

注意

エンティティ関数と関連する機能は Durable Functions 2.0 以降でのみ使用できます。Entity functions and related functionality is only available in Durable Functions 2.0 and above.

一般的な概念General concepts

エンティティは、メッセージを介して通信する小さなサービスと同じように動作します。Entities behave a bit like tiny services that communicate via messages. 各エンティティは、一意の ID と内部状態 (存在する場合) を備えています。Each entity has a unique identity and an internal state (if it exists). サービスやオブジェクトと同様に、エンティティは、要求されたときに操作を実行します。Like services or objects, entities perform operations when prompted to do so. 操作を実行すると、エンティティの内部状態が更新されることがあります。When an operation executes, it might update the internal state of the entity. また、外部サービスを呼び出して応答を待つこともあります。It might also call external services and wait for a response. エンティティは、リライアブル キューを介して暗黙的に送信されるメッセージを使用して、他のエンティティ、オーケストレーション、およびクライアントと通信します。Entities communicate with other entities, orchestrations, and clients by using messages that are implicitly sent via reliable queues.

競合を防ぐために、1 つのエンティティに対するすべての操作は、直列に (つまり順番に) 実行されることが保証されます。To prevent conflicts, all operations on a single entity are guaranteed to execute serially, that is, one after another.

エンティティ IDEntity ID

エンティティには、一意の識別子である "エンティティ ID" を介してアクセスします。Entities are accessed via a unique identifier, the entity ID. エンティティ ID は単に、エンティティのインスタンスを一意に示す文字列のペアです。An entity ID is simply a pair of strings that uniquely identifies an entity instance. 構成は次のとおりです。It consists of an:

  • エンティティ名: エンティティの種類を示す名前です。Entity name, which is a name that identifies the type of the entity. たとえば、"Counter" などです。An example is "Counter." この名前は、エンティティを実装するエンティティ関数の名前と一致している必要があります。This name must match the name of the entity function that implements the entity. 大文字と小文字は区別されません。It isn't sensitive to case.
  • エンティティ キー: 同じ名前の他のすべてのエンティティの間でそのエンティティを一意に示す文字列です。Entity key, which is a string that uniquely identifies the entity among all other entities of the same name. たとえば、GUID などです。An example is a GUID.

たとえば、Counter エンティティ関数は、オンライン ゲームでスコアを保持するために使用される可能性があります。For example, a Counter entity function might be used for keeping score in an online game. ゲームの各インスタンスは、@Counter@Game1@Counter@Game2 などの一意のエンティティ ID を持ちます。Each instance of the game has a unique entity ID, such as @Counter@Game1 and @Counter@Game2. 特定のエンティティを対象とするすべての操作では、エンティティ ID をパラメーターとして指定する必要があります。All operations that target a particular entity require specifying an entity ID as a parameter.

エンティティの操作Entity operations

エンティティで操作を呼び出すには、次を指定します。To invoke an operation on an entity, specify the:

  • ターゲット エンティティのエンティティ IDEntity ID of the target entity.
  • 操作名: 実行する操作を指定する文字列です。Operation name, which is a string that specifies the operation to perform. たとえば、Counter エンティティでは、addget、または reset 操作をサポートする場合があります。For example, the Counter entity could support add, get, or reset operations.
  • 操作の入力: 操作のオプションの入力パラメーターです。Operation input, which is an optional input parameter for the operation. たとえば、add 操作では入力として整数値を受け取ることができます。For example, the add operation can take an integer amount as the input.
  • "*スケジュール時刻": 操作の配信時刻を指定するためのオプション パラメーターです。*Scheduled time, which is an optional parameter for specifying the delivery time of the operation. たとえば、将来、数日間にわたって操作を実行するよう確実にスケジュールすることができます。For example, an operation can be reliably scheduled to run several days in the future.

操作では、結果値またはエラー結果 (JavaScript エラーや .NET 例外など) を返すことができます。Operations can return a result value or an error result, such as a JavaScript error or a .NET exception. この結果またはエラーは、操作を呼び出したオーケストレーションによって確認できます。This result or error can be observed by orchestrations that called the operation.

エンティティ操作では、エンティティの状態の作成、読み取り、更新、および削除を行うこともできます。An entity operation can also create, read, update, and delete the state of the entity. エンティティの状態は、常にストレージ内に持続的に保持されます。The state of the entity is always durably persisted in storage.

エンティティの定義Define entities

現在、エンティティを定義するための 2 つの異なる API は次のとおりです。Currently, the two distinct APIs for defining entities are:

関数ベースの構文: エンティティは関数として表され、操作はアプリケーションによって明示的にディスパッチされます。Function-based syntax, where entities are represented as functions and operations are explicitly dispatched by the application. この構文は、単純な状態のエンティティ、操作が少ないエンティティ、または動的な操作のセット (アプリケーション フレームワーク内のような) を備えたエンティティに適しています。This syntax works well for entities with simple state, few operations, or a dynamic set of operations like in application frameworks. この構文は、コンパイル時に型エラーがキャッチされないため、保守が煩雑になる可能性があります。This syntax can be tedious to maintain because it doesn't catch type errors at compile time.

クラスベースの構文 (.NET のみ) : エンティティおよび操作はクラスおよびメソッドによって表されます。Class-based syntax (.NET only), where entities and operations are represented by classes and methods. この構文では、より読みやすいコードが生成され、タイプ セーフな方法で操作を呼び出すことができます。This syntax produces more easily readable code and allows operations to be invoked in a type-safe way. クラスベースの構文は、関数ベースの構文の上にあるシン レイヤーであるため、同じアプリケーションで両方のバリアントを同じ意味で使用できます。The class-based syntax is a thin layer on top of the function-based syntax, so both variants can be used interchangeably in the same application.

例:関数ベースの構文 - C#Example: Function-based syntax - C#

次のコードは、持続的関数として実装されているシンプルな Counter エンティティの例です。The following code is an example of a simple Counter entity implemented as a durable function. この関数では 3 つの操作 addresetget が定義されていて、いずれも整数の状態に対して動作します。This function defines three operations, add, reset, and get, each of which operates on an integer state.

[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
    switch (ctx.OperationName.ToLowerInvariant())
    {
        case "add":
            ctx.SetState(ctx.GetState<int>() + ctx.GetInput<int>());
            break;
        case "reset":
            ctx.SetState(0);
            break;
        case "get":
            ctx.Return(ctx.GetState<int>());
            break;
    }
}

関数ベースの構文と使用方法の詳細については、「関数ベースの構文」を参照してください。For more information on the function-based syntax and how to use it, see Function-based syntax.

例:クラス ベースの構文 - C#Example: Class-based syntax - C#

次の例は、クラスとメソッドを使用した Counter エンティティの同等の実装です。The following example is an equivalent implementation of the Counter entity using classes and methods.

[JsonObject(MemberSerialization.OptIn)]
public class Counter
{
    [JsonProperty("value")]
    public int CurrentValue { get; set; }

    public void Add(int amount) => this.CurrentValue += amount;

    public void Reset() => this.CurrentValue = 0;

    public int Get() => this.CurrentValue;

    [FunctionName(nameof(Counter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
        => ctx.DispatchAsync<Counter>();
}

このエンティティの状態は Counter 型のオブジェクトになっています。これには、カウンターの現在の値を格納するフィールドが含まれます。The state of this entity is an object of type Counter, which contains a field that stores the current value of the counter. このオブジェクトは、ストレージに保持するために、Json.NET ライブラリによってシリアル化および逆シリアル化されます。To persist this object in storage, it's serialized and deserialized by the Json.NET library.

クラスベースの構文とその使用方法の詳細については、「エンティティ クラスの定義」を参照してください。For more information on the class-based syntax and how to use it, see Defining entity classes.

エンティティへのアクセスAccess entities

エンティティには、一方向または双方向の通信を使用してアクセスできます。Entities can be accessed using one-way or two-way communication. 次の用語は、2 つの通信の形式を区別します。The following terminology distinguishes the two forms of communication:

  • エンティティの呼び出しでは、双方向 (ラウンドトリップ) 通信が使われます。Calling an entity uses two-way (round-trip) communication. 操作メッセージをエンティティに送信し、応答メッセージを待機してから続行します。You send an operation message to the entity, and then wait for the response message before you continue. 応答メッセージでは、結果値またはエラー結果 (JavaScript エラーや .NET 例外など) を提供できます。The response message can provide a result value or an error result, such as a JavaScript error or a .NET exception. この結果またはエラーは、呼び出し元によって確認されます。This result or error is then observed by the caller.
  • エンティティのシグナル通知では、一方向 (ファイア アンド フォーゲット) 通信が使われます。Signaling an entity uses one-way (fire and forget) communication. 操作メッセージを送信しますが、応答を待ちません。You send an operation message but don't wait for a response. 最終的にメッセージが配信されることは保証されますが、送信側は、それがいつかを認識せず、結果値やエラーを確認することもできません。While the message is guaranteed to be delivered eventually, the sender doesn't know when and can't observe any result value or errors.

エンティティには、クライアント関数内、オーケストレーター関数内、またはエンティティ関数内からアクセスできます。Entities can be accessed from within client functions, from within orchestrator functions, or from within entity functions. すべての形式の通信がすべてのコンテキストでサポートされるわけではありません。Not all forms of communication are supported by all contexts:

  • クライアント内からは、エンティティにシグナル通知を出すことができ、エンティティの状態を読み取ることができます。From within clients, you can signal entities and you can read the entity state.
  • オーケストレーション内からは、エンティティにシグナル通知を出すことができ、エンティティを呼び出すことができます。From within orchestrations, you can signal entities and you can call entities.
  • エンティティ内からは、エンティティにシグナル通知を出すことができます。From within entities, you can signal entities.

次の例では、エンティティにアクセスするこれらのさまざまな方法を示しています。The following examples illustrate these various ways of accessing entities.

例:クライアントがエンティティにシグナル通知を出すExample: Client signals an entity

通常の Azure 関数 (クライアント関数とも呼ばれます) からエンティティにアクセスするには、エンティティ クライアントのバインドを使用します。To access entities from an ordinary Azure Function, which is also known as a client function, use the entity client binding. 次の例では、このバインドを使用してエンティティにシグナル通知する、キューによってトリガーされた関数を示します。The following example shows a queue-triggered function signaling an entity using this binding.

注意

わかりやすくするために、次の例では、エンティティにアクセスするための緩やかに型指定された構文を示しています。For simplicity, the following examples show the loosely typed syntax for accessing entities. 一般に、より多くの型チェックが提供されるので、インターフェイスを介してエンティティにアクセスすることをお勧めします。In general, we recommend that you access entities through interfaces because it provides more type checking.

[FunctionName("AddFromQueue")]
public static Task Run(
    [QueueTrigger("durable-function-trigger")] string input,
    [DurableClient] IDurableEntityClient client)
{
    // Entity operation input comes from the queue message content.
    var entityId = new EntityId(nameof(Counter), "myCounter");
    int amount = int.Parse(input);
    return client.SignalEntityAsync(entityId, "Add", amount);
}

"シグナル通知" とは、エンティティの API 呼び出しが一方向で非同期であることを意味します。The term signal means that the entity API invocation is one-way and asynchronous. クライアント関数は、エンティティが操作をいつ処理したかを認識できません。It's not possible for a client function to know when the entity has processed the operation. また、クライアント関数は、結果の値または例外を確認することはできません。Also, the client function can't observe any result values or exceptions.

例:クライアントがエンティティの状態を読み取るExample: Client reads an entity state

次の例に示すように、クライアント関数では、エンティティの状態についてクエリを実行することもできます。Client functions can also query the state of an entity, as shown in the following example:

[FunctionName("QueryCounter")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req,
    [DurableClient] IDurableEntityClient client)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");
    EntityStateResponse<JObject> stateResponse = await client.ReadEntityStateAsync<JObject>(entityId);
    return req.CreateResponse(HttpStatusCode.OK, stateResponse.EntityState);
}

エンティティ状態のクエリは永続性追跡ストアに送信され、エンティティの最後に保存された状態が返されます。Entity state queries are sent to the Durable tracking store and return the entity's most recently persisted state. この状態は、常に "コミット済み" 状態です。つまり、操作の実行中に想定される一時的な中間状態ではありません。This state is always a "committed" state, that is, it's never a temporary intermediate state assumed in the middle of executing an operation. ただし、この状態は、エンティティのメモリ内の状態より古い可能性があります。However, it's possible that this state is stale compared to the entity's in-memory state. 次のセクションで説明するように、エンティティのメモリ内の状態を読み取ることができるのはオーケストレーションだけです。Only orchestrations can read an entity's in-memory state, as described in the following section.

例:オーケストレーションがエンティティにシグナル通知を出し、エンティティを呼び出すExample: Orchestration signals and calls an entity

オーケストレーター関数では、オーケストレーション トリガー バインドに対する API を使用して、エンティティにアクセスできます。Orchestrator functions can access entities by using APIs on the orchestration trigger binding. 次のコード例では、オーケストレーター関数による Counter エンティティの呼び出しとシグナル通知を示します。The following example code shows an orchestrator function calling and signaling a Counter entity.

[FunctionName("CounterOrchestration")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var entityId = new EntityId(nameof(Counter), "myCounter");

    // Two-way call to the entity which returns a value - awaits the response
    int currentValue = await context.CallEntityAsync<int>(entityId, "Get");
    if (currentValue < 10)
    {
        // One-way signal to the entity which updates the value - does not await a response
        context.SignalEntity(entityId, "Add", 1);
    }
}

エンティティを呼び出して応答 (戻り値または例外) を取得できるのは、オーケストレーションだけです。Only orchestrations are capable of calling entities and getting a response, which could be either a return value or an exception. クライアント バインドを使用するクライアント関数は、エンティティに対するシグナル通知だけが可能です。Client functions that use the client binding can only signal entities.

注意

オーケストレーター関数からのエンティティの呼び出しは、オーケストレーター関数からのアクティビティ関数の呼び出しと似ています。Calling an entity from an orchestrator function is similar to calling an activity function from an orchestrator function. 主な違いは、エンティティ関数は、アドレス (エンティティ ID) を持つ持続オブジェクトであることです。The main difference is that entity functions are durable objects with an address, which is the entity ID. エンティティ関数は、操作名の指定がサポートされています。Entity functions support specifying an operation name. それに対し、アクティビティ関数はステートレスであり、操作の概念はありません。Activity functions, on the other hand, are stateless and don't have the concept of operations.

例:エンティティがエンティティにシグナル通知を出すExample: Entity signals an entity

エンティティ関数は、操作の実行中に他のエンティティ (またはそれ自体) にシグナルを送信することができます。An entity function can send signals to other entities, or even itself, while it executes an operation. たとえば、前の Counter エンティティの例を変更して、カウンターが値 100 に達したときに "マイルストーン到達" シグナルを一部の監視エンティティに送信することができます。For example, we can modify the previous Counter entity example so that it sends a "milestone-reached" signal to some monitor entity when the counter reaches the value 100.

   case "add":
        var currentValue = ctx.GetState<int>();
        var amount = ctx.GetInput<int>();
        if (currentValue < 100 && currentValue + amount >= 100)
        {
            ctx.SignalEntity(new EntityId("MonitorEntity", ""), "milestone-reached", ctx.EntityKey);
        }

        ctx.SetState(currentValue + amount);
        break;

エンティティの調整 (現在 .NET のみ)Entity coordination (currently .NET only)

複数のエンティティ間で操作を調整することが必要になる場合があります。There might be times when you need to coordinate operations across multiple entities. たとえば、銀行のアプリケーションでは、個々の銀行口座を表すエンティティがある場合があります。For example, in a banking application, you might have entities that represent individual bank accounts. 口座間で送金を行う場合は、送金元口座に十分な資金があることを確認する必要があります。When you transfer funds from one account to another, you must ensure that the source account has sufficient funds. さらに、送金元口座と送金先口座の両方に対する更新がトランザクション的に一貫した方法で実行されることを確認する必要もあります。You also must ensure that updates to both the source and destination accounts are done in a transactionally consistent way.

例:送金 (C#)Example: Transfer funds (C#)

次のコード例では、オーケストレーター関数を使用して、2 つの口座エンティティ間で送金を行います。The following example code transfers funds between two account entities by using an orchestrator function. エンティティの更新を調整するには、LockAsync メソッドを使用して、オーケストレーション内に_クリティカル セクション_を作成する必要があります。Coordinating entity updates requires using the LockAsync method to create a critical section in the orchestration.

注意

わかりやすくするため、この例では、前に定義した Counter エンティティを再利用します。For simplicity, this example reuses the Counter entity defined previously. 実際のアプリケーションでは、より詳細な BankAccount エンティティを定義することをお勧めします。In a real application, it would be better to define a more detailed BankAccount entity.

// This is a method called by an orchestrator function
public static async Task<bool> TransferFundsAsync(
    string sourceId,
    string destinationId,
    int transferAmount,
    IDurableOrchestrationContext context)
{
    var sourceEntity = new EntityId(nameof(Counter), sourceId);
    var destinationEntity = new EntityId(nameof(Counter), destinationId);

    // Create a critical section to avoid race conditions.
    // No operations can be performed on either the source or
    // destination accounts until the locks are released.
    using (await context.LockAsync(sourceEntity, destinationEntity))
    {
        ICounter sourceProxy = 
            context.CreateEntityProxy<ICounter>(sourceEntity);
        ICounter destinationProxy =
            context.CreateEntityProxy<ICounter>(destinationEntity);

        int sourceBalance = await sourceProxy.Get();

        if (sourceBalance >= transferAmount)
        {
            await sourceProxy.Add(-transferAmount);
            await destinationProxy.Add(transferAmount);

            // the transfer succeeded
            return true;
        }
        else
        {
            // the transfer failed due to insufficient funds
            return false;
        }
    }
}

.NET の LockAsync では、破棄されるとクリティカル セクションが終了される IDisposable が返されます。In .NET, LockAsync returns IDisposable, which ends the critical section when disposed. この IDisposable の結果を using ブロックと共に使用して、クリティカル セクションの構文表現を取得できます。This IDisposable result can be used together with a using block to get a syntactic representation of the critical section.

前の例では、オーケストレーター関数を使用して、送金元エンティティから送金先エンティティに送金を行いました。In the preceding example, an orchestrator function transferred funds from a source entity to a destination entity. LockAsync メソッドにより、送金元と送金先の両方の口座エンティティがロックされました。The LockAsync method locked both the source and destination account entities. このロックにより、オーケストレーションのロジックが using ステートメントの最後でクリティカル セクションを終了するまで、他のクライアントによってどちらの口座の状態も照会または変更されないことが保証されました。This locking ensured that no other client could query or modify the state of either account until the orchestration logic exited the critical section at the end of the using statement. この動作により、送金元口座からの過剰な送金の可能性を防ぐことができます。This behavior prevents the possibility of overdrafting from the source account.

注意

オーケストレーションが (正常に、またはエラーで) 終了すると、進行中のすべてのクリティカル セクションが暗黙的に終了し、すべてのロックが解除されます。When an orchestration terminates, either normally or with an error, any critical sections in progress are implicitly ended and all locks are released.

クリティカル セクションの動作Critical section behavior

LockAsync メソッドによって、オーケストレーション内にクリティカル セクションが作成されます。The LockAsync method creates a critical section in an orchestration. これらのクリティカル セクションにより、指定されているエンティティのセットに対して他のオーケストレーションにより重複する変更が行われることを防止できます。These critical sections prevent other orchestrations from making overlapping changes to a specified set of entities. 内部的には、LockAsync API ではエンティティに "ロック" 操作が送信され、同じこれらの各エンティティから "ロック取得済み" 応答メッセージを受信するとその API は制御を返します。Internally, the LockAsync API sends "lock" operations to the entities and returns when it receives a "lock acquired" response message from each of these same entities. ロックとロック解除はどちらも、すべてのエンティティでサポートされている組み込み操作です。Both lock and unlock are built-in operations supported by all entities.

ロック状態にあるエンティティに対して、他のクライアントからの操作は許可されません。No operations from other clients are allowed on an entity while it's in a locked state. この動作により、一度に 1 つのオーケストレーション インスタンスだけがエンティティをロックできるようになります。This behavior ensures that only one orchestration instance can lock an entity at a time. オーケストレーションによってロックされているエンティティに対して呼び出し元が操作を呼び出そうとすると、その操作は保留中操作キューに配置されます。If a caller tries to invoke an operation on an entity while it's locked by an orchestration, that operation is placed in a pending operation queue. 保持しているオーケストレーションがロックを解放するまで、保留中の操作は処理されません。No pending operations are processed until after the holding orchestration releases its lock.

注意

この動作は、C# の lock ステートメントなど、ほとんどのプログラミング言語で使用される同期プリミティブとは若干異なります。This behavior is slightly different from synchronization primitives used in most programming languages, such as the lock statement in C#. たとえば、C# では、複数のスレッド間で同期が確実に行われるようにするには、すべてのスレッドで lock ステートメントを使用する必要があります。For example, in C#, the lock statement must be used by all threads to ensure proper synchronization across multiple threads. 一方、エンティティでは、すべての呼び出し元が明示的にエンティティをロックする必要はありません。Entities, however, don't require all callers to explicitly lock an entity. いずれかの呼び出し元によってエンティティがロックされた場合、そのエンティティに対する他のすべての操作はブロックされ、キューでそのロックの後に配置されます。If any caller locks an entity, all other operations on that entity are blocked and queued behind that lock.

エンティティのロックは持続的であるため、実行プロセスがリサイクルされた場合でも永続化されます。Locks on entities are durable, so they persist even if the executing process is recycled. ロックは、エンティティの持続状態の一部として内部的に保持されます。Locks are internally persisted as part of an entity's durable state.

トランザクションとは異なり、クリティカル セクションでは、エラーが発生した場合に変更が自動的にロールバックされません。Unlike transactions, critical sections don't automatically roll back changes in the case of errors. 代わりに、たとえばエラーまたは例外をキャッチすることにより、エラー処理 (ロールバックや再試行など) を明示的にコーディングする必要があります。Instead, any error handling, such as roll-back or retry, must be explicitly coded, for example by catching errors or exceptions. この設計の選択は意図的なものです。This design choice is intentional. 一般に、オーケストレーションのすべての効果を自動的にロールバックすることは困難であるか不可能です。これは、オーケストレーションによってアクティビティが実行され、ロールバックできない外部サービスへの呼び出しが行われることがあるためです。Automatically rolling back all the effects of an orchestration is difficult or impossible in general, because orchestrations might run activities and make calls to external services that can't be rolled back. また、ロールバックの試み自体が失敗し、さらにエラー処理が必要になる場合があります。Also, attempts to roll back might themselves fail and require further error handling.

クリティカル セクションのルールCritical section rules

ほとんどのプログラミング言語の低レベルのロック プリミティブとは異なり、クリティカル セクションは、デッドロックが発生しないことが保証されますUnlike low-level locking primitives in most programming languages, critical sections are guaranteed not to deadlock. デッドロックを防ぐために、次の制限が適用されます。To prevent deadlocks, we enforce the following restrictions:

  • クリティカル セクションを入れ子にすることはできません。Critical sections can't be nested.
  • クリティカル セクションでサブオーケストレーションを作成することはできません。Critical sections can't create suborchestrations.
  • クリティカル セクションでは、自分がロックしているエンティティのみを呼び出すことができます。Critical sections can call only entities they have locked.
  • クリティカル セクションでは、複数の並列呼び出しを使用して、同じエンティティを呼び出すことはできません。Critical sections can't call the same entity using multiple parallel calls.
  • クリティカル セクションでは、自分がロックしていないエンティティのみにシグナルを送信できます。Critical sections can signal only entities they haven't locked.

これらのルールに違反すると、どのルールに違反していたかを説明するメッセージが含まれる実行時エラー (.NET の LockingRulesViolationException など) が発生します。Any violations of these rules cause a runtime error, such as LockingRulesViolationException in .NET, which includes a message that explains what rule was broken.

仮想アクターとの比較Comparison with virtual actors

持続エンティティの多くの機能は、アクター モデルに基づいています。Many of the durable entities features are inspired by the actor model. アクターについて既によくわかっている場合は、この記事で説明されている多くの概念を理解できます。If you're already familiar with actors, you might recognize many of the concepts described in this article. 持続エンティティは、Orleans プロジェクトによって普及した仮想アクターまたはグレインに特に似ています。Durable entities are particularly similar to virtual actors, or grains, as popularized by the Orleans project. 次に例を示します。For example:

  • 持続エンティティは、エンティティ ID を使用してアドレス指定可能です。Durable entities are addressable via an entity ID.
  • 持続エンティティの操作は、競合状態を避けるため、一度に 1 つずつ順番に実行されます。Durable entity operations execute serially, one at a time, to prevent race conditions.
  • 持続エンティティは、呼び出されるか、シグナル通知を受け取ると、暗黙的に作成されます。Durable entities are created implicitly when they're called or signaled.
  • 実行する操作がなくなると、持続エンティティはメモリからサイレントにアンロードされます。When not executing operations, durable entities are silently unloaded from memory.

いくつか注目すべき重要な違いがあります。There are some important differences that are worth noting:

  • 持続エンティティは、待ち時間より持続性の方が優先されるので、待ち時間の要件が厳しいアプリケーションには適していない可能性があります。Durable entities prioritize durability over latency, and so might not be appropriate for applications with strict latency requirements.
  • 持続エンティティには、メッセージの組み込みのタイムアウトがありません。Durable entities don't have built-in timeouts for messages. Orleans では、構成可能な時間後にすべてのメッセージがタイムアウトします。In Orleans, all messages time out after a configurable time. 既定値は 30 秒です。The default is 30 seconds.
  • エンティティ間で送信されるメッセージは、信頼性の高い方法で順番に配信されます。Messages sent between entities are delivered reliably and in order. Orleans では、ストリームを介して送信されるコンテンツの信頼性の高い配信または順次配信がサポートされますが、グレイン間のすべてのメッセージについては保証されません。In Orleans, reliable or ordered delivery is supported for content sent through streams, but isn't guaranteed for all messages between grains.
  • エンティティでの要求 - 応答パターンは、オーケストレーションに制限されます。Request-response patterns in entities are limited to orchestrations. エンティティ内からは、元のアクター モデルのように、そして Orleans のグレインとは異なり、一方向のメッセージ (シグナル通知とも呼ばれます) のみが許可されます。From within entities, only one-way messaging (also known as signaling) is permitted, as in the original actor model, and unlike grains in Orleans.
  • 持続エンティティではデッドロックは発生しません。Durable entities don't deadlock. Orleans では、デッドロックが発生する可能性があり、メッセージがタイムアウトするまで解決されません。In Orleans, deadlocks can occur and don't resolve until messages time out.
  • 持続エンティティは、持続オーケストレーションと組み合わせて使用でき、分散ロック メカニズムがサポートされます。Durable entities can be used in conjunction with durable orchestrations and support distributed locking mechanisms.

次のステップNext steps