This is an automated email from the ASF dual-hosted git repository.
pjfanning pushed a commit to branch 1.3.x
in repository https://gitbox.apache.org/repos/asf/pekko-persistence-jdbc.git
The following commit(s) were added to refs/heads/1.3.x by this push:
new e79cba6f fix incorrect impl of Durable State deleteObject(id,
revision) (#482) (#505)
e79cba6f is described below
commit e79cba6f875890b585945a7f356dcf18325d604c
Author: PJ Fanning <[email protected]>
AuthorDate: Fri May 29 10:46:39 2026 +0100
fix incorrect impl of Durable State deleteObject(id, revision) (#482) (#505)
* test durable state store tck (#482)
* Copy DurableStateStore TCK base classes from apache/pekko#2833 and add
integration tests for all supported databases
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-persistence-jdbc/sessions/c3116ae6-042e-496b-b5bc-f480e95f7a01
Co-authored-by: pjfanning <[email protected]>
* Fix: remove sealed CapabilityFlags inheritance from
DurableStateStoreCapabilityFlags
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-persistence-jdbc/sessions/dcab8f13-0bc4-403e-afbd-d60bdaa2b03a
Co-authored-by: pjfanning <[email protected]>
* Fix Oracle TCK failures: use non-empty tag in DurableStateStoreSpec tests
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-persistence-jdbc/sessions/491c7f9d-e7f5-446b-8cac-cc96c7c17767
Co-authored-by: pjfanning <[email protected]>
* Bring over latest TCK changes from apache/pekko#2917
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-persistence-jdbc/sessions/b8ecac9c-455d-49ad-b6c1-7397780899da
Co-authored-by: pjfanning <[email protected]>
* use tck files from 2.0.0-M2 release
* Fix deleteObject revision semantics to match pekko 2.0.0-M2 TCK
Agent-Logs-Url:
https://github.com/pjfanning/incubator-pekko-persistence-jdbc/sessions/146149b4-03f1-4102-b987-773bc5eda38e
Co-authored-by: pjfanning <[email protected]>
* remove use of DeleteRevisionException
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
* add tck spec
* Update DurableStateStoreSpec.scala
* Update JdbcDurableStateStoreTCKSpec.scala
---------
Co-authored-by: copilot-swe-agent[bot]
<[email protected]>
Co-authored-by: pjfanning <[email protected]>
---
.../jdbc/state/DurableStateQueries.scala | 8 +-
.../scaladsl/DurableStateExceptionSupport.scala | 48 -----
.../state/scaladsl/JdbcDurableStateStore.scala | 25 ++-
.../state/scaladsl/DurableStateStoreSpec.scala | 214 +++++++++++++++++++++
.../jdbc/state/scaladsl/JdbcDurableStateSpec.scala | 28 ++-
.../scaladsl/JdbcDurableStateStoreTCKSpec.scala | 55 ++++++
.../integration/DurableStateStoreTCKSpec.scala | 52 +++++
7 files changed, 370 insertions(+), 60 deletions(-)
diff --git
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/DurableStateQueries.scala
b/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/DurableStateQueries.scala
index b4346100..86bfabad 100644
---
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/DurableStateQueries.scala
+++
b/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/DurableStateQueries.scala
@@ -115,13 +115,15 @@ import slick.jdbc.{
}
/**
- * Deletes a particular revision of an object based on its persistenceId.
- * This revision may no longer exist and if so, no delete will occur.
+ * Deletes the row for a given persistenceId whose revision equals `revision
- 1`.
+ * Following the same "next-revision" convention as `upsertObject`, the
caller passes
+ * the tombstone revision (= current stored revision + 1), so we delete the
row
+ * where `storedRevision = passedRevision - 1`.
*
* @since 1.1.0
*/
private[jdbc] def deleteBasedOnPersistenceIdAndRevision(persistenceId:
String, revision: Long) = {
- selectFromDbByPersistenceId(persistenceId).filter(_.revision ===
revision).delete
+ selectFromDbByPersistenceId(persistenceId).filter(_.revision === revision
- 1L).delete
}
def deleteAllFromDb() = {
diff --git
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateExceptionSupport.scala
b/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateExceptionSupport.scala
deleted file mode 100644
index 88e19316..00000000
---
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateExceptionSupport.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.pekko.persistence.jdbc.state.scaladsl
-
-import java.lang.invoke.{ MethodHandles, MethodType }
-
-import scala.util.Try
-
-/**
- * INTERNAL API
- *
- * Support for creating a `DeleteRevisionException`if the class is
- * available on the classpath. Pekko 1.0 does not have this class, but
- * it is added in Pekko 1.1.
- */
-private[scaladsl] object DurableStateExceptionSupport {
- val DeleteRevisionExceptionClass =
- "org.apache.pekko.persistence.state.exception.DeleteRevisionException"
-
- private def exceptionClassOpt: Option[Class[_]] =
- Try(Class.forName(DeleteRevisionExceptionClass)).toOption
-
- private val constructorOpt = exceptionClassOpt.map { clz =>
- val mt = MethodType.methodType(classOf[Unit], classOf[String])
- MethodHandles.publicLookup().findConstructor(clz, mt)
- }
-
- def createDeleteRevisionExceptionIfSupported(message: String):
Option[Exception] =
- constructorOpt.map { constructor =>
- constructor.invoke(message).asInstanceOf[Exception]
- }
-
-}
diff --git
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStore.scala
b/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStore.scala
index ca05b084..3f5585db 100644
---
a/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStore.scala
+++
b/core/src/main/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStore.scala
@@ -102,7 +102,24 @@ class JdbcDurableStateStore[A](
Future
.fromTry(row)
.flatMap { r =>
- val action = if (revision == 1) insertDurableState(r) else
updateDurableState(r)
+ val action = if (revision == 1) insertDurableState(r)
+ else {
+ // Try UPDATE first (entity exists at revision - 1). If 0 rows are
affected, the
+ // entity may have been deleted (no row at all) rather than having a
stale revision.
+ // In that case fall back to INSERT so that re-creation after
deletion works.
+ for {
+ s <- queries.getSequenceNextValueExpr()
+ u <- queries.updateDbWithDurableState(r, s.head)
+ result <-
+ if (u > 0) DBIO.successful(u)
+ else {
+
queries.selectFromDbByPersistenceId(persistenceId).exists.result.flatMap {
exists =>
+ if (!exists) queries.insertDbWithDurableState(r, s.head)
+ else DBIO.successful(0) // entity exists with wrong revision
-> propagate 0 to throw below
+ }
+ }
+ } yield result
+ }
db.run(action)
}
.map { rowsAffected =>
@@ -119,16 +136,12 @@ class JdbcDurableStateStore[A](
override def deleteObject(persistenceId: String, revision: Long):
Future[Done] =
db.run(queries.deleteBasedOnPersistenceIdAndRevision(persistenceId,
revision)).map { count =>
if (count != 1) {
- // if you run this code with Pekko 1.0.x, no exception will be thrown
here
- // this matches the behavior of pekko-connectors-jdbc 1.0.x
- // if you run this code with Pekko 1.1.x, a DeleteRevisionException
will be thrown here
val msg = if (count == 0) {
s"Failed to delete object with persistenceId [$persistenceId] and
revision [$revision]"
} else {
s"Delete object succeeded for persistenceId [$persistenceId] and
revision [$revision] but more than one row was affected ($count rows)"
}
-
DurableStateExceptionSupport.createDeleteRevisionExceptionIfSupported(msg)
- .foreach(throw _)
+ throw new IllegalStateException(msg)
}
Done
}(ExecutionContexts.parasitic)
diff --git
a/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateStoreSpec.scala
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateStoreSpec.scala
new file mode 100644
index 00000000..557c6a6b
--- /dev/null
+++
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/DurableStateStoreSpec.scala
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * license agreements; and to You under the Apache License, version 2.0:
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * This file is part of the Apache Pekko project, which was derived from Akka.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Lightbend Inc. <https://www.lightbend.com>
+ */
+
+package org.apache.pekko.persistence.jdbc.state.scaladsl
+
+import scala.annotation.nowarn
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import org.apache.pekko
+import pekko.actor.ActorSystem
+import pekko.persistence._
+import pekko.persistence.scalatest.{ MayVerb, OptionalTests }
+import pekko.persistence.state.DurableStateStoreRegistry
+import pekko.persistence.state.scaladsl.DurableStateUpdateStore
+import pekko.testkit.TestProbe
+
+import com.typesafe.config.Config
+import com.typesafe.config.ConfigFactory
+
+object DurableStateStoreSpec {
+ val config: Config = ConfigFactory.parseString(s"""
+ pekko.actor {
+ serializers {
+ durable-state-tck-test = "${classOf[TestSerializer].getName}"
+ }
+ serialization-bindings {
+ "${classOf[TestPayload].getName}" = durable-state-tck-test
+ }
+ }
+ """)
+}
+
+/**
+ * This spec aims to verify custom pekko-persistence [[DurableStateStore]]
implementations.
+ * Plugin authors are highly encouraged to include it in their plugin's test
suites.
+ *
+ * In case your durable state store plugin needs some kind of setup or
teardown, override the `beforeAll`
+ * or `afterAll` methods (don't forget to call `super` in your overridden
methods).
+ *
+ * This is a copy of the TCK spec added in Pekko 2.0.0.
+ *
https://github.com/apache/pekko/blob/4f20b4736980a5d57bc58e1356fea4dede87a7cd/persistence-tck/src/main/scala/org/apache/pekko/persistence/state/DurableStateStoreSpec.scala
+ */
+abstract class DurableStateStoreSpec(config: Config)
+ extends PluginSpec(config)
+ with MayVerb
+ with OptionalTests {
+
+ implicit lazy val system: ActorSystem =
+ ActorSystem("DurableStateStoreSpec",
config.withFallback(DurableStateStoreSpec.config))
+
+ protected def supportsDeleteWithRevisionCheck: CapabilityFlag =
CapabilityFlag.off()
+
+ protected def supportsUpsertWithRevisionCheck: CapabilityFlag =
CapabilityFlag.off()
+
+ protected def supportsSerialization: CapabilityFlag = CapabilityFlag.on()
+
+ protected def supportsSoftDelete: CapabilityFlag = CapabilityFlag.off()
+
+ override protected def beforeEach(): Unit = {
+ super.beforeEach()
+ preparePersistenceId(pid)
+ }
+
+ /**
+ * Overridable hook that is called before each test case.
+ * `pid` is the `persistenceId` that will be used in the test.
+ * This method may be needed to clean any pre-existing state from the store,
+ * for example when running against a shared external database.
+ */
+ def preparePersistenceId(@nowarn("msg=never used") pid: String): Unit = ()
+
+ /**
+ * Returns the `DurableStateUpdateStore` under test. By default, this uses
the plugin
+ * configured under `pekko.persistence.state.plugin` in the provided config.
+ */
+ def durableStateStore(): DurableStateUpdateStore[Any] =
+
DurableStateStoreRegistry(system).durableStateStoreFor[DurableStateUpdateStore[Any]]("")
+
+ protected val timeout: FiniteDuration = 5.seconds
+
+ "A durable state store" must {
+ "not find a non-existing object" in {
+ val result = Await.result(durableStateStore().getObject(pid), timeout)
+ result.value shouldBe None
+ }
+
+ "persist a state and retrieve it" in {
+ val value = s"state-${pid}"
+ Await.result(durableStateStore().upsertObject(pid, 1L, value,
"test-tag"), timeout)
+ val result = Await.result(durableStateStore().getObject(pid), timeout)
+ result.value shouldBe Some(value)
+ result.revision shouldBe 1L
+ }
+
+ "update a state" in {
+ val store = durableStateStore()
+ val value1 = s"state-1-${pid}"
+ val value2 = s"state-2-${pid}"
+ Await.result(store.upsertObject(pid, 1L, value1, "test-tag"), timeout)
+ Await.result(store.upsertObject(pid, 2L, value2, "test-tag"), timeout)
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe Some(value2)
+ result.revision shouldBe 2L
+ }
+
+ "delete a state" in {
+ val store = durableStateStore()
+ val value = s"state-${pid}"
+ Await.result(store.upsertObject(pid, 1L, value, "test-tag"), timeout)
+ Await.result(store.deleteObject(pid, 2L), timeout)
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe None
+ }
+
+ "handle different persistence IDs independently" in {
+ val store = durableStateStore()
+ val pid2 = pid + "-2"
+ val value1 = s"state-${pid}"
+ val value2 = s"state-${pid2}"
+ Await.result(store.upsertObject(pid, 1L, value1, "test-tag"), timeout)
+ Await.result(store.upsertObject(pid2, 1L, value2, "test-tag"), timeout)
+
+ val result1 = Await.result(store.getObject(pid), timeout)
+ val result2 = Await.result(store.getObject(pid2), timeout)
+
+ result1.value shouldBe Some(value1)
+ result2.value shouldBe Some(value2)
+ }
+
+ "upsert again after a deletion" in {
+ val store = durableStateStore()
+ val original = s"state-${pid}"
+ val recreated = s"state-${pid}-v2"
+ Await.result(store.upsertObject(pid, 1L, original, "test-tag"), timeout)
+ Await.result(store.deleteObject(pid, 2L), timeout)
+ Await.result(store.upsertObject(pid, 3L, recreated, "test-tag"), timeout)
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe Some(recreated)
+ result.revision shouldBe 3L
+ }
+ }
+
+ "A durable state store optionally".may {
+ optional(flag = supportsDeleteWithRevisionCheck) {
+ "fail to delete a state when the revision does not match" in {
+ val store = durableStateStore()
+ val value = s"state-${pid}"
+ Await.result(store.upsertObject(pid, 1L, value, "test-tag"), timeout)
+ val deleteResult = store.deleteObject(pid, 99L)
+ intercept[Exception] {
+ Await.result(deleteResult, timeout)
+ }
+ // The original state should still be accessible
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe Some(value)
+ result.revision shouldBe 1L
+ }
+ }
+
+ optional(flag = supportsUpsertWithRevisionCheck) {
+ "fail to upsert a state when the revision is stale" in {
+ val store = durableStateStore()
+ val original = s"state-${pid}"
+ val stale = s"state-${pid}-stale"
+ Await.result(store.upsertObject(pid, 1L, original, "test-tag"),
timeout)
+ // Re-using revision 1 should be rejected; the next valid revision is
2.
+ val staleUpsert = store.upsertObject(pid, 1L, stale, "test-tag")
+ intercept[Exception] {
+ Await.result(staleUpsert, timeout)
+ }
+ // The original state should still be accessible
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe Some(original)
+ result.revision shouldBe 1L
+ }
+ }
+
+ optional(flag = supportsSerialization) {
+ "serialize and deserialize values via the configured serializer" in {
+ val store = durableStateStore()
+ val probe = TestProbe()
+ val value = TestPayload(probe.ref)
+ Await.result(store.upsertObject(pid, 1L, value, "test-tag"), timeout)
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe Some(value)
+ result.revision shouldBe 1L
+ }
+ }
+
+ optional(flag = supportsSoftDelete) {
+ "delete a state via the deprecated deleteObject overload" in {
+ val store = durableStateStore()
+ val value = s"state-${pid}"
+ Await.result(store.upsertObject(pid, 1L, value, "test-tag"), timeout)
+ @nowarn("cat=deprecation")
+ val deleteResult = store.deleteObject(pid)
+ Await.result(deleteResult, timeout)
+ val result = Await.result(store.getObject(pid), timeout)
+ result.value shouldBe None
+ }
+ }
+ }
+}
diff --git
a/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateSpec.scala
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateSpec.scala
index 119b1e84..06387528 100644
---
a/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateSpec.scala
+++
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateSpec.scala
@@ -121,7 +121,7 @@ abstract class JdbcDurableStateSpec(config: Config,
schemaType: SchemaType) exte
}
}
}
- "fail to delete old object revision" in {
+ "fail to delete with old object revision" in {
val f = for {
n <- stateStoreString.upsertObject("p987", 1, "a valid string", "t123")
_ = n shouldBe pekko.Done
@@ -137,7 +137,7 @@ abstract class JdbcDurableStateSpec(config: Config,
schemaType: SchemaType) exte
}
} else {
whenReady(f.failed) { e =>
- e.getClass.getName shouldEqual
DurableStateExceptionSupport.DeleteRevisionExceptionClass
+ e.getClass shouldEqual classOf[IllegalStateException]
e.getMessage should include("Failed to delete object with
persistenceId [p987] and revision [1]")
}
}
@@ -152,7 +152,9 @@ abstract class JdbcDurableStateSpec(config: Config,
schemaType: SchemaType) exte
_ = g.value shouldBe Some("a valid string")
u <- stateStoreString.upsertObject("p9876", 2, "updated valid
string", "t123")
_ = u shouldBe pekko.Done
- d <- stateStoreString.deleteObject("p9876", 2)
+ // revision 3 = current stored revision (2) + 1, following the same
tombstone-revision
+ // convention used by upsertObject and the pekko-persistence TCK
+ d <- stateStoreString.deleteObject("p9876", 3)
_ = d shouldBe pekko.Done
h <- stateStoreString.getObject("p9876")
@@ -162,6 +164,26 @@ abstract class JdbcDurableStateSpec(config: Config,
schemaType: SchemaType) exte
v.value shouldBe None
}
}
+ "upsert again after deletion" in {
+ whenReady {
+ for {
+ n <- stateStoreString.upsertObject("p11111", 1, "original string",
"t123")
+ _ = n shouldBe pekko.Done
+ // tombstone revision = current stored revision (1) + 1 = 2
+ d <- stateStoreString.deleteObject("p11111", 2)
+ _ = d shouldBe pekko.Done
+ g <- stateStoreString.getObject("p11111")
+ _ = g.value shouldBe None
+ // re-insert: revision = tombstone revision (2) + 1 = 3
+ u <- stateStoreString.upsertObject("p11111", 3, "recreated string",
"t123")
+ _ = u shouldBe pekko.Done
+ h <- stateStoreString.getObject("p11111")
+ } yield h
+ } { v =>
+ v.value shouldBe Some("recreated string")
+ v.revision shouldBe 3L
+ }
+ }
}
"A durable state store with payload that needs custom serializer" must
withActorSystem { implicit system =>
diff --git
a/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStoreTCKSpec.scala
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStoreTCKSpec.scala
new file mode 100644
index 00000000..090394f7
--- /dev/null
+++
b/core/src/test/scala/org/apache/pekko/persistence/jdbc/state/scaladsl/JdbcDurableStateStoreTCKSpec.scala
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * license agreements; and to You under the Apache License, version 2.0:
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * This file is part of the Apache Pekko project, which was derived from Akka.
+ */
+
+package org.apache.pekko.persistence.jdbc.state.scaladsl
+
+import com.typesafe.config.Config
+import org.apache.pekko
+import pekko.persistence.CapabilityFlag
+import pekko.persistence.jdbc.config.SlickConfiguration
+import pekko.persistence.jdbc.db.SlickDatabase
+import pekko.persistence.jdbc.testkit.internal.SchemaType
+import pekko.persistence.jdbc.util.DropCreate
+import org.scalatest.BeforeAndAfterAll
+
+abstract class JdbcDurableStateStoreTCKSpec(config: Config, schemaType:
SchemaType)
+ extends DurableStateStoreSpec(config)
+ with BeforeAndAfterAll
+ with DropCreate {
+
+ override protected def supportsDeleteWithRevisionCheck: CapabilityFlag =
CapabilityFlag.on()
+
+ override protected def supportsUpsertWithRevisionCheck: CapabilityFlag =
CapabilityFlag.on()
+
+ override protected def supportsSerialization: CapabilityFlag =
CapabilityFlag.on()
+
+ override protected def supportsSoftDelete: CapabilityFlag =
CapabilityFlag.on()
+
+ lazy val db = {
+ val cfg = config.getConfig("jdbc-durable-state-store")
+ if (cfg.hasPath("slick.profile")) {
+ SlickDatabase.database(cfg, new
SlickConfiguration(cfg.getConfig("slick")), "slick.db")
+ } else {
+ SlickDatabase.database(
+ config,
+ new
SlickConfiguration(config.getConfig("pekko-persistence-jdbc.shared-databases.slick")),
+ "pekko-persistence-jdbc.shared-databases.slick.db")
+ }
+ }
+
+ override def beforeAll(): Unit = {
+ dropAndCreate(schemaType)
+ super.beforeAll()
+ }
+
+ override def afterAll(): Unit = {
+ super.afterAll()
+ db.close()
+ }
+}
diff --git
a/integration-test/src/test/scala/org/apache/pekko/persistence/jdbc/integration/DurableStateStoreTCKSpec.scala
b/integration-test/src/test/scala/org/apache/pekko/persistence/jdbc/integration/DurableStateStoreTCKSpec.scala
new file mode 100644
index 00000000..e113e634
--- /dev/null
+++
b/integration-test/src/test/scala/org/apache/pekko/persistence/jdbc/integration/DurableStateStoreTCKSpec.scala
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * license agreements; and to You under the Apache License, version 2.0:
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * This file is part of the Apache Pekko project, which was derived from Akka.
+ */
+
+package org.apache.pekko.persistence.jdbc.integration
+
+import com.typesafe.config.ConfigFactory
+import
org.apache.pekko.persistence.jdbc.state.scaladsl.JdbcDurableStateStoreTCKSpec
+import org.apache.pekko.persistence.jdbc.testkit.internal.{ MariaDB, MySQL,
Oracle, Postgres, SqlServer }
+
+// postgres-application.conf already includes pekko.persistence.state.plugin =
"jdbc-durable-state-store"
+class PostgresDurableStateStoreTCKSpec
+ extends
JdbcDurableStateStoreTCKSpec(ConfigFactory.load("postgres-application.conf"),
Postgres)
+
+// mariadb-application.conf already includes pekko.persistence.state.plugin =
"jdbc-durable-state-store"
+class MariaDBDurableStateStoreTCKSpec
+ extends
JdbcDurableStateStoreTCKSpec(ConfigFactory.load("mariadb-application.conf"),
MariaDB)
+
+object MySQLDurableStateStoreTCKSpec {
+ // mysql-application.conf does not configure the durable state plugin, so
add it here
+ val config = ConfigFactory
+ .parseString("""pekko.persistence.state.plugin =
"jdbc-durable-state-store"""")
+ .withFallback(ConfigFactory.load("mysql-application.conf"))
+}
+
+class MySQLDurableStateStoreTCKSpec
+ extends JdbcDurableStateStoreTCKSpec(MySQLDurableStateStoreTCKSpec.config,
MySQL)
+
+object OracleDurableStateStoreTCKSpec {
+ // oracle-application.conf does not configure the durable state plugin, so
add it here
+ val config = ConfigFactory
+ .parseString("""pekko.persistence.state.plugin =
"jdbc-durable-state-store"""")
+ .withFallback(ConfigFactory.load("oracle-application.conf"))
+}
+
+class OracleDurableStateStoreTCKSpec
+ extends
JdbcDurableStateStoreTCKSpec(OracleDurableStateStoreTCKSpec.config, Oracle)
+
+object SqlServerDurableStateStoreTCKSpec {
+ // sqlserver-application.conf does not configure the durable state plugin,
so add it here
+ val config = ConfigFactory
+ .parseString("""pekko.persistence.state.plugin =
"jdbc-durable-state-store"""")
+ .withFallback(ConfigFactory.load("sqlserver-application.conf"))
+}
+
+class SqlServerDurableStateStoreTCKSpec
+ extends
JdbcDurableStateStoreTCKSpec(SqlServerDurableStateStoreTCKSpec.config,
SqlServer)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]