Skip to content

Comments

Use Alpakka Cassandra 2.0.2 instead of DataStax Java Driver 3.11.0#54

Merged
negokaz merged 10 commits intomainfrom
upgrade-datastax-java-driver-to-4.13.0
Sep 8, 2021
Merged

Use Alpakka Cassandra 2.0.2 instead of DataStax Java Driver 3.11.0#54
negokaz merged 10 commits intomainfrom
upgrade-datastax-java-driver-to-4.13.0

Conversation

@xirc
Copy link
Contributor

@xirc xirc commented Aug 26, 2021

Use Alpakka Cassandra 2.0.2 instead of DataStax Java Driver 3.11.0.

  • It includes DataStax Java Driver upgrade to 4.x from 3.x
  • Using Alpakka Cassandra instead would make us easy to maintain backward binary compatibility.

DataStax Java Driver Upgrade

The Upgrade Guide: https://docs.datastax.com/en/developer/java-driver/4.6/upgrade_guide

  • Upgrade
  • Add tests
  • Write the migration guide
  • Write the changelog

@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch from a381893 to 667d516 Compare August 26, 2021 06:11
# If we prefer to override such settings for each tenant,
# we must use a different path for each tenant by overriding this setting.
# See also https://docs.datastax.com/en/developer/java-driver/latest/manual/core/configuration/
datastax-java-driver-config = "datastax-java-driver"
Copy link
Contributor Author

@xirc xirc Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

次の driver に関連する項目は datastax-java-driver から設定できます。

  • contact-points
  • authentication
  • socket
  • retry-policy
  • load-balancing-policy

# We can set different profiles for reads and writes.
# See also https://docs.datastax.com/en/developer/java-driver/latest/manual/core/configuration/#execution-profiles
read-profile = "lerna-util-sequence-profile"
write-profile = "lerna-util-sequence-profile"
Copy link
Contributor Author

@xirc xirc Aug 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

profile 機能を活用し、consistency level 等が設定できます。
profile の概要は次の URL から確認できます。
https://docs.datastax.com/en/developer/java-driver/4.13/manual/core/configuration/#execution-profiles

デフォルト構成では、read, write の profile は同じものを使います。
必要に応じてprofile 名を変更することで、read と write に異なる profile を使用することもできます。

@@ -284,7 +288,7 @@ private[sequence] final class SequenceStore(
maybeRow <- executeRead(
selectSequenceReservationStatement.bind(sequenceId, normalizeSubId(sequenceSubId), Integer.valueOf(nodeId)),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Statement は immutable な builder API になりました。
https://docs.datastax.com/en/developer/java-driver/4.13/upgrade_guide/#statements

もしも Statement を mutable API を使って構築している場合には書き換えが必要です。

$ git grep -iF 'Statement' -- lerna-util-sequence
lerna-util-sequence/src/main/scala/lerna/util/sequence/CassandraStatements.scala:private[sequence] final class CassandraStatements(config: SequenceFactoryCassandraConfig) {
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:import com.datastax.oss.driver.api.core.cql.{ PreparedStatement, Row, Statement }
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      selectSequenceReservationStatement: PreparedStatement,
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      insertSequenceReservationStatement: PreparedStatement,
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:  val statements = new CassandraStatements(config)
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:  private[this] def executeWrite[T <: Statement[T]](
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      statement: Statement[T],
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:    session.executeAsync(statement.setExecutionProfileName(config.writeProfileName)).toScala.map(_ => Done)
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:  private[this] def executeRead[T <: Statement[T]](
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      statement: Statement[T],
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:    session.executeAsync(statement.setExecutionProfileName(config.readProfileName)).toScala.map { asyncResult =>
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      _                                  <- session.executeAsync(statements.createKeyspace).toScala
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      _                                  <- session.executeAsync(statements.useKeyspace).toScala
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      _                                  <- session.executeAsync(statements.createTable).toScala
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      selectSequenceReservationStatement <- session.prepareAsync(statements.selectSequenceReservation).toScala
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:      insertSequenceReservationStatement <- session.prepareAsync(statements.insertSequenceReservation).toScala
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:        selectSequenceReservationStatement,
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:        insertSequenceReservationStatement,
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:        selectSequenceReservationStatement.bind(sequenceId, normalizeSubId(sequenceSubId), Integer.valueOf(nodeId)),
lerna-util-sequence/src/main/scala/lerna/util/sequence/SequenceStore.scala:        insertSequenceReservationStatement.bind(
lerna-util-sequence/src/test/scala/lerna/util/sequence/SequenceTestkit.scala:import com.datastax.oss.driver.api.core.cql.SimpleStatement
lerna-util-sequence/src/test/scala/lerna/util/sequence/SequenceTestkit.scala:      SimpleStatement

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確認する限り、書き換えが必要なコードはありませんでした。

selectSequenceReservationStatement.setRetryPolicy(config.cassandraReadRetryPolicy),
insertSequenceReservationStatement.setRetryPolicy(config.cassandraWriteRetryPolicy),
selectSequenceReservationStatement,
insertSequenceReservationStatement,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RetryPolicy は profile ごとに指定するようになります。
executeWrite, executeRead メソッドで profile を指定しています。

@xirc xirc added this to the v3.0.0 milestone Aug 26, 2021
@xirc xirc self-assigned this Aug 26, 2021
@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch 2 times, most recently from ea57405 to 22bb101 Compare August 27, 2021 05:25
val selectSequenceReservation: SimpleStatement =
SimpleStatement
.newInstance(selectSequenceReservationCQL)
.setIdempotent(true)
Copy link
Contributor Author

@xirc xirc Aug 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Statement (a.k.a. Query) に 冪等 (Idempotent) かどうかを設定するようにします。

QueryBuilder を使わない限り、冪等かどうかは手動で設定する必要があります。
冪等でない Query は driver ではリトライされません。
Query が冪等かどうか設定されていない場合には、
setDefaultIdempotence(true)と明示しない限り (3.xの場合)、デフォルトは冪等ではないと扱われます。
4.x の場合は、設定項目 basic.request.default-idempotence があります。

https://docs.datastax.com/en/developer/java-driver/3.11/manual/retries/#retries
https://docs.datastax.com/en/developer/java-driver/3.11/manual/idempotence/#query-idempotence
https://docs.datastax.com/en/developer/java-driver/4.13/manual/core/retries/#retries
https://docs.datastax.com/en/developer/java-driver/4.13/manual/core/idempotence/

selectSequenceReservationStatement および insertSequenceReservationStatement が冪等な CQL を実行していれば、.setIdempotence(true) と設定することでRetry Policy を使った driver でのリトライが行われるようになります。5つの CQL は冪等であるため、.setIdempotence(true) を使用しました。

冪等の設定は、prepared statement 、 bounded statement を介した場合でも引き継がれます。
ドキュメントから確認することができます。
https://docs.datastax.com/en/developer/java-driver/4.13/manual/core/idempotence/#:~:text=When%20you%20prepare%20a%20statement,%20its%20idempotence%20carries%20over%20to%20bound%20statements:

また、4.x では冪等を明示しない場合のデフォルト値を、設定 basic.request.default-idempotence で指定することができます。デフォルト値は false です。この設定が true に設定された場合でも、冪等を明示していない、冪等でない Query が 誤って 冪等であると判断されないように、冪等でない Query の場合には .setIdempotence(false) を明示するほうが安全だと思われます。

@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch 4 times, most recently from aed0c97 to 0665c95 Compare August 30, 2021 06:08
import com.datastax.driver.core.policies._
import akka.actor.ClassicActorSystemProvider
import com.datastax.oss.driver.api.core.config.DriverConfigLoader
import com.datastax.oss.driver.internal.core.config.typesafe.DefaultDriverConfigLoader
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

バイナリの後方互換性について、注意事項があります。
#54 (comment) のディスカッションを参照してください。

@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch from 0665c95 to af561da Compare August 30, 2021 06:29
Dependencies.Akka.actorTyped,
Dependencies.Akka.actorTestKitTyped % Test,
Dependencies.Akka.actorTestKitTyped % Test,
Dependencies.ScalaLang.scalaJava8Compat % Test,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scala/scala-java8-compat: A Java 8 compatibility kit for Scala.

幾つか追加したテストで Java Optional => Scala Option に変換する等のために必要です。

@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch 2 times, most recently from 3bacc8a to 1dd93d7 Compare August 31, 2021 02:11
Here is the upgrade guide.
https://docs.datastax.com/en/developer/java-driver/4.13/upgrade_guide

Note that the Maven Coordinates is changed.
@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch from 1dd93d7 to df339c4 Compare August 31, 2021 02:18
@xirc xirc changed the title WIP: Upgrade datastax java driver to 4.13.0 Upgrade datastax java driver to 4.13.0 Aug 31, 2021
@xirc xirc marked this pull request as ready for review August 31, 2021 02:38
@xirc xirc requested a review from negokaz August 31, 2021 02:38
@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch from a9eac9f to bfe5bb7 Compare September 2, 2021 05:17
It would make us easy to maintain binary backward compatibility.
@xirc xirc changed the title Upgrade datastax java driver to 4.13.0 Use Alpakka Cassandra 2.0.2 instead of DataStax Java Driver 3.11.0 Sep 3, 2021
Feedback from code review.
We prefer to handle possible exceptions explicitly.
@xirc xirc force-pushed the upgrade-datastax-java-driver-to-4.13.0 branch from 03d7383 to 785eee8 Compare September 3, 2021 02:47
It could provide
* Customize Session Provider
* Cassandra's contact points discovery via Akka Discovery
# we must use a different path for each tenant by overriding this setting.
# See also https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/configuration/
datastax-java-driver-config = "datastax-java-driver"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xirc 設定項目 session-providerservice-discoverydatastax-java-driver-configalpakka.cassandra と同じ構成になっているようなので、設定項目を次のように継承するのはどうでしょうか?

default = ${alpakka.cassandra} {

    # Profiles to use.
    # We can set different profiles for reads and writes.
    # See also https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/configuration/#execution-profiles
    read-profile = "lerna-util-sequence-profile"
   ... 略 ...

キーの衝突を避けるため、次のように設定を継承するための新しい設定項目を作っても良いかもしれません。

defualt {
    alpakka.cassandra = ${alpakka.cassandra}

    # Profiles to use.
    # We can set different profiles for reads and writes.
    # See also https://docs.datastax.com/en/developer/java-driver/4.6/manual/core/configuration/#execution-profiles
    read-profile = "lerna-util-sequence-profile"
   ... 略 ...
}

config の継承については次のページに説明があります。

data-center-generic = { cluster-size = 6 }
data-center-east = ${data-center-generic} { name = "east" }
data-center-west = ${data-center-generic} { name = "west", cluster-size = 8 }

lightbend/config: configuration library for JVM languages using HOCON files

このようにしておくと、ユーザーが session-providerservice-discovery を設定する場合 alpakka.cassandra 配下の設定を override しさえすれば、akka-persistence と lenra-util-sequence の両方に設定を反映できるようになるはずです。

また、Alpakka Cassandra が読み込む設定が増えたとしても lerna-util-sequence の reference.conf を改修する必要がなくなるはずです。

Copy link
Contributor Author

@xirc xirc Sep 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@negokaz

継承することも可能だと思います。
継承する方法はデメリットもあるように思うので、慎重に検討する方が良いと思いました。

session-dispatcher

lerna.util.sequence.cassandra.default には alpakka.cassandra の設定がすべて含まれるわけではありません。
lerna.util.sequence.cassandra.default には設定項目 session-dispatcher がありません。

https://github.com/akka/alpakka/blob/v2.0.2/cassandra/src/main/resources/reference.conf#L13-L14

  # The ExecutionContext to use for the session tasks and future composition.
  session-dispatcher = "akka.actor.default-dispatcher"

session-dispatcher は、CassandraSessionRegistry から使用されるようです。
https://github.com/akka/alpakka/blob/v2.0.2/cassandra/src/main/scala/akka/stream/alpakka/cassandra/scaladsl/CassandraSessionRegistry.scala#L92

    val executionContext = system.dispatchers.lookup(sessionProviderConfig.getString("session-dispatcher"))

lerna-util-sequence は、CassandraSessionRegistry を使用していないため、session-dispatcher は使用されません。
使用されない設定項目が存在する場合に、ユーザが混乱することを懸念しています。

この設定項目は Cassandra Session に関連するタスクを実行する ExecutionContext を指定できるものだと理解していますが、
session-dispatcher が設定可能である場合、ユーザは SequenceStore 等が実行する CQL 実行の Future の合成に使用する ExecutionContext も指定できると想定する可能性がないかとも懸念しています。 設定項目のパスだけを見ると lerna.util.sequence.cassandra.default.session-dispatcher と見えるためです。

今後、仮に alpakka.cassandra の設定項目が増えた場合に、 lerna.util.sequence.cassandra.default にあるどの設定項目が使用されているのか判断することは難しくなっていくかもしれません。lerna.util.sequence.cassandra.default.alpakka.cassandra という設定項目を作ったとしても、同じような問題に遭遇するように思います。

akka-persistence-cassandra

akka-persistence-cassandra は、alpakka.cassandra の設定を継承していないように思います。

https://github.com/akka/akka-persistence-cassandra/blob/v1.0.5/core/src/main/resources/reference.conf#L23-L46

akka.persistence.cassandra {
... truncated

alpakka.cassandra.session-provideralpakka.cassandra.service-discovery の設定を変更しても、akka-persistence-cassandra の振る舞いは変更されないのではないかと思います(実際に試したわけではありませんので確証はありません)。

必要であれば、ユーザは次のようにして設定項目を継承できます。

akka.persistence.cassandra.session-provider = ${alpakka.cassandra.session-provider}

lenra-util-sequence についても、同じようにユーザは継承を活用して同じ値を設定できます。

テスト

lerna.util.sequence.cassandra.defaultalpakka.cassandra の設定項目を継承すると仮定します。alpakka.cassandra で設定項目が追加された際に、その設定項目が lerna-util-sequence においても意図通りに機能することをテストする必要があるように思います。Alpakka Cassandra のアップデートによって、テストしていない設定項目が追加されることに私たちはどのように対応するのか、検討しておく必要があります。

設定の後方互換性

「設定項目を継承する」ことにもメリットがあることも分かります。

設定項目を管理する手間を省くことができるかもしれません。
ただし、これはテストをしないということは意図していません。
設定項目についてテストを実施する必要があると思います。

CqlSessionProvider(system, config) が要求する設定項目が確実に存在することを保証できます。
CqlSessionProvider の要求する必須設定項目が増えた場合に、現在の実装では CqlSessionProvider の呼び出しで例外が発生することになると思われます。そのため、CqlSessionProvider を使用している CassandraSessionProvider.connect が 恐らく Failure を返すことになります。

回避策の1つとして、次のようにすることも考えられます。

        val  alpakkaCassandraConfig = system.classicSystem.settings.config.getConfig("alpakka.cassandra")
        CqlSessionProvider(
          system.classicSystem.asInstanceOf[ExtendedActorSystem],
          validatedConfig.sessionProviderConfig.withFallback(alpakkaCassandraConfig),
        )

この方法にもデメリットがあるかもしれません。
例えば、ユーザが Alpakka Cassandra を全く別の用途に使っており、alpakka.cassandra.service-discovery.name を設定していたとします。ユーザが誤って lerna.util.sequence.cassandra.default.service-discovery.namenull にした場合、 alpakka.cassandra.service-discovery.name にフォールバックされるかもしれません(実際に試したわけではないため、確証はありません)。これは、lerna-util-sequence がユーザの意図しない Cassandra Cluster に接続する結果となる恐れがあります。Cassandra の認証情報を個別に管理していれば接続が拒否されるだけで済みますが、そうでない場合にどのようになるのか予想するのは難しいように思います。このようなフォールバックとなる振る舞いをユーザが意図的に設定したわけではないため、ユーザの混乱を招かないか懸念しています。

ユーザが予測しにくいデフォルトを設定するよりもエラーとなるようにしたいと思いました。
ただし、もっと上手な対処方法があればデメリットなしで設定を継承することも可能かもしれません。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defualt {
    alpakka.cassandra = ${alpakka.cassandra}

提案頂いた設定項目の継承を調整して、次のように alpakka.cassandra へのパスを指定する方法も考えられそうです。

defualt {
    alpakka-cassandra-config = "alpakka.cassandra"

    read-profile = "lerna-util-sequence-profile"
    // ... truncated
}

この方法であれば、設定の互換性は問題なくなるかもしれません。

また、lerna.util.sequence.cassandra.default.session-dispatcher のような使用しない設定項目がユーザに見えることもないように思うため、上手く解決できる可能性がありそうです。依然として alpakka.cassandra.session-dispatcher は使用しませんが、設定階層が異なるため混乱は招きにくくなりましたか?それともあまり改善できていませんか?

欠点は、Cassandraドライバの設定 (datastax-java-driver) にたどり着くために、いくつか設定項目を参照しながら辿る必要があることでしょうか。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xirc 様々な観点での検討ありがとうございます。

session-dispatcher

使用されない設定項目が存在する場合に、ユーザが混乱することを懸念しています。

ユーザーが混乱する可能性があることは私も同意です。
設定項目を継承する場合は、利用されない設定項目についてコメントで説明しておく必要があると思います。

akka-persistence-cassandra

akka-persistence-cassandra は、alpakka.cassandra の設定を継承していないように思います。

確かに継承していないですね。。
akka-cluster-sharding の coordinator-singleton と同じような構造になっているのかと思っていました。
コメント書く前に確認したほうが良かったですね。すみません。

coordinator-singleton = ${akka.cluster.singleton}

akka/reference.conf at v2.6.16 · akka/akka

設定を共有する方法については、示してもらったユーザー自身による継承で対処してもらうという方針で良さそうです。

テスト

lerna.util.sequence.cassandra.defaultが alpakka.cassandra の設定項目を継承すると仮定します。alpakka.cassandra で設定項目が追加された際に、その設定項目が lerna-util-sequence においても意図通りに機能することをテストする必要があるように思います。

新しく追加された設定項目が lerna-util-sequence の振る舞いに影響を与えるものであれば、おっしゃるようにテストは必要だと思います。

設定の互換性

CqlSessionProvider の要求する必須設定項目が増えた場合に、現在の実装では CqlSessionProvider の呼び出しで例外が発生することになると思われます。

lerna-util-sequence が依存しているものよりも新しい Alpakka Cassandra を利用した akka-persistence-cassandra がリリースされ、ユーザーがその新しい akka-persistence-cassandra を使う可能性があることも検討に加えたほうが良いかもしれません。

akka-persistence-cassandra が依存する Alpakka Cassandra のバージョンで新しい設定項目が追加されている場合にランタイムエラーが発生する可能性があります。
このことについては次のような対処方法があるかなと思いました。

  1. Alpakka Cassandra の設定項目を継承して設定項目が追加されたとしても設定項目不足によるランタイムエラーが発生するのを回避する
  2. 設定項目に互換性のないバージョンを利用したときに発生するランタイムエラーはユーザー自身に解決してもらう
  3. ユーザーに lerna-util-sequence が依存する Alpakka Cassandra と同じバージョンの Alpakka Cassandra に依存した akka-persistence-cassandra を使ってもらう

そもそもは互換性の問題を回避するために Cassandra Driver ではなく、Alpakka Cassandra に依存することを選択したので、目的に反する 3 の選択肢は選ばないほうが良い気がしています。

1 はユーザーがランタイムエラーに遭遇する可能性を下げられますが、新しい設定項目のデフォルト値が lerna-util-sequence の振る舞いに悪影響を及ぼす可能性を完全には否定できません。

2 は新しい設定項目の読み込みが稀に行われるようなものだった場合、実運用に入ってからランタイムエラーに遭遇するかもしれないという点が気になります。不足している設定項目を起動直後にチェックして設定の追加をユーザーに促すなどすれば、この問題は軽減できそうです。

2 で事前チェックを行うのが安全性という点では良さそうですが、Alpakka Cassandra の新しい設定項目についてユーザーがどのような設定をすれば良いのか判断できるか不安があります。

この問題について何か追加のアイディアなどありますか?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xirc

ページをリロードせず投稿してしまっていたので、直前のコメント見落としてました。

提案頂いた設定項目の継承を調整して、次のように alpakka.cassandra へのパスを指定する方法も考えられそうです。

lerna.util.sequence.cassandra.* で設定項目が見つからなかった場合にフォールバックする設定項目へのパスを指定するということですね。

alpakka.cassandra = ${alpakka.cassandra} と書いた場合と、withFallback で他の設定項目をマージ(と表現して良いのかわからないですが)した場合の Config の見え方には違いがありそうでしょうか?
直感的には同じような見え方をしそうな気がしています。

ConfigFactory.defaultReference() などで読み込んだときの見え方を意識されているということでしょうか?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@negokaz
ありがとうございます。
コメントいただいた点についても検討が必要だと私も思いました。

Alpakka Cassandra の新しい設定項目についてユーザーがどのような設定をすれば良いのか判断できるか不安があります。

これについては、私にはアイディアはありません。
ドキュメントへのリンクを提供することはできるかもしれませんが、どの設定が使われるのかは、使用される Alpakka Cassandra のバージョンに大きく依存するように思いました。おそらくドキュメントを記載するにしても、「lerna-util-sequence が依存する Alpakka Cassandra と同じバージョンの Alpakka Cassandra に依存した Akka Persistence Cassandra を使ってください」と言及することになると予想しています。それ以外について動作保証をするのは難しいように思いました。

事前チェックについて

事前チェックを実施したい場合、例えば、Akka Management で使用できる Health checks • Akka Management を提供するのも良さそうだと思いました。その場合には、 lerna-util-sequence で HealthCheck 機能を提供するための実装が必要になるかもしれません。

設定のみを使って、事前チェックを厳密に行うのは難しいかもしれません。CqlSessionProvider (alpakka/CqlSessionProvider.scala at v2.0.2 · akka/alpakka) のソースコードを確認すると Akka Discovery を使う場合には CqlSessionProvider(...).connect() を呼び出すまで、設定が有効なものかどうかは確認することができないように読めました。恐らく、実際に CqlSession を確立するまでは、設定が有効かどうか判断することはできないかもしれません。これを踏まえて、Akka Management の ヘルスチェックを提供することを選択肢として挙げてみました。作業が多く必要そうなので実施するのは難しいかもしれません。

その他の方式案

例えば次のように、alpakka.cassandra の設定へのパスを指定するようにし、Apache Cassandra • Alpakka Documentation に記載のある CassandraSessionRegistry.get(system).sessionFor(sessionSettings) を使うようにします。これによって使われない設定というのはほぼ無くなるとは思いますし、設定の互換性を確保しやすいかもしれません。しかし、新しく alpakka.cassandra に追加された設定が、lerna-util-sequence に与える影響を推し量ることは依然として難しいとは思います。

実現するにはおそらくかなりの作業が必要そうなので選択肢としては難しいかもしれませんが、案としては考えられるため記録のためコメントに記載しておきます。Cassandra の Session のライフサイクルが変わるため、SequenceStore などの大幅な改修が必要そうだと予想しています。

defualt {
    alpakka-cassandra-config = "alpakka.cassandra"

    read-profile = "lerna-util-sequence-profile"
    // ... truncated
}

最後の選択肢

次のコミットを revert することで、依存関係には Alpakka Cassandra を使いつつも、DataStax Java Driver を直接使用することに比較的近い Alpakka Cassandra の API のみを使うように戻すという選択肢があります。これによって、Akka Discovery による Cassandra の contact-points 検出などの機能は使用できなくなりますが、設定互換性などの問題は回避できると思います。「DataStax Java Driver のメジャーバージョンアップを実施する」という当初の目的も達成できています。

Use akka.stream.alpakka.cassandra.SessionProvider instead 9efa34f

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@negokaz

私も見落としてしまいました 🙇

alpakka.cassandra = ${alpakka.cassandra} と書いた場合と、withFallback で他の設定項目をマージ(と表現して良いのかわからないですが)した場合の Config の見え方には違いがありそうでしょうか?
直感的には同じような見え方をしそうな気がしています。
ConfigFactory.defaultReference() などで読み込んだときの見え方を意識されているということでしょうか?

おっしゃる通り、プログラムから見える設定に違いはほぼないと思います。
(もしかすると厳密には少し違うかもしれません)
ユーザが IntelliJ などの IDE で設定ファイルを開いた際の補完候補に違いが生まれるかもしれません。
プログラムで withFallback すれば、 想定していない設定項目をユーザに表示しなくても済むかもしれません。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xirc

惜しいですが、「最後の選択肢」を使うのが現時点においては最良の選択のような気がしますね。

Alpakka Cassandra のほんの一部の機能しか使っていない経緯を後で追えるよう、CqlSessionProvider あたりのコメントにこのディスカッションへのリンクを残しておくのが良さそうな気がしました。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue #58 にしました。コードには issue #58 へのリンクを残しておきます。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@negokaz
対象 commit を revert し、 issue へのリンクを残しました。

Revert "Use akka.stream.alpakka.cassandra.SessionProvider instead" … 1696490
Add comments about considerations to use Alpakka's features … ed3ab0d

Taichi Yamakawa added 2 commits September 8, 2021 09:57
This reverts commit 9efa34f.
The commit has some considerations that we could not resolved.
#58
Copy link
Contributor

@negokaz negokaz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🎉

@negokaz negokaz enabled auto-merge September 8, 2021 02:48
@negokaz negokaz merged commit fdb3268 into main Sep 8, 2021
@negokaz negokaz deleted the upgrade-datastax-java-driver-to-4.13.0 branch September 8, 2021 02:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cassandra Driver (Datastax Java Driver) のメジャーバージョンアップ

2 participants