Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

<sync>

1 つ以上の非同期要求からの応答を待ちます。

Synopsis

<sequence>   <call name="A" async="1" />   <call name="B" async="1" />   ...   <sync calls="A,B" type="all" timeout="3600"/> </sequence>

詳細

属性または要素 説明
calls 属性 必須項目。<sync> が待機する 1 つ以上の非同期 <call> 要素の名前のリストです。 <call> 要素名のカンマ区切りリスト。この値は、リテラル文字列として指定するか、または @ 間接演算子でコンテキスト変数の値を参照することによって指定できます。この後の説明を参照してください。
allowresync 属性 オプション。真の場合、<sync> 要素は繰り返しポーリングを実行し、非同期呼び出しの完了を検出します。つまり、同じ呼び出しに対して <sync> を繰り返し実行することができます。この機能は、呼び出しが完了するまでの時間が明確でない場合に役立ちます。デフォルトの allowresync 値は偽です。 1 (真) または 0 (偽) のブーリアン値。
timeout 属性 オプション。応答を待機する秒数を、XML の xsd:dateTime 型の値を求める式として指定します。 1 文字以上の文字列 (“2003:10:19T10:10” など)。
type 属性 オプション。 文字列 “all” (デフォルト) または “any”。
namedisabledxposyposxendyend 属性 一般的な属性と要素” を参照してください。  
<annotation> 要素

説明

多くのビジネス・プロセスは、外部システムに対して 1 つ以上の要求を発行します。外部システムの応答が遅い場合や、外部システムを利用できない場合などに対応するため、通常、これらの要求は非同期に発行されます。<sync> 要素を使用すると、1 つ以上の非同期呼び出しからの応答を待つ処理が簡単になります。この要素は、<call> 要素と共に使用します。

<sync> 要素の動作は、calls 属性、timeout 属性、および type 属性で指定します。type 属性には、値 “all” (すべての呼び出しからの応答を待機) または “any” (最初に受け取る応答のみを待機) を指定できます。“any” の場合、タイムアウト時間を過ぎた場合と同じように、残りの応答は破棄されます。

例えば、以下の BPL では、2 つの非同期要求 A と B を実行し、さらに、<sync> 要素を使用してその応答を待ちます (最長 1 時間)。

<sequence>
  <call name="A" async="1" />
  <call name="B" async="1" />
  <sync calls="A,B" type="all" timeout="3600" />
</sequence>

タイムアウト時間後に受信した応答には "Discarded" ステータスが設定され、ビジネス・プロセスでは処理されません。<sync> 要素でタイムアウト値を指定しない場合は、経過時間にかかわらず、すべての応答を受け取るまで待機し続けます。 ただし、<sync> 要素が待機している間はビジネス・プロセスがディスクに保存され、それを実行していたジョブが解放されるので、他のビジネス・プロセスを処理できます。

以下の BPL 例では、<process> が 2 つの呼び出しを発行し、5 秒間待機します。

<process request="Demo.Loan.Msg.Application">
  <context>
    <property name="BankName" type="%String"/>
    <property name="IsApproved" type="%Boolean"/>
    <property name="InterestRate" type="%Numeric"/>
    <property name="Results" type="Demo.Loan.Msg.Approval" collection="list"/>
    <property name="Iterator" type="%String"/>
    <property name="ThisResult" type="Demo.Loan.Msg.Approval"/>
  </context>
  <sequence>
    <trace value='"received application for "_request.Name'/>
    <call name="BankUS" target="Demo.Loan.BankUS" async="1">
    <annotation>
      Send an asynchronous request to Bank US.
    </annotation>
    <request type="Demo.Loan.Msg.Application">
      <assign property="callrequest" value="request"/>
    </request>
    <response type="Demo.Loan.Msg.Approval">
      <assign property="context.Results"
              value="callresponse"
              action="append"/>
    </response>
  </call>

  <call name="BankSoprano" target="Demo.Loan.BankSoprano" async="1">
    <annotation>
      Send an asynchronous request to Bank Soprano.
    </annotation>
    <request type="Demo.Loan.Msg.Application">
      <assign property="callrequest" value="request"/>
    </request>
    <response type="Demo.Loan.Msg.Approval">
      <assign property="context.Results"
              value="callresponse"
              action="append"/>
    </response>
  </call>

  <call name="BankManana" target="Demo.Loan.BankManana" async="1">
    <annotation>
      Send an asynchronous request to Bank Manana.
    </annotation>
    <request type="Demo.Loan.Msg.Application">
      <assign property="callrequest" value="request"/>
    </request>
    <response type="Demo.Loan.Msg.Approval">
      <assign property="context.Results"
              value="callresponse"
              action="append"/>
    </response>
  </call>

  <sync name='Wait for Banks'
        calls="BankUS,BankSoprano,BankManana"
        type="all"
        timeout="5">
    <annotation>
      Wait for responses from the banks. Wait up to 5 seconds.
    </annotation>
  </sync>
  <trace value='"sync complete"'/>
  </sequence>
</process>

<sync> 要素を実行するたびに、その <sync> 要素の name がメッセージ・ヘッダに挿入されるので、その後も [メッセージ・ブラウザ] や [ビジュアル・トレース] で参照できます。

<call> 要素の一意名

別の <call> 要素と同じ name で <call> 要素を定義しようとすると、BPL エディタにエラー・メッセージが表示されます。この場合、一意の名前を指定する必要があります。

calls 属性の間接指定

calls 属性の値は文字列です。この文字列は、<call> 要素名のカンマ区切りリストとして指定する必要があります。以下のように、この文字列はリテラル値でもかまいません。

calls="BankUS,BankSoprano,BankManana" 

また、次のように @ 間接演算子を使用して、適切な文字列を含むコンテキスト変数の値にアクセスすることもできます。

calls="@context.myListOfCalls" 

syncresponses

<call> 要素の結果として受け取る応答を処理するための、さらに別のしくみが用意されています。

このしくみでは、<sync> 要素を使用すると、受信したさまざまな応答がコレクションに追加されます。このコレクションはビジネス・プロセスの実行コンテキストの変数であり、syncresponses と呼ばれます。実行コンテキストには、synctimedout という整数の変数もあります。2 つの変数 synctimedoutsyncresponses は、次のように連動して機能します。

オブジェクト 説明
syncresponses syncresponses は応答オブジェクトのコレクションであり、同期している <call> アクティビティの名前がキーとなります。完了した呼び出しのみが示されます。syncresponses から応答を取得できるのは、<sync> を実行してから、現在の <sequence> の終了までの間に限られます。該当する呼び出しが <call name="MyName"> として定義されている syncresponses.GetAt("MyName") 構文を使用して応答を取得します。
synctimedout

synctimedout 値は整数です。synctimedout は、いくつかの呼び出し後の <sync> アクティビティの結果を示します。synctimedout の値をテストできるのは、<sync> の後から、該当する呼び出しと <sync> を含む <sequence> の直前までです。synctimedout の値は、以下の 3 つのいずれかになります。

  • 0 の場合、どの呼び出しもタイムアウトになっていません。すべての呼び出しが時間内に完了しました。<sync> アクティビティに timeout が設定されていない場合も、この値が返されます。

  • 1 の場合、1 つ以上の呼び出しがタイムアウトになりました。つまり、時間切れのため、完了できなかった <call> アクティビティがあります。

  • 2 の場合、1 つ以上の呼び出しが中断されました。

通常、synctimedout を取得してステータスを確認し、その後、syncresponses コレクションの完了した呼び出しから応答を取得します。

<sync> アクティビティを実行するとすぐに、新しい応答に備えて syncresponses コレクションが消去されます。呼び出しから制御が戻ると、それらの応答が syncresponses コレクションに追加されます。<sync> アクティビティが完了した時点で、待機していた応答の一部または全部が syncresponses に格納されます。

例えば、以下の構文を使用して、Call1 と Call2 に <sync> を実行した場合を考えてみます。

<sync type="all" timeout="60">

ここで、Call1 は 60 秒以内に返り、Call2 は 60 秒経過後も返らないものと仮定します。この時点の syncresponses には、Call1 に対する応答のみが含まれ、Call2 への応答は含まれません。synctimedout の値をテストして、該当する値が syncresponses に格納されているかどうかを確認できます。

<sync> アクティビティを実行した後、返された応答にアクセスするには、<call> アクティビティの名前をキーとして使用します。例えば、呼び出しが以下のように定義されているとします。

<call name="nameOfCall">

この場合、次の構文を使用して、応答にアクセスします。

syncresponses.GetAt("nameOfCall")

以下の <sequence> 要素を実行するとします。

<sequence>
  <call name="A" async="1" />
  <call name="B" async="1" />
  <call name="C" async="1" />
  <sync calls="A,B,C" type="all" />
</sequence>

<sync> 要素が完了すると、syncresponses コレクションには、以下のように 3 つの応答オブジェクトへの参照が追加されます。

  • syncresponses.GetAt("A") = A からの応答 (存在する場合)

  • syncresponses.GetAt("B") = B からの応答 (存在する場合)

  • syncresponses.GetAt("C") = C からの応答 (存在する場合)

応答がない場合、syncresponses コレクションは空になります。

Note:

ビジネス・プロセス実行コンテキストの詳細は、このドキュメントの <assign> 要素と、"BPL プロセスの開発" を参照してください。

マルチ・スレッドの syncresponses

<sync> 要素を <flow> と共に使用する場合、<process> 自体を実行するプライマリ・スレッドを含め、スレッドごとに別個の syncresponses コレクションが作成されます。そのため、ビジネス・プロセスの実行中、さまざまな syncresponses コレクションがスコープ内またはスコープ外になる可能性があります。各コレクションは、その直近の <sequence> にのみ関連し、その他の <sequence> とは関連性がありません。

以下の例は、3 つのスレッドにおける synctimedoutsyncresponses の使用法を示しています。3 つのスレッドとは、プライマリ・ビジネス・プロセスのスレッドと、<flow> によって作成された 2 つのスレッドです。

XData BPL
{
<process>
  <context>
    <property name="ResultsFromNorth" type="%String"/>
    <property name="ResultsFromSouth" type="%String"/>
    <property name="ResultsFromEast" type="%String"/>
    <property name="ResultsFromWest" type="%String"/>
  </context>
  <sequence>
  // In this context, syncresponses refers to the primary process thread
    <flow>
    // This flow runs two sequences (two threads) in parallel

      <sequence name="thread1">
      // In this context, syncresponses refers to results in thread1
        <call name="A" />
        <call name="B"  />
        <sync calls="A,B" type="all" timeout="10" />
        // Did the synchronization time out before it finished?
        <if condition='synctimedout="1"'>
          <true>
            <trace value='"thread1 timeout: Call A or B did not return."' />
          </true>
          // If not, then the calls came back, so assign the results.
          <false>
            <assign property="context.ResultsFromEast"
                    value='syncresponses.GetAt("A")'
                    action="append"/>
            <assign property="context.ResultsFromWest"
                    value='syncresponses.GetAt("B")'
                    action="append"/>
          </false>
        </if>
        </sequence>

        <sequence name="thread2">
        // In this context, syncresponses refers to results in thread2
          <call name="C" />
          <call name="A" />
          <sync calls="C,A" type="all"/>
          // Assign the results
          <assign property="context.ResultsFromNorth"
                  value='syncresponses.GetAt("C")'
                  action="append"/>
          <assign property="context.ResultsFromSouth"
                  value='syncresponses.GetAt("A")'
                  action="append"/>
        </sequence>
      </flow>

    // In this context, syncresponses refers to the primary process thread
    <call name="E" />
  </sequence>
</process>
}

この例の <if> アクティビティでは synctimedout が整数値 1 であるかどうかをテストする条件が指定されています。<call>に関するドキュメントで説明しているように、synctimedout の値は、0、1、または 2 となります。2 つの値が等しい場合、この <if> 条件は整数値 1 を受け取り、<true> 要素内の文が実行されます。それ以外の場合は、<false> 要素内の文が実行されます。

allowresync

BPL ビジネス・プロセスでは、<call> を実行した後、その呼び出しに対して、タイムアウトを指定または指定せずに <sync> を複数回実行できます。<sync> の allowresync 属性は、この動作を制御します。allowresync を 1 (真) に設定した場合、同じ <call> に対して引き続き <sync> を実行できます。その呼び出しが完了するまで、繰り返し実行できます。<sync> の allowresync を値 0 (偽) に設定した場合、同じ呼び出しに対してさらに <sync> を実行できません。デフォルトの allowresync 値は 0 です。

実行に長時間かかり、いつまでも応答がない可能性のある <call> A を非同期で実行するとします。A に対する <sync> の timeout を 5 にします。この <sync> は、A が完了した時点で即座に制御を返します。また、A が完了しなくても、タイムアウト時間 (5 秒) が経過した時点で制御を返します。ここで、A の所要時間が不明確であるものの、エラーが発生する可能性は低いとします。つまり、通常は 5 秒以内に完了しますが、ときには 1 時間かかる可能性もあり、その場合の遅延は許容可能だとします。この場合、通常の時間に完了するが、同じ <call> に対してさらに <sync> アクティビティを実行できるケース、または完了に長時間かかるケースに備えて、A が完了したかどうかを頻繁にチェックする必要があります。

一般的な使用法は以下のとおりです。

<sequence>
  <call name="A" async="1" />
  <sync call="A" timeout="5" allowresync="1" />
  <while condition='synctimedout=1'>
    <alert value="Waiting for call A to complete."/>
    <sync call="A" timeout="5" allowresync="1" />
  </while>
</sequence>

<sync> でタイムアウトを指定しない場合は、各 <sync> の前に synctimedout 変数をチェックすることが重要です。この変数をチェックしないと、既に完了している呼び出しを待機し続ける可能性があります。

連続する <sync> タイムアウト

同じ <call> 要素を参照する複数の <sync> 要素を連続して指定し、各 <sync> に timeout 値を設定したとします。<call> が返されるか、または <sync> の timeout 時間が経過したため、最初の <sync> が満たされると、2 番目の <sync> 要素は待機せずに即座に完了します。

<sequence>
  <call name="A" async="1" />
  <sync name="Sync1" calls="A" type="all" timeout="60" />
  <sync name="Sync2" calls="A" type="all" timeout="300" />
</sequence>
FeedbackOpens in a new tab