Workflow Manager 1.0 の新しいバージョンのワークフローまたはカスタム アクティビティの追加

 

ワークフローを開発する場合、バグ修正の必要性やビジネス要件の変更のために、頻繁にアクティビティの定義を変更する必要があることに気付くことがあります。どちらの場合も、以前に発行したアクティビティ定義やワークフロー定義の新しいリビジョンを作成したいと考えます。このトピックでは、Workflow Manager 1.0 によって提供されるバージョン管理機能の概要と、それらの機能を自分のシナリオにどのように当てはめるかについて説明します。

Workflow Manager 1.0 では、アクティビティおよびワークフロー定義を更新できます。アクティビティまたはワークフロー定義を更新するだけで、この簡単な更新によって、内部でリビジョン管理メカニズムを呼び出すことができます。たとえば、LoanProcessing アクティビティを使用する EligibilityCheck ワークフローがあり、EligibilityCheck アクティビティのバグを修正したいと考える場合、単にこのアクティビティを新しい定義で更新するだけです。ただし、このアクティビティを参照する既存のワークフローにはどのような影響が出るでしょうか。古い定義と新しい定義のどちらを使用するのでしょうか。既存のインスタンスはどの実装を使用するのでしょうか。新しいインスタンスはどの実装を使用するのでしょうか。

同様に、LoanProcessing ワークフローを 50 万ドルを超えるローンの追加の承認者手順を含めて更新したいとします。ここでも、次のような疑問を持たれるでしょう。既存のインスタンスにはどのような影響が出るでしょうか。古い定義と新しい定義のどちらを使用するのでしょうか。新しいインスタンスはどのバージョンを使用するのでしょうか。

このトピックのセクションでは、こうしたシナリオを実装する方法と、Workflow Manager 1.0 のバージョン管理機能の概要を説明します。

ワークフロー リビジョンのシナリオを見ていきましょう。LoanProcessing というワークフローがあります。LoanProcessingEligibilityCheck アクティビティを含んでいます。既に EligibilityCheck アクティビティと LoanProcessing ワークフローを Workflow Manager 1.0 に発行しています。ここで、ワークフロー ロジックのバグを修正するために、LoanProcessing ワークフローを修正する必要があります。必要な変更を行ったら、PublishWorkflow クラスで WorkflowResourceManager メソッドを呼び出します (または REST API を直接呼び出す場合はワークフロー リソースで HTTP PUT を使用します)。この操作の一部として、Workflow Manager 1.0 は内部で、この呼び出しの一部として渡された定義を使用して、このワークフローの新しいリビジョンを作成します。バグ修正の性質によって、(古い定義を使用する) 既存のインスタンスを終了するか、起動に使用した古い定義を使用して実行し続けるかのオプションがあります。ワークフローを発行するには、PublishWorkflow メソッドを使用できます。次の例では、実装として LoanProcessing を使用する EligibilityCheck ワークフローを発行しています。

WorkflowDescription wfDesc = new WorkflowDescription();
wfDesc.Name = "LoanProcessing";
wfDesc.ActivityPath = "EligibilityCheck";
Uri wfUri = client.Workflows.Publish(wfDesc);

既存のインスタンスを終了する場合は、PublishWorkflowterminateActiveInstances に設定して、true メソッドを呼び出すことができます。false に設定するか、内部で PublishWorkflow の値を指定する terminateActiveInstances パラメーターのない false メソッドのオーバーロードを呼び出した場合、既存のインスタンスはインスタンス化に使用した定義を使用して、実行し続けます。これは、バグ修正が増分的な性質を持つシナリオの場合に適しています。たとえば、LoanProcessingWorkflow に変更があるが、このプロセスの変更は新しいローン申請に対してのみ有効にする必要がある場合、および既存のローン申請で、プロセスの古いバージョンを使用してもかまわない (既存のローン顧客にそのことを伝えているため) 場合、そのような状況では、terminateActiveInstancesfalse に設定できます。前の例では、PublishWorkflow パラメーターを取らない terminateActiveInstances のオーバーロードが呼び出されているため、既存のインスタンスは終了しません。

バグ修正が重大で、既存のインスタンスを終了させたい場合、たとえば、ローン処理ワークフローが誤ってすべての申請を承認した場合などは、terminateActiveInstancestrue に設定して、定義を更新できます。アクティブなインスタンスの終了プロセスは非同期であるため、直ちに行われるとは限らず、最終的に終了するまで、1 つまたは複数のインスタンスが実行し続ける可能性があります。ワークフローの複数のリビジョンがあっても、最新のバージョンのみが新しいインスタンスの作成に使用されます。同様に、このワークフローの GetWorkflow 呼び出しを行うと、最新のワークフローの定義のみが取得されます。

上記の同じローン承認プロセスの例を拡張して、ビジネス要件の変更を考慮するように、EligibilityCheck アクティビティを修正する必要がある場合はどうでしょうか。このアクティビティに必要な変更は行っており、ここで EligibilityCheck にこの新しい定義を発行したいと考えます。これを実行するには、クライアントで PublishActivity メソッド (またはアクティビティのリソース URI で HTTP PUT) を呼び出すことができます。この呼び出しの結果として、このアクティビティを (直接または間接的に) 使用するすべてのアクティビティとすべてのワークフローが、新しいバージョンを使用するように内部で更新され、このアクティビティを (直接または間接的に) 使用するワークフローの新しいインスタンスは新しい定義を使用して起動します。

ワークフローの更新に伴って、既存のアクティブなインスタンスの終了を選択できるのと同じように、アクティビティの更新時にも同様の選択ができます。ただし、この選択は、システムにはるかに大きい影響を及ぼす可能性があります。これを理解するには、ワークフローはアクティビティ (少なくとも 1 つのアクティビティ) を参照でき、同様にアクティビティは 0 個以上のアクティビティを参照できることを思い出す必要があります。そのため、特定のアクティビティは、0 個以上のアクティビティによって参照されている可能性があり、さらに、それらのアクティビティは 0 個以上のワークフローによって参照されている可能性があります。このことは、特定のアクティビティが多くのワークフロー定義によって、直接または間接的に参照されている可能性があることを意味します。

アクティビティを更新する場合、ワークフローを更新する場合と同じ決定をします。(アクティビティに依存する) すべてのワークフローのすべてのインスタンスを終了するか、または以前のアクティビティ定義を使用して実行し続けるかということです。この動作は、terminateDependentInstances パラメーターによって決まります。terminateDependentInstances パラメーターを使用しないオーバーロードを呼び出した場合、依存するインスタンスは終了されずに古いバージョンのアクティビティを使用します。次の例では、TestActivity が発行され、依存するインスタンスは終了しません。

Activity newActivity = new Sequence
{
     ...
};

XElement activityXaml = XElement.Parse(XamlServices.Save(newActivity));

ActivityDescription activityDesc = new ActivityDescription();
activityDesc.SetXaml(activityXaml);

activityDesc.Name = "TestActivity";
client.Activities.Publish(activityDesc);

既存のアクティビティ定義が更新されると、Workflow Manager 1.0 は次の処理を実行します。

  1. 指定されている定義を使用して、このアクティビティの新しいバージョンを作成します。

  2. このアクティビティを参照しているすべてのワークフロー定義を、このアクティビティの新しいバージョンを使用するように更新します。

  3. terminateDependentInstancestrue に設定して、呼び出しが行われた場合、このアクティビティを参照しているすべてのワークフローのすべてのインスタンスが終了します。

System_CAPS_noteメモ

前のリストで、最初の手順は、アクティビティ定義を更新する呼び出しの一部として同時に実行され、それに続く手順は非同期に実行されます。このことは、特定のアクティビティを正しく更新していても、このアクティビティを参照するすべてのワークフローにこの変更が適用されるには、しばらく (数分程度) かかる可能性があることを意味します。そのため、その間、それらのワークフローが古い定義を使用する可能性があります。ただし、この非同期プロセスが完了すると、このアクティビティを参照しているすべてのワークフローがこのアクティビティの最新の定義を使用するようになります。

System_CAPS_noteメモ

アクティビティの複数のリビジョンがある場合でも、アクティブなのは常にそれらのうち 1 つのアクティビティだけです。他のリビジョンは、このアクティビティを参照している既存のワークフローのインスタンスをサポートするために、内部で維持されています。そのため、このアクティビティの Get 呼び出しを行うと、最新のアクティビティ定義のみが取得されます。

特定のワークフローが必要でなくなった場合に、削除したいと考えることがあります。たとえば LoanProcessing ワークフローで、組織で特定の種類のローンの処理を中止したとします。誤ってインスタンスがトリガーされないようにするために、このワークフローを削除したいと考えます。ワークフローを削除するには、クライアント API を使用して DeleteWorkflow メソッドを呼び出すか、ワークフロー リソースの URI を使用して REST エンドポイントで DELETE を呼び出します。ワークフローを削除する場合、既存のインスタンスに関して 2 つの選択肢があります。ビジネス上の決断で、既存のローンの処理を完了させるが、新しいインスタンスを許可しない場合、Delete で次の WorkflowManager メソッドを呼び出すことができます。

public void Delete(string workflowName)

このオーバーロードでは、既存のインスタンスを終了しません。既存のインスタンスは、完了するまで処理が続行します。ただし、ワークフロー自体が存在しないため、新しいインスタンスは作成されません。そのため、このワークフローの新しいインスタンスをアクティブにするメッセージを送信しても、このワークフローのインスタンスはアクティブになりません。ただし、ビジネス上の決断で、既存のローン申請も終了させる場合は、Delete パラメーターを取る terminateActiveInstances オーバーロードを使用して、そのパラメーターを true に指定できます。

public void Delete(string workflowName, bool terminateActiveInstances)

これにより、新しいインスタンスが起動しなくなり、実行中のインスタンスが終了します。

きわめてまれな状況で、アクティビティも削除する必要がある場合があります。アクティビティの更新の場合と同様に、多くのワークフローが直接または間接的にアクティビティを参照し、削除によって影響を受けます。アクティビティを削除するには、クライアント API の Delete メソッドを使用するか、アクティビティ リソースの URI を使用して REST エンドポイントで DELETE を呼び出します。ここでもまた、このアクティビティを参照する既存のワークフローのインスタンスに関して、2 つの選択肢があります。アクティビティを直接または間接的に参照する既存のインスタンスの実行を続行させたい場合は、DeleteActivityManager パラメーターを取らない terminateDependentInstances メソッド オーバーロードを呼び出すか、このパラメーターを取るオーバーロードを呼び出して、そのパラメーターを false に設定します。

public void Delete(string activityName)

このオーバーロードは、このアクティビティを参照している既存のワークフローのインスタンスを終了しません。ただし、新しいインスタンス用のこのアクティビティは存在しなくなったため、このアクティビティを参照する新しいワークフローのインスタンスは作成されません。そのため、実行時に、アクティビティの 1 つがないため、ワークフローの XAML が完全に計算できなかったことを示す例外がログにスローされます。

アクティビティの削除とワークフローの削除の動作の違いに注意してください。ワークフロー定義が削除されると、ワークフローのインスタンスをアクティブ化するすべてのメッセージが単に無視されるだけです。しかし、アクティビティの削除の場合は、このアクティビティを参照しているすべてのワークフロー定義が削除されません。ワークフロー定義は存在し続けるため、ワークフロー定義に属するすべてのメッセージの処理を試みます。しかし、このアクティビティを見つけて実行することができないため、例外をスローし、インスタンスを終了します。これが意味することは、特定のアクティビティを削除しても、ワークフロー定義がまだ使用可能であることです。この削除したアクティビティを使用しないように、ワークフロー定義ロジックを変更すれば、新しいインスタンスは正常に実行を開始します。アクティビティを削除するときに既存のインスタンスを終了したい場合は、Delete を呼び出し、terminateDependentInstancestrue に設定します。これにより、このアクティビティを参照しているワークフローの既存のインスタンスも終了します。

public void Delete(string activityName, bool terminateDependentInstances)
表示: