diff --git a/.travis.yml b/.travis.yml index 2c1a7a84..3e334f1a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,11 @@ language: scala scala: - 2.10.4 - 2.11.7 + - 2.12.1 + jdk: - - oraclejdk7 - oraclejdk8 + services: - postgresql - mysql diff --git a/CHANGELOG.md b/CHANGELOG.md index bafc831d..ce4b61ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,11 @@ # Changelog +## 0.2.20 - 2017-09-17 + +* Building for Scala 2.12; +* Fix SFL4J deprecation warning - #201 - @golem131; + ## 0.2.19 - 2016-03-17 * Always use `NUMERIC` when handling numbers in prepared statements in PostgreSQL; diff --git a/README.markdown b/README.markdown index 9977b309..79f4b057 100644 --- a/README.markdown +++ b/README.markdown @@ -1,7 +1,7 @@ -- [[![Build Status](https://travis-ci.org/mauricio/postgresql-async.png)](https://travis-ci.org/mauricio/postgresql-async) postgresql-async & mysql-async - async, Netty based, database drivers for MySQL and PostgreSQL written in Scala 2.10 and 2.11](#!build-statushttpstravis-ciorgmauriciopostgresql-asyncpnghttpstravis-ciorgmauriciopostgresql-async-postgresql-async-&-mysql-async---async-netty-based-database-drivers-for-mysql-and-postgresql-written-in-scala-210-and-211) +- This project is not being maintained anymore, feel free to fork and work on it - [Abstractions and integrations](#abstractions-and-integrations) - [Include them as dependencies](#include-them-as-dependencies) - [Database connections and encodings](#database-connections-and-encodings) @@ -22,7 +22,7 @@ -# [![Build Status](https://travis-ci.org/mauricio/postgresql-async.png)](https://travis-ci.org/mauricio/postgresql-async) postgresql-async & mysql-async - async, Netty based, database drivers for MySQL and PostgreSQL written in Scala 2.10 and 2.11 +# [![Build Status](https://travis-ci.org/mauricio/postgresql-async.png)](https://travis-ci.org/mauricio/postgresql-async) This project is not being maintained anymore, feel free to fork and work on it The main goal for this project is to implement simple, async, performant and reliable database drivers for PostgreSQL and MySQL in Scala. This is not supposed to be a JDBC replacement, these drivers aim to cover the common @@ -54,7 +54,7 @@ You can view the project's [CHANGELOG here](CHANGELOG.md). And if you're in a hurry, you can include them in your build like this, if you're using PostgreSQL: ```scala -"com.github.mauricio" %% "postgresql-async" % "0.2.20" +"com.github.mauricio" %% "postgresql-async" % "0.2.21" ``` Or Maven: @@ -63,14 +63,23 @@ Or Maven: com.github.mauricio postgresql-async_2.11 - 0.2.20 + 0.2.21 + +``` + +respectively for Scala 2.12: +```xml + + com.github.mauricio + postgresql-async_2.12 + 0.2.21 ``` And if you're into MySQL: ```scala -"com.github.mauricio" %% "mysql-async" % "0.2.20" +"com.github.mauricio" %% "mysql-async" % "0.2.21" ``` Or Maven: @@ -79,7 +88,15 @@ Or Maven: com.github.mauricio mysql-async_2.11 - 0.2.20 + 0.2.21 + +``` +respectively for Scala 2.12: +```xml + + com.github.mauricio + mysql-async_2.12 + 0.2.21 ``` diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index 5498f80c..00000000 --- a/Vagrantfile +++ /dev/null @@ -1,13 +0,0 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - -# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! -VAGRANTFILE_API_VERSION = "2" - -Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| - - config.vm.box = "chef/centos-6.5" - config.vm.provision :shell, path: "bootstrap.sh" - config.vm.network :forwarded_port, host: 3307, guest: 3306 - -end diff --git a/db-async-common/src/main/scala/com/github/mauricio/async/db/pool/SingleThreadedAsyncObjectPool.scala b/db-async-common/src/main/scala/com/github/mauricio/async/db/pool/SingleThreadedAsyncObjectPool.scala index 49f60593..b4f25ae2 100644 --- a/db-async-common/src/main/scala/com/github/mauricio/async/db/pool/SingleThreadedAsyncObjectPool.scala +++ b/db-async-common/src/main/scala/com/github/mauricio/async/db/pool/SingleThreadedAsyncObjectPool.scala @@ -22,7 +22,7 @@ import com.github.mauricio.async.db.util.{Log, Worker} import java.util.concurrent.atomic.AtomicLong import java.util.{Timer, TimerTask} -import scala.collection.mutable.{ArrayBuffer, Queue, Stack} +import scala.collection.mutable.{ArrayBuffer, Queue} import scala.concurrent.{Future, Promise} import scala.util.{Failure, Success} @@ -52,7 +52,7 @@ class SingleThreadedAsyncObjectPool[T]( import SingleThreadedAsyncObjectPool.{Counter, log} private val mainPool = Worker() - private var poolables = new Stack[PoolableHolder[T]]() + private var poolables = List.empty[PoolableHolder[T]] private val checkouts = new ArrayBuffer[T](configuration.maxObjects) private val waitQueue = new Queue[Promise[T]]() private val timer = new Timer("async-object-pool-timer-" + Counter.incrementAndGet(), true) @@ -171,7 +171,7 @@ class SingleThreadedAsyncObjectPool[T]( */ private def addBack(item: T, promise: Promise[AsyncObjectPool[T]]) { - this.poolables.push(new PoolableHolder[T](item)) + this.poolables ::= new PoolableHolder[T](item) if (this.waitQueue.nonEmpty) { this.checkout(this.waitQueue.dequeue()) @@ -226,7 +226,9 @@ class SingleThreadedAsyncObjectPool[T]( case e: Exception => promise.failure(e) } } else { - val item = this.poolables.pop().item + val h :: t = this.poolables + this.poolables = t + val item = h.item this.checkouts += item promise.success(item) } diff --git a/db-async-common/src/main/scala/com/github/mauricio/async/db/util/NettyUtils.scala b/db-async-common/src/main/scala/com/github/mauricio/async/db/util/NettyUtils.scala index 32f736e3..c9e09f1a 100644 --- a/db-async-common/src/main/scala/com/github/mauricio/async/db/util/NettyUtils.scala +++ b/db-async-common/src/main/scala/com/github/mauricio/async/db/util/NettyUtils.scala @@ -20,7 +20,7 @@ import io.netty.util.internal.logging.{InternalLoggerFactory, Slf4JLoggerFactory object NettyUtils { - InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()) + InternalLoggerFactory.setDefaultFactory(Slf4JLoggerFactory.INSTANCE) lazy val DefaultEventLoopGroup = new NioEventLoopGroup(0, DaemonThreadsFactory("db-async-netty")) } \ No newline at end of file diff --git a/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/AbstractAsyncObjectPoolSpec.scala b/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/AbstractAsyncObjectPoolSpec.scala index 34ca0662..7c8bfdc4 100644 --- a/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/AbstractAsyncObjectPoolSpec.scala +++ b/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/AbstractAsyncObjectPoolSpec.scala @@ -10,7 +10,8 @@ import scala.util.Failure import scala.reflect.runtime.universe.TypeTag import scala.util.Try -import scala.concurrent.duration.{Duration, SECONDS} +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.duration._ /** * This spec is designed abstract to allow testing of any implementation of AsyncObjectPool, against the common diff --git a/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/TimeoutSchedulerSpec.scala b/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/TimeoutSchedulerSpec.scala index acc952e7..0c6d85b4 100644 --- a/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/TimeoutSchedulerSpec.scala +++ b/db-async-common/src/test/scala/com/github/mauricio/async/db/pool/TimeoutSchedulerSpec.scala @@ -18,6 +18,7 @@ package com.github.mauricio.async.db.pool import java.util.concurrent.{ScheduledFuture, TimeoutException} import com.github.mauricio.async.db.util.{ByteBufferUtils, ExecutorServiceUtils} import org.specs2.mutable.SpecificationWithJUnit +import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ import scala.concurrent.{Future, Promise} diff --git a/mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/util/MySQLIO.scala b/mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/util/MySQLIO.scala index 4587eb09..3b56ecc0 100644 --- a/mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/util/MySQLIO.scala +++ b/mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/util/MySQLIO.scala @@ -21,7 +21,7 @@ object MySQLIO { final val CLIENT_PROTOCOL_41 = 0x0200 final val CLIENT_CONNECT_WITH_DB = 0x0008 final val CLIENT_TRANSACTIONS = 0x2000 - final val CLIENT_MULTI_RESULTS = 0x200000 + final val CLIENT_MULTI_RESULTS = 0x20000 final val CLIENT_LONG_FLAG = 0x0001 final val CLIENT_PLUGIN_AUTH = 0x00080000 final val CLIENT_SECURE_CONNECTION = 0x00008000 diff --git a/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/StoredProceduresSpec.scala b/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/StoredProceduresSpec.scala index 3d68563b..d8ff2142 100644 --- a/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/StoredProceduresSpec.scala +++ b/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/StoredProceduresSpec.scala @@ -19,6 +19,7 @@ package com.github.mauricio.async.db.mysql import com.github.mauricio.async.db.ResultSet import com.github.mauricio.async.db.util.FutureUtils._ import org.specs2.mutable.Specification +import scala.concurrent.ExecutionContext.Implicits.global class StoredProceduresSpec extends Specification with ConnectionHelper { @@ -129,4 +130,4 @@ class StoredProceduresSpec extends Specification with ConnectionHelper { } } } -} \ No newline at end of file +} diff --git a/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/TransactionSpec.scala b/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/TransactionSpec.scala index 0ef2f86b..83548c9b 100644 --- a/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/TransactionSpec.scala +++ b/mysql-async/src/test/scala/com/github/mauricio/async/db/mysql/TransactionSpec.scala @@ -10,6 +10,7 @@ import com.github.mauricio.async.db.Connection import scala.concurrent.duration.Duration import scala.concurrent.{Await, Future} +import scala.concurrent.ExecutionContext.Implicits.global import scala.util.{Success, Failure} object TransactionSpec { diff --git a/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/ArrayDecoder.scala b/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/ArrayDecoder.scala index d69eeba4..b62e9629 100644 --- a/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/ArrayDecoder.scala +++ b/postgresql-async/src/main/scala/com/github/mauricio/async/db/postgresql/column/ArrayDecoder.scala @@ -19,7 +19,7 @@ package com.github.mauricio.async.db.postgresql.column import com.github.mauricio.async.db.column.ColumnDecoder import com.github.mauricio.async.db.postgresql.util.{ArrayStreamingParserDelegate, ArrayStreamingParser} import scala.collection.IndexedSeq -import scala.collection.mutable.{ArrayBuffer, Stack} +import scala.collection.mutable.ArrayBuffer import com.github.mauricio.async.db.general.ColumnData import io.netty.buffer.{Unpooled, ByteBuf} import java.nio.charset.Charset @@ -32,12 +32,13 @@ class ArrayDecoder(private val decoder: ColumnDecoder) extends ColumnDecoder { buffer.readBytes(bytes) val value = new String(bytes, charset) - val stack = new Stack[ArrayBuffer[Any]]() + var stack = List.empty[ArrayBuffer[Any]] var current: ArrayBuffer[Any] = null var result: IndexedSeq[Any] = null val delegate = new ArrayStreamingParserDelegate { override def arrayEnded { - result = stack.pop() + result = stack.head + stack = stack.tail } override def elementFound(element: String) { @@ -63,7 +64,7 @@ class ArrayDecoder(private val decoder: ColumnDecoder) extends ColumnDecoder { case None => {} } - stack.push(current) + stack ::= current } } diff --git a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PostgreSQLConnectionSpec.scala b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PostgreSQLConnectionSpec.scala index 2843e95e..0e050477 100644 --- a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PostgreSQLConnectionSpec.scala +++ b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/PostgreSQLConnectionSpec.scala @@ -30,6 +30,7 @@ import org.specs2.mutable.Specification import scala.concurrent.duration._ import scala.concurrent.{Await, Future} +import scala.concurrent.ExecutionContext.Implicits.global object PostgreSQLConnectionSpec { val log = Log.get[PostgreSQLConnectionSpec] @@ -154,7 +155,7 @@ class PostgreSQLConnectionSpec extends Specification with DatabaseTestHelper { row(10) === DateEncoderDecoder.decode("1984-08-06") row(11) === TimeEncoderDecoder.Instance.decode("22:13:45.888888") row(12) === true - row(13) must beAnInstanceOf[java.lang.Long] + row(13).asInstanceOf[AnyRef] must beAnInstanceOf[java.lang.Long] row(13).asInstanceOf[Long] must beGreaterThan(0L) diff --git a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/ConnectionPoolSpec.scala b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/ConnectionPoolSpec.scala index b71ebe65..c2471a75 100644 --- a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/ConnectionPoolSpec.scala +++ b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/ConnectionPoolSpec.scala @@ -22,6 +22,7 @@ import com.github.mauricio.async.db.pool.{ConnectionPool, PoolConfiguration} import com.github.mauricio.async.db.postgresql.exceptions.GenericDatabaseException import com.github.mauricio.async.db.postgresql.{PostgreSQLConnection, DatabaseTestHelper} import org.specs2.mutable.Specification +import scala.concurrent.ExecutionContext.Implicits.global object ConnectionPoolSpec { val Insert = "insert into transaction_test (id) values (?)" diff --git a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/SingleThreadedAsyncObjectPoolSpec.scala b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/SingleThreadedAsyncObjectPoolSpec.scala index d99a60d1..75da1ebd 100644 --- a/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/SingleThreadedAsyncObjectPoolSpec.scala +++ b/postgresql-async/src/test/scala/com/github/mauricio/async/db/postgresql/pool/SingleThreadedAsyncObjectPoolSpec.scala @@ -16,12 +16,14 @@ package com.github.mauricio.async.db.postgresql.pool -import com.github.mauricio.async.db.pool.{SingleThreadedAsyncObjectPool, PoolExhaustedException, PoolConfiguration} +import com.github.mauricio.async.db.pool.{AsyncObjectPool, PoolConfiguration, PoolExhaustedException, SingleThreadedAsyncObjectPool} import com.github.mauricio.async.db.postgresql.{DatabaseTestHelper, PostgreSQLConnection} import java.nio.channels.ClosedChannelException import java.util.concurrent.TimeUnit + import org.specs2.mutable.Specification -import scala.concurrent.Await + +import scala.concurrent.{Await, Future} import scala.concurrent.duration._ import scala.language.postfixOps import com.github.mauricio.async.db.exceptions.ConnectionStillRunningQueryException @@ -47,23 +49,36 @@ class SingleThreadedAsyncObjectPoolSpec extends Specification with DatabaseTestH pool => val connection = get(pool) - val promises = List(pool.take, pool.take, pool.take) + val promises: List[Future[PostgreSQLConnection]] = List(pool.take, pool.take, pool.take) pool.availables.size === 0 pool.inUse.size === 1 + pool.queued.size must be_<=(3) + + /* pool.take call checkout that call this.mainPool.action, + so enqueuePromise called in executorService, + so there is no guaranties that all promises in queue at that moment + */ + val deadline = 5.seconds.fromNow + while(pool.queued.size < 3 || deadline.hasTimeLeft) { + Thread.sleep(50) + } + pool.queued.size === 3 executeTest(connection) pool.giveBack(connection) - promises.foreach { + val pools: List[Future[AsyncObjectPool[PostgreSQLConnection]]] = promises.map { promise => val connection = Await.result(promise, Duration(5, TimeUnit.SECONDS)) executeTest(connection) pool.giveBack(connection) } + Await.ready(pools.last, Duration(5, TimeUnit.SECONDS)) + pool.availables.size === 1 pool.inUse.size === 0 pool.queued.size === 0 diff --git a/project/Build.scala b/project/Build.scala index ca5bcb9e..b543b050 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -49,21 +49,21 @@ object ProjectBuild extends Build { object Configuration { - val commonVersion = "0.2.21-SNAPSHOT" - val projectScalaVersion = "2.11.7" - val specs2Version = "2.5" + val commonVersion = "0.2.22-SNAPSHOT" + val projectScalaVersion = "2.12.1" + val specs2Version = "3.8.6" val specs2Dependency = "org.specs2" %% "specs2-core" % specs2Version % "test" val specs2JunitDependency = "org.specs2" %% "specs2-junit" % specs2Version % "test" val specs2MockDependency = "org.specs2" %% "specs2-mock" % specs2Version % "test" - val logbackDependency = "ch.qos.logback" % "logback-classic" % "1.1.6" % "test" + val logbackDependency = "ch.qos.logback" % "logback-classic" % "1.1.8" % "test" val commonDependencies = Seq( - "org.slf4j" % "slf4j-api" % "1.7.18", - "joda-time" % "joda-time" % "2.9.2", + "org.slf4j" % "slf4j-api" % "1.7.22", + "joda-time" % "joda-time" % "2.9.7", "org.joda" % "joda-convert" % "1.8.1", - "io.netty" % "netty-all" % "4.1.1.Final", - "org.javassist" % "javassist" % "3.20.0-GA", + "io.netty" % "netty-all" % "4.1.6.Final", + "org.javassist" % "javassist" % "3.21.0-GA", specs2Dependency, specs2JunitDependency, specs2MockDependency, @@ -82,8 +82,9 @@ object Configuration { :+ Opts.compile.unchecked :+ "-feature" , + testOptions in Test += Tests.Argument(TestFrameworks.Specs2, "sequential"), scalacOptions in doc := Seq("-doc-external-doc:scala=http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/"), - crossScalaVersions := Seq(projectScalaVersion, "2.10.6"), + crossScalaVersions := Seq(projectScalaVersion, "2.10.6", "2.11.8"), javacOptions := Seq("-source", "1.6", "-target", "1.6", "-encoding", "UTF8"), organization := "com.github.mauricio", version := commonVersion, diff --git a/project/build.properties b/project/build.properties index d638b4f3..e0cbc71d 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version = 0.13.8 \ No newline at end of file +sbt.version = 0.13.13 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt index 4528f2d6..0e9ec632 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,6 +2,10 @@ addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.5.0") addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0") -addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.3") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") + +addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.3.0") resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases" + +// pgpSigningKey := Some(0xB98761578C650D77L)