Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SQL Server #200

Merged
merged 1 commit into from
Sep 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ services:
- postgresql
- docker
before_install:
# - docker pull mysql
# - docker run --name mysql -d -p 127.0.0.1:3306:3306 -e MYSQL_ROOT_PASSWORD=root mysql
# - docker inspect mysql
- docker pull alexeiled/docker-oracle-xe-11g
- docker pull topaztechnology/mssql-server-linux
- docker run --name oracle -d -p 127.0.0.1:1521:1521 -e ORACLE_ALLOW_REMOTE=true alexeiled/docker-oracle-xe-11g
- docker run --name sqlserver -d -p 127.0.0.1:1433:1433 -e DBCA_TOTAL_MEMORY=1024 -e ACCEPT_EULA=Y -e SQL_USER=docker -e SQL_PASSWORD=docker -e SQL_DB=docker topaztechnology/mssql-server-linux
- docker inspect oracle
- docker inspect sqlserver
- docker ps -a
scala:
- 2.11.12
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ Configure `slick`:
- `slick.jdbc.MySQLProfile$`
- `slick.jdbc.H2Profile$`
- `slick.jdbc.OracleProfile$`
- `slick.jdbc.SQLServerProfile$`

## Database Schema

- [Postgres Schema](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/schema/postgres/postgres-schema.sql)
- [MySQL Schema](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/schema/mysql/mysql-schema.sql)
- [H2 Schema](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/schema/h2/h2-schema.sql)
- [Oracle Schema](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/schema/oracle/oracle-schema.sql)
- [SQL Server Schema](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/schema/sqlserver/sqlserver-schema.sql)

## Configuration

Expand All @@ -80,6 +82,7 @@ configuration shows how this is configured:
- [MySQL](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/mysql-application.conf)
- [H2](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/h2-application.conf)
- [Oracle](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/oracle-application.conf)
- [SQL Server](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/sqlserver-application.conf)

### Sharing the database connection pool between the journals

Expand All @@ -89,6 +92,7 @@ In order to create only one connection pool which is shared between all journals
- [MySQL](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/mysql-shared-db-application.conf)
- [H2](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/h2-shared-db-application.conf)
- [Oracle](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/oracle-shared-db-application.conf)
- [SQL Server](https://github.com/dnvriend/akka-persistence-jdbc/blob/master/src/test/resources/sqlserver-shared-db-application.conf)

### Customized loading of the db connection

Expand Down
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ done;
}
rm ./bintray.sbt

wait 5432 PostgreSQL
Copy link
Member

Choose a reason for hiding this comment

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

hmm, PostgreSQL was not included by default?

wait 3306 MySQL
wait 1521 Oracle
wait 1433 SqlSever

sbt test
1 change: 1 addition & 0 deletions project/ProjectAutoPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ object ProjectAutoPlugin extends AutoPlugin {
libraryDependencies += "org.postgresql" % "postgresql" % "42.2.5" % Test,
libraryDependencies += "com.h2database" % "h2" % "1.4.197" % Test,
libraryDependencies += "mysql" % "mysql-connector-java" % "8.0.12" % Test,
libraryDependencies += "com.microsoft.sqlserver" % "mssql-jdbc" % "7.0.0.jre8" % Test,
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3" % Test,
libraryDependencies += "com.typesafe.akka" %% "akka-slf4j" % AkkaVersion % Test,
libraryDependencies += "com.typesafe.akka" %% "akka-persistence-tck" % AkkaVersion % Test,
Expand Down
13 changes: 13 additions & 0 deletions scripts/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,16 @@ oracle:
- "DBCA_TOTAL_MEMORY=1024"
ports:
- "1521:1521" # DB_CONN: credentials (system:oracle)

sqlserver:
image: topaztechnology/mssql-server-linux
container_name: sqlserver-test
environment:
- "TZ=Europe/Amsterdam"
- "DBCA_TOTAL_MEMORY=1024"
- "ACCEPT_EULA=Y"
- "SQL_USER=docker"
- "SQL_PASSWORD=docker"
- "SQL_DB=docker"
ports:
- "1433:1433" # credentials (docker:docker)
1 change: 1 addition & 0 deletions scripts/launch-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ docker-compose -f scripts/docker-compose.yml up -d
wait 3306 MySQL
wait 5432 Postgres
wait 1521 Oracle
wait 1433 SqlServer
37 changes: 37 additions & 0 deletions scripts/launch-sqlserver.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# Copyright 2016 Dennis Vriend
#
# Licensed 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.
#
#!/bin/bash
export VM_HOST="${VM_HOST:-localhost}"

# Wait for a certain service to become available
# Usage: wait 1433 SqlServer
wait() {
while true; do
if ! nc -z $VM_HOST $1
then
echo "$2 not available, retrying..."
sleep 1
else
echo "$2 is available"
break;
fi
done;
}

docker-compose -f scripts/sqlserver.yml kill
docker-compose -f scripts/sqlserver.yml rm -f
docker-compose -f scripts/sqlserver.yml up -d
wait 1433 SqlServer
4 changes: 4 additions & 0 deletions scripts/sqlserver-cli.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
echo "================== Help for SqlServer cli ========================"
echo "================================================================="
docker exec -it sqlserver /opt/mssql-tools/bin/sqlcmd -S localhost -U docker -P docker -d docker
12 changes: 12 additions & 0 deletions scripts/sqlserver.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
sqlserver:
image: topaztechnology/mssql-server-linux
container_name: sqlserver
environment:
- "TZ=Europe/Amsterdam"
- "DBCA_TOTAL_MEMORY=1024"
- "ACCEPT_EULA=Y"
- "SQL_USER=docker"
- "SQL_PASSWORD=docker"
- "SQL_DB=docker"
ports:
- "1433:1433" # credentials (docker:docker)
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package akka.persistence.jdbc
package journal.dao

import java.io.NotSerializableException

import akka.{ Done, NotUsed }
import akka.persistence.jdbc.config.JournalConfig
import akka.persistence.jdbc.serialization.FlowPersistentReprSerializer
Expand All @@ -28,7 +26,7 @@ import akka.stream.scaladsl.{ Keep, Sink, Source }
import akka.stream.{ Materializer, OverflowStrategy, QueueOfferResult }
import org.slf4j.LoggerFactory
import slick.jdbc.JdbcBackend._
import slick.jdbc.JdbcProfile
import slick.jdbc.{ JdbcProfile, H2Profile }

import scala.collection.immutable._
import scala.concurrent.{ ExecutionContext, Future, Promise }
Expand Down Expand Up @@ -86,9 +84,14 @@ trait BaseByteArrayJournalDao extends JournalDaoWithUpdates {
}
}

private def writeJournalRows(xs: Seq[JournalRow]): Future[Unit] = for {
_ <- db.run(queries.writeJournalRows(xs))
} yield ()
private def writeJournalRows(xs: Seq[JournalRow]): Future[Unit] = {
if (slickProfile != H2Profile)
// Write atomically without auto-commit
db.run(queries.writeJournalRows(xs).transactionally).map(_ => Unit)
else
// However transactionally causes H2 tests to fail
db.run(queries.writeJournalRows(xs)).map(_ => Unit)
Copy link
Member

Choose a reason for hiding this comment

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

Why H2 is failing when using transactionally? That's not normal.

Copy link
Member

Choose a reason for hiding this comment

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

I forgot I had added this comment and merge it.

In any case, I don't think we are doing any harm here. Actually, I run this locally without the if/else and calling transactionally. All H2 tests passed.

Moreover, we don't need it transactionally because we have only one DBIO. transactionally is only needed when we have many DBIOs and we want to run them all together in the same tx. That's not the case here. Here we have one DBIO with many row inserts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes the test failures were intermittent. Locally I also didn't have a problem, but maybe the Travis hardware was lower spec and caused the circuit breaker to time out. It's also not clear why this would reduce performance in H2 in the first place.

With regards to not requiring transactionally, it certainly made a significant difference to SQL Server performance. It's calling JournalTableC ++= xs.sortBy(_.sequenceNumber) but I have no idea how Slick handles this internally.

}

/**
* @see [[akka.persistence.journal.AsyncWriteJournal.asyncWriteMessages(messages)]]
Expand Down
23 changes: 23 additions & 0 deletions src/test/resources/schema/sqlserver/sqlserver-schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
DROP TABLE IF EXISTS journal;

CREATE TABLE journal (
"ordering" BIGINT IDENTITY(1,1) NOT NULL,
"deleted" BIT NULL DEFAULT 0,
"persistence_id" VARCHAR(255) NOT NULL,
"sequence_number" NUMERIC(10,0) NOT NULL,
"tags" VARCHAR(255) NULL DEFAULT NULL,
"message" VARBINARY(max) NOT NULL,
PRIMARY KEY ("persistence_id", "sequence_number")
);

CREATE UNIQUE INDEX journal_ordering_idx ON journal (ordering);

DROP TABLE IF EXISTS snapshot;

CREATE TABLE snapshot (
"persistence_id" VARCHAR(255) NOT NULL,
"sequence_number" NUMERIC(10,0) NOT NULL,
"created" NUMERIC NOT NULL,
"snapshot" VARBINARY(max) NOT NULL,
PRIMARY KEY ("persistence_id", "sequence_number")
);
19 changes: 19 additions & 0 deletions src/test/resources/sqlserver-application-with-hard-delete.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2016 Dennis Vriend
#
# Licensed 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.

// general.conf is included only for shared settings used for the akka-persistence-jdbc tests
include "general.conf"
include "sqlserver-application.conf"

akka-persistence-jdbc.logicalDeletion.enable = false
84 changes: 84 additions & 0 deletions src/test/resources/sqlserver-application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright 2016 Dennis Vriend
#
# Licensed 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.

include "general.conf"

akka {
persistence {
journal {
plugin = "jdbc-journal"
// Enable the line below to automatically start the journal when the actorsystem is started
// auto-start-journals = ["jdbc-journal"]
}
snapshot-store {
plugin = "jdbc-snapshot-store"
// Enable the line below to automatically start the snapshot-store when the actorsystem is started
// auto-start-snapshot-stores = ["jdbc-snapshot-store"]
}
}
}

jdbc-journal {
tables {
journal {
tableName = "journal"
schemaName = "dbo"
}
}

slick = ${slick}
}

# the akka-persistence-snapshot-store in use
jdbc-snapshot-store {
tables {
snapshot {
tableName = "snapshot"
schemaName = "dbo"
}
}

slick = ${slick}
}

# the akka-persistence-query provider in use
jdbc-read-journal {
tables {
journal {
tableName = "journal"
schemaName = "dbo"
}
}

slick = ${slick}
}

slick {
profile = "slick.jdbc.SQLServerProfile$"
db {
host = ${docker.host}
host = ${?SQLSERVER_HOST}
port = "1433"
port = ${?SQLSERVER_PORT}
url = "jdbc:sqlserver://"${slick.db.host}":"${slick.db.port}";databaseName=docker;integratedSecurity=false"
user = "docker"
user = ${?SQLSERVER_USER}
password = "docker"
password = ${?SQLSERVER_PASSWORD}
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
numThreads = 5
maxConnections = 5
minConnections = 1
}
}
67 changes: 67 additions & 0 deletions src/test/resources/sqlserver-shared-db-application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright 2016 Dennis Vriend
#
# Licensed 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.

include "general.conf"

akka {
persistence {
journal {
plugin = "jdbc-journal"
// Enable the line below to automatically start the journal when the actorsystem is started
// auto-start-journals = ["jdbc-journal"]
}
snapshot-store {
plugin = "jdbc-snapshot-store"
// Enable the line below to automatically start the snapshot-store when the actorsystem is started
// auto-start-snapshot-stores = ["jdbc-snapshot-store"]
}
}
}

akka-persistence-jdbc {
shared-databases {
slick {
profile = "slick.jdbc.SQLServerProfile$"
db {
host = ${docker.host}
host = ${?SQLSERVER_HOST}
url = "jdbc:sqlserver://"${akka-persistence-jdbc.shared-databases.slick.db.host}":1433;databaseName=docker;integratedSecurity=false;"
user = "docker"
user = ${?SQLSERVER_USER}
// This password needs to include at least 8 characters of at least three of these four categories:
// uppercase letters, lowercase letters, numbers and non-alphanumeric symbols.
password = "docker"
password = ${?SQLSERVER_PASSWORD}
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
numThreads = 5
maxConnections = 5
minConnections = 1
}
}
}
}

jdbc-journal {
use-shared-db = "slick"
}

# the akka-persistence-snapshot-store in use
jdbc-snapshot-store {
use-shared-db = "slick"
}

# the akka-persistence-query provider in use
jdbc-read-journal {
use-shared-db = "slick"
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,20 @@ class OracleJournalPerfSpecPhysicalDelete extends OracleJournalPerfSpec {
this.cfg.withValue("jdbc-journal.logicalDelete", ConfigValueFactory.fromAnyRef(false))
}

class SqlServerJournalPerfSpec extends JdbcJournalPerfSpec(ConfigFactory.load("sqlserver-application.conf"), SqlServer()) {
override def eventsCount: Int = 100
}

class SqlServerJournalPerfSpecSharedDb extends JdbcJournalPerfSpec(ConfigFactory.load("sqlserver-shared-db-application.conf"), SqlServer()) {
override def eventsCount: Int = 100
}

class SqlServerJournalPerfSpecPhysicalDelete extends SqlServerJournalPerfSpec {
this.cfg.withValue("jdbc-journal.logicalDelete", ConfigValueFactory.fromAnyRef(false))
}

class H2JournalPerfSpec extends JdbcJournalPerfSpec(ConfigFactory.load("h2-application.conf"), H2())

class H2JournalPerfSpecSharedDb extends JdbcJournalPerfSpec(ConfigFactory.load("h2-shared-db-application.conf"), H2())

class H2JournalPerfSpecPhysicalDelete extends H2JournalPerfSpec {
Expand Down
Loading