Hitachi

Hitachi Microservices Platform - Paxos Commit Transaction Orchestrator ユーザーズガイド


2.2.11 TccServiceインタフェースの実装クラスの作成(TCC-Participant限定)

ここでは、TccServiceインタフェースの実装クラスの作成に関して説明します。

TccServiceインタフェースの実装クラスの作成は、TCC-Participantのアプリケーションで実装してください。

TccServiceインタフェースの詳細については、「6.4.5 TccService<I, O extends java.io.Serializable>インタフェース」を参照してください。なお、TCC-Participantでは、TccServiceに実装されたexecuteTryメソッド、executeConfirmメソッド、およびexecuteCancelメソッドの実行によって、APIで扱っているデータの状態は、次の表に示すデータの状態遷移、および次の図に示すデータのステートマシン図のように遷移することを想定しています。

表2‒5 データの状態遷移表

イベント

データの状態

データなし

S0

Try中

S1

Try済み

S2

Confirm済み

S3

executeTryメソッド実行

S1

S1

S2

S3

executeTryメソッド実行完了

S2

executeConfirmメソッド実行

S0

S1

S3

S3

executeCancelメソッド実行

S0

S0

S0

S3

図2‒1 データのステートマシン図

[図データ]

〈この項の構成〉

(1) @Tccアノテーションの付与

TccServiceインタフェースを実装したクラスと、TCC-Participantの機能の紐づけに関して説明します。@Tccアノテーションを付与することでTccServiceインタフェースを実装したクラスとTCC-Participantが紐づけられます。これによって、TCC-Participantの処理中にTccServiceインタフェースを実装したクラスのメソッドが呼び出されて利用されます。

TccServiceインタフェースを実装したクラスを有効にするには、そのクラスをBeanとしてSpring IoC Containerに登録します。

@Tccアノテーションを付与したメソッドは、別のクラスから呼び出してください。同一クラスの別メソッドから呼び出した場合、HMP-PCTOの機能は正しく動作しません。

(a) ライブラリの組み込み

@Tccを使用するには、hmppcto-participant-tccライブラリをアプリケーションに組み込む必要があります。Gradleで組み込む記載例を次に示します。

dependencies {
    implementation 'jp.co.Hitachi.soft.hmppcto:hmppcto-participant-tcc:<version>'
}

また、通常版の場合、hmppcto-participant-tccライブラリは、Hitachi Elastic Application Data Store Client for JavaのJARライブラリを外部読み込みします。このため、実行可能なJAR形式を作成する際、LauncherクラスとしてPropertiesLauncherを使用する必要があります。GradleでLauncherクラスとしてPropertiesLauncherを使用し、実行可能なJAR形式を作成する記載例を次に示します。

bootJar {
    manifest {
        attributes 'Main-Class' : 'org.springframework.boot.loader.PropertiesLauncher'
    }
}

なお、トライアル版の場合、Launcherクラスの変更は不要です。

(b) コーディング例

@Tccアノテーションを利用したコーディング例を次に示します。ここで示すコーディング例では、@Componentアノテーションを付与することで、TccServiceインタフェースを実装したクラスをSpring IoC Containerへ登録しています。@Tccアノテーションを使用するメソッドのアクセス制御修飾子は、private以外にしてください。privateとした場合は、HMP-PCTOの機能は正しく動作しません。

@Component
@Tcc
public class TccServiceClass implements TccService<RequestClass, ResponseClass> {
}

(2) executeTryメソッドの実装

TCC-Participantでは、次に示す機能がexecuteTryメソッドに実装されていることを想定して動作します。

(a) データの仮登録

一般的にTCCパターンのTryフェーズでは、データの仮登録を行います。仮登録であることが分かる状態をデータに持たせる必要があります。

(b) トランザクションを一意に表す文字列とデータの紐づけの永続化

第二引数としてトランザクションを一意に表す文字列であるtransactionKeyがインタフェースに定義されています。TCC-Participantでは、トランザクションを一意に表す文字列をトランザクションで管理する文字列として扱うため、トランザクションを一意に表す文字列と「(a) データの仮登録」で登録したデータの紐づけが必要となります。

紐づけられた情報はexecuteRecoverメソッドで利用します。executeRecoverメソッドはTCC-Participantが再起動時に実行されるため、紐づけられた情報はTCC-Participantが再起動しても情報が失われないよう永続化する必要があります。

トランザクションを一意に表す文字列と(a)で登録したデータの紐づけには、後述のTccResponseクラスを使用してください。TccResponseクラスはjava.io.Serializableインタフェースを継承しているため、このクラスのインスタンスそのものを外部APIなどを使用して永続化してください。

(c) TccResponseクラスの返却

インタフェースには戻り値としてTccResponseクラスを返す必要があると定義されています。TccResponseクラスの詳細については、「6.4.4 TccResponse<T extends java.io.Serializable>クラス」を参照してください。

TccResponseクラスはstring型のtransactionKeyとT型のdataを持ちます。第二引数でトランザクションを一意に表す文字列が渡されるため、transactionKeyはそのまま設定することを想定しています。dataはジェネリクスクラスのT型のため、任意の型のデータを格納できます。「(a) データの仮登録」で仮登録したデータのオブジェクトを設定することを想定しています。

HMP-PCTOは、executeTryメソッドの戻り値をチェックし、次のどちらかに該当する場合はKFSG62017-Eメッセージを出力し、java.lang.IllegalStateExceptionを送出します。

  • 戻り値がnullである場合

  • 戻り値のTccResponseクラスのインスタンスのtransactionKeyフィールドがnullである場合

(3) executeConfirmメソッドの実装

TCC-Participantでは、次に示す機能がexecuteConfirmメソッドに実装されていることを想定して動作します。

(a) executeTryメソッドで登録した仮登録のデータの確定

一般的にTCCパターンのConfirmフェーズでは、executeTryメソッドで仮登録したデータの確定処理を行います。DBの概念ではCommitに該当する処理になります。executeTryメソッドで登録したデータの仮登録の状態を更新し、仮登録ではない状態にする必要があります。executeConfirmメソッドの引数にはexecuteTryメソッドの戻り値のTccResponseクラスが渡されます。TccResponseクラスのdataの内容を見て、確定処理を行うデータを特定することを想定しています。

(b) 永続化したトランザクションを一意に表す文字列とデータの紐づけ情報の削除

executeTryメソッドで永続化したトランザクションを一意に表す文字列と、データの紐づけ情報の削除を行う必要があります。executeRecoverメソッドでは未決着状態のデータを返す必要があるため、executeConfirmメソッドで決着したデータに関してこの削除処理を行わないと、決着済みのデータを返してしまい、executeRecoverメソッドの要件を満たすことができなくなります。

(4) executeCancelメソッドの実装

TCC-Participantでは、次に示す機能がexecuteCancelメソッドに実装されていることを想定して動作します。

(a) executeTryメソッドで登録した仮登録のデータの削除

一般的にTCCパターンのCancelフェーズでは、executeTryメソッドで仮登録したデータの削除処理を行います。

DBの概念ではRollbackに該当する処理になります。そのため、executeTryメソッドを実行する前の状態に戻っている必要があります。executeTryメソッドの実行状況によって、次のケースが考えられます。

  • executeTry完了後にexecuteCancelが実行されるケース

  • executeTry実行中にexecuteCancelが実行されるケース

executeTry完了後にexecuteCancelが実行されるケース

executeCancelメソッドの引数にはexecuteTryメソッドの戻り値のTccResponseクラスが渡されます。TccResponseクラスのdataの内容を見て、削除処理を行うデータを特定することを想定しています。

executeTry実行中にexecuteCancelが実行されるケース

TCC-ParticipantではexecuteTryメソッドの実行がタイムアウトした場合にexecuteTryメソッドの途中であってもexecuteCancelメソッドが実行されます。その場合にexecuteTryメソッドの実行を中止し、executeTryメソッド実行前の状態に戻す必要があります。この場合、executeCancelメソッドの引数に渡されるTccResponseクラスにはtransactionKeyだけが設定され、dataはnullの状態で渡されます。

このケースでは、transactionKeyの情報だけでexecuteTry実行前の状態に戻す必要があります。

(b) 永続化したトランザクションを一意に表す文字列とデータの紐づけ情報の削除

executeTryメソッドで永続化したトランザクションを一意に表す文字列と、データの紐づけ情報の削除を行う必要があります。executeRecoverメソッドでは未決着状態のデータを返す必要があるため、executeCancelメソッドで削除したデータに関してこの削除処理を行わないと、削除済みのデータを返してしまい、executeRecoverメソッドの要件を満たすことができなくなります。

(5) executeRecoverメソッドの実装

TCC-Participantでは、次に示す機能がexecuteRecoverメソッドに実装されていることを想定して動作します。

(a) 未決着状態かつ自身のTccServiceが登録した永続化したデータの一覧を返す

executeRecoverメソッドは戻り値としてTccResponseの一覧を返す必要があります。その際に条件として、未決着状態、かつ、自身のTccServiceが登録したデータであることが必要です。executeTryメソッド、executeConfirmメソッド、executeCancelメソッドの実装で示したとおり、executeTryメソッドでトランザクションを一意に表す文字列とデータの紐づけの情報が永続化され、executeConfirmメソッド、executeCancelメソッド実行時に削除されます。これによって、永続化されている情報は未決着状態のデータだけとなります。この時点では自身のTccServiceが登録したデータの絞り込みがされていないため、executeRecoverメソッド内で絞り込みを実施する必要があります。

なお、executeRecoverメソッドの戻り値に含めるTccResponseクラスのインスタンスは、executeTryメソッドのときにシリアライズして永続化したTccResponseクラスのインスタンスをexecuteRecoverメソッド内でデシリアライズしたものである必要があります。このため、executeRecoverメソッド内でTccResponseクラスのコンストラクタを呼び出してTccResponseクラスのインスタンスを生成することはできません。もし、executeRecoverメソッド内でTccResponseクラスのコンストラクタを呼び出した場合、HMP-PCTOはKFSG62016-Eメッセージを出力し、java.lang.IllegalStateExceptionを送出します。

HMP-PCTOは、executeRecoverメソッドの戻り値をチェックし、次のどれかに該当する場合はKFSG62018-Eメッセージを出力し、java.lang.IllegalStateExceptionを送出します。

  • 戻り値がnullである場合

  • 戻り値のjava.util.Setにnullが含まれている場合

  • 戻り値のjava.util.SetにtransactionKeyフィールドがnullであるTccResponseクラスのインスタンスが含まれている場合

    重要

    ユーザがexecuteRecoverメソッド実行時の前提を設けている場合(例えば、トランザクションを一意に表す文字列とデータの紐づけの永続化先としてDBを使用しており、その前提としてexecuteRecoverメソッド実行時よりも前にDBの初期化を完了させておく必要があるなど)、TCC-ParticipantのJavaアプリケーションプロセス起動開始前にその前提を満たしておく必要があります。

(6) getOperationIdメソッドの実装

TCC-Participantでは、次に示す機能がgetOperationIdメソッドに実装されていることを想定して動作します。

(a) TccServiceを一意に識別できる文字列を返す

TCC-ParticipantではgetOperationIdメソッドの戻り値を利用してTccServiceを一意に識別しています。ほかのTccServiceとOperationIdが重複した場合にはTCC-Participantの動作に影響が出るため、ほかのTccServiceと重複しない一意に識別できる文字列を返す必要があります。

戻り値の文字列の長さは1〜256バイトの範囲内である必要があります。

HMP-PCTOは、getOperationIdメソッドの戻り値をチェックし、1に該当する場合はKFSG62019-Eメッセージ、2に該当する場合はKFSG62020-Eメッセージ、3に該当する場合はKFSG62021-Eメッセージを出力し、java.lang.IllegalStateExceptionを送出します。

  1. 戻り値がnullである場合

  2. 戻り値の文字列の長さが1〜256バイトの範囲内ではない場合

  3. 同一のTCC-Participant内の他のTccServiceと同じOperationIdを返した場合

また、TCC-Participantが再起動した際は再起動前と同じ文字列を返す必要があります。