Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import monix.connect.aws.auth.MonixAwsConf._
import monix.connect.aws.auth.configreader.KebabConfigReader
import monix.eval.Task
import monix.execution.Scheduler
import monix.execution.exceptions.DummyException
import monix.testing.scalatest.MonixTaskTest

import java.io.File
Expand Down Expand Up @@ -128,8 +129,8 @@ class MonixAwsConfigSpec extends AsyncFlatSpec with MonixTaskTest with Matchers

Task(configSource.loadOrThrow[AppConf]).map(_.monixAws).attempt.asserting { monixAwsConf =>
monixAwsConf.isLeft shouldBe true
monixAwsConf.left.get shouldBe a[ConfigReaderException[_]]
monixAwsConf.left.get.getMessage should include("Key not found: 'region'")
monixAwsConf.swap.getOrElse(DummyException("failed")) shouldBe a[ConfigReaderException[_]]
monixAwsConf.swap.getOrElse(DummyException("failed")).getMessage should include("Key not found: 'region'")
}
}

Expand Down
135 changes: 70 additions & 65 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Dependencies.Versions
import sbt.Keys.version
import sbt.Keys.{target, version}
import sbt.Test

val monixConnectSeries = "0.7.0"

Expand All @@ -17,9 +18,9 @@ inThisBuild(List(
)
))

skip in publish := true //required by sbt-ci-release
publish / publish := true //required by sbt-ci-release

def sharedSettings(publishForScala3: Boolean= true) = {
def sharedSettings(publishForScala3: Boolean= true, fatalWarningsEnables: Boolean = true) = {
Seq(
scalaVersion := "2.13.8",
crossScalaVersions := Seq("2.12.17", "2.13.8") ++ (if (publishForScala3) Seq("3.1.2") else Seq.empty)
Expand All @@ -40,60 +41,62 @@ def sharedSettings(publishForScala3: Boolean= true) = {
"-language:higherKinds",
"-language:implicitConversions",
"-language:experimental.macros"
),
//warnUnusedImports
scalacOptions in(Compile, console) ++= Seq("-Ywarn-unused:imports")
)
,

// Linter
scalacOptions ++= Seq(
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
"-Ywarn-dead-code", // Warn when dead code is identified.
scalacOptions ++= (
(CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq.empty
case _ => Seq(
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
"-Ywarn-dead-code", // Warn when dead code is identified.
// Turns all warnings into errors ;-)
//temporary disabled for mongodb warn, -YWarn (2.13) and Silencer (2.12) should fix it...
// Enables linter options
"-Xlint:adapted-args", // warn if an argument list is modified to match the receiver
"-Xlint:infer-any", // warn when a type argument is inferred to be `Any`
"-Xlint:missing-interpolator", // a string literal appears to be missing an interpolator id
"-Xlint:doc-detached", // a ScalaDoc comment appears to be detached from its element
"-Xlint:private-shadow", // a private field (or class parameter) shadows a superclass field
"-Xlint:type-parameter-shadow", // a local type parameter shadows a type already in scope
"-Xlint:poly-implicit-overload", // parameterized overloaded implicit methods are not visible as view bounds
"-Xlint:option-implicit", // Option.apply used implicit view
"-Xlint:delayedinit-select", // Selecting member of DelayedInit
"-Ywarn-unused"
//"-Xlint:package-object-classes" // Class or object defined in package object
) ++ (if(fatalWarningsEnables) Seq("-Xfatal-warnings") else Seq.empty[String])
}) ++ Seq(
// Turns all warnings into errors ;-)
//temporary disabled for mongodb warn, -YWarn (2.13) and Silencer (2.12) should fix it...
//"-Xfatal-warnings", //Turning of fatal warnings for the moment
// Enables linter options
"-Xlint:adapted-args", // warn if an argument list is modified to match the receiver
"-Xlint:infer-any", // warn when a type argument is inferred to be `Any`
"-Xlint:missing-interpolator", // a string literal appears to be missing an interpolator id
"-Xlint:doc-detached", // a ScalaDoc comment appears to be detached from its element
"-Xlint:private-shadow", // a private field (or class parameter) shadows a superclass field
"-Xlint:type-parameter-shadow", // a local type parameter shadows a type already in scope
"-Xlint:poly-implicit-overload", // parameterized overloaded implicit methods are not visible as view bounds
"-Xlint:option-implicit", // Option.apply used implicit view
"-Xlint:delayedinit-select", // Selecting member of DelayedInit
//"-Xlint:package-object-classes" // Class or object defined in package object
)
// Note, this is used by the doc-source-url feature to determine the
// relative path of a given source file. If it's not a prefix of a the
// absolute path of the source file, the absolute path of that file
// will be put into the FILE_SOURCE variable, which is
// definitely not what we want.
"-sourcepath",
file(".").getAbsolutePath.replaceAll("[.]$", "")
//"-Xlint:package-object-classes" // Class or object defined in package objecz
) ++ (if(fatalWarningsEnables) Seq("-Xfatal-warnings") else Seq.empty[String]))
,

// ScalaDoc settings
scalacOptions in(Compile, doc) ++= Seq("-no-link-warnings")
(Compile / doc / scalacOptions) ++= Seq("-no-link-warnings")
,
autoAPIMappings := true
,
scalacOptions in ThisBuild ++= Seq(
// Note, this is used by the doc-source-url feature to determine the
// relative path of a given source file. If it's not a prefix of a the
// absolute path of the source file, the absolute path of that file
// will be put into the FILE_SOURCE variable, which is
// definitely not what we want.
"-sourcepath",
file(".").getAbsolutePath.replaceAll("[.]$", "")
scalacOptions ++= Seq(

)
,
parallelExecution in Test := true
,
parallelExecution in ThisBuild := true
Test / parallelExecution := true
,
testForkedParallel in Test := true
,
testForkedParallel in ThisBuild := true
Test / testForkedParallel := true
,
concurrentRestrictions in Global += Tags.limit(Tags.Test, 3)
,
logBuffered in Test := false
,
logBuffered in IntegrationTest := false
,
Test /logBuffered := false,
//dependencyClasspath in IntegrationTest := (dependencyClasspath in IntegrationTest).value ++ (exportedProducts in Test).value,
// https://github.com/sbt/sbt/issues/2654
incOptions := incOptions.value.withLogRecompileOnMacro(false)
Expand Down Expand Up @@ -151,10 +154,8 @@ def mimaSettings(projectName: String) = Seq(
mimaBinaryIssueFilters ++= MimaFilters.allMimaFilters
)

mimaFailOnNoPrevious in ThisBuild := false

//ignores scaladoc link warnings (which are
scalacOptions in (Compile, doc) ++= Seq("-no-link-warnings")
(Compile / doc / scalacOptions) ++= Seq("-no-link-warnings")

val IT = config("it") extend Test

Expand All @@ -179,13 +180,13 @@ lazy val hdfs = monixConnector("hdfs", Dependencies.Hdfs)
}))


lazy val mongodb = monixConnector("mongodb", Dependencies.MongoDb, isMimaEnabled = false, isITParallelExecution = true, scala3Publish = false)
lazy val mongodb = monixConnector("mongodb", Dependencies.MongoDb, isITParallelExecution = true, scala3Publish = false, fatalWarningsEnabled = false)
.settings(libraryDependencies ++= (CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) => Seq.empty
case _ => Seq(
"org.mongodb.scala" %% "mongo-scala-driver" % Versions.MongoScala,
"org.mongodb.scala" %% "mongo-scala-bson" % Versions.MongoScala % Test,
"org.mockito" %% "mockito-scala" % Versions.Mockito % Test cross CrossVersion.for3Use2_13)
"org.mockito" %% "mockito-scala" % Versions.Mockito % Test)
}))

lazy val parquet = monixConnector("parquet", Dependencies.Parquet, scala3Publish = false)
Expand Down Expand Up @@ -226,7 +227,8 @@ def monixConnector(
projectDependencies: Seq[ModuleID],
isMimaEnabled: Boolean = true,
isITParallelExecution: Boolean = false,
scala3Publish: Boolean = true) = {
scala3Publish: Boolean = true,
fatalWarningsEnabled: Boolean = true) = {
Project(id = connectorName, base = file(connectorName))
.enablePlugins(AutomateHeaderPlugin)
.settings(name := s"monix-$connectorName",
Expand All @@ -235,16 +237,19 @@ def monixConnector(
IntegrationTest / parallelExecution := isITParallelExecution,
IntegrationTest / testForkedParallel := isITParallelExecution
)
.settings(sharedSettings(scala3Publish))
.settings(sharedSettings(scala3Publish, fatalWarningsEnabled))
.configs(IntegrationTest, IT)
.enablePlugins(AutomateHeaderPlugin)
.settings(
if(isMimaEnabled) {
mimaSettings(s"monix-$connectorName")
} else { Seq.empty },
// skips publishing docs in scala3 due to a bug running task
Compile / doc / sources := { if (scalaVersion.value.startsWith("3.")) Seq.empty else (Compile / doc / sources).value },
Test / doc / sources := { if (scalaVersion.value.startsWith("3.")) Seq.empty else (Compile / doc / sources).value }
)
Test / doc / sources := { if (scalaVersion.value.startsWith("3.")) Seq.empty else (Test / doc / sources).value },
doctestGenTests := { Seq.empty },
doctestOnlyCodeBlocksMode := false,
Test / unidoc / sources := { Seq.empty })
}

//=> non published modules
Expand All @@ -267,34 +272,34 @@ lazy val docs = project
.enablePlugins(DocusaurusPlugin, MdocPlugin, ScalaUnidocPlugin)

lazy val skipOnPublishSettings = Seq(
skip in publish := true,
publish / skip := true,
publishArtifact := false,
)

lazy val mdocSettings = Seq(
scalacOptions --= Seq("-Xfatal-warnings", "-Ywarn-unused"),
crossScalaVersions := Seq(scalaVersion.value),
unidocProjectFilter in (ScalaUnidoc, unidoc) := inProjects(parquet, dynamodb, s3, sqs, elasticsearch, gcs, hdfs, mongodb, redis),
target in (ScalaUnidoc, unidoc) := (baseDirectory in LocalRootProject).value / "website" / "static" / "api",
cleanFiles += (target in (ScalaUnidoc, unidoc)).value,
(ScalaUnidoc / unidoc / unidocProjectFilter) := inProjects(parquet, dynamodb, s3, sqs, elasticsearch, gcs, hdfs, mongodb, redis),
(ScalaUnidoc / unidoc / target) := (baseDirectory in LocalRootProject).value / "website" / "static" / "api",
cleanFiles += (ScalaUnidoc / unidoc / target).value,
docusaurusCreateSite := docusaurusCreateSite
.dependsOn(unidoc in Compile)
.dependsOn(updateSiteVariables in ThisBuild)
.dependsOn(Compile / unidoc)
.dependsOn(ThisBuild / updateSiteVariables)
.value,
docusaurusPublishGhpages :=
docusaurusPublishGhpages
.dependsOn(unidoc in Compile)
.dependsOn(updateSiteVariables in ThisBuild)
.dependsOn(Compile / unidoc)
.dependsOn(ThisBuild / updateSiteVariables)
.value,
scalacOptions in (ScalaUnidoc, unidoc) ++= Seq(
(ScalaUnidoc / unidoc / scalacOptions) ++= Seq(
"-doc-source-url", s"https://github.com/monix/monix-connect/tree/v${version.value}€{FILE_PATH}.scala",
"-sourcepath", baseDirectory.in(LocalRootProject).value.getAbsolutePath,
"-sourcepath", (LocalRootProject / baseDirectory).value.getAbsolutePath,
"-doc-title", "Monix Connect",
"-doc-version", s"v${version.value}",
"-groups"
),
// Exclude monix.*.internal from ScalaDoc
sources in (ScalaUnidoc, unidoc) ~= (_ filterNot { file =>
ScalaUnidoc / unidoc / sources ~= (_ filterNot { file =>
// Exclude protobuf generated files
file.getCanonicalPath.contains("/src_managed/main/monix/connect/")
file.getCanonicalPath.contains("monix-connect/redis/target/scala-2.12/src_managed")
Expand All @@ -310,17 +315,17 @@ def minorVersion(version: String): String = {


val updateSiteVariables = taskKey[Unit]("Update site variables")
updateSiteVariables in ThisBuild := {
ThisBuild / updateSiteVariables := {
val file =
(baseDirectory in LocalRootProject).value / "website" / "variables.js"
(LocalRootProject / baseDirectory).value / "website" / "variables.js"

val variables =
Map[String, String](
"organization" -> (organization in LocalRootProject).value,
"coreModuleName" -> (moduleName in monixConnect).value,
"organization" -> (LocalRootProject / organization).value,
"coreModuleName" -> (monixConnect / moduleName).value,
"latestVersion" -> version.value,
"scalaPublishVersions" -> {
val minorVersions = (crossScalaVersions in monixConnect).value.map(minorVersion)
val minorVersions = (monixConnect / crossScalaVersions).value.map(minorVersion)
if (minorVersions.size <= 2) minorVersions.mkString(" and ")
else minorVersions.init.mkString(", ") ++ " and " ++ minorVersions.last
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient
import software.amazon.awssdk.services.dynamodb.model.{AttributeDefinition, AttributeValue, BillingMode, CreateTableRequest, CreateTableResponse, DeleteTableRequest, DeleteTableResponse, GetItemRequest, KeySchemaElement, KeyType, ProvisionedThroughput, PutItemRequest, ScalarAttributeType}

import scala.collection.JavaConverters._
import scala.concurrent.duration._

@scala.annotation.nowarn
trait DynamoDbFixture {

import scala.collection.JavaConverters._

case class Citizen(citizenId: String, city: String, age: Int)
val strAttr: String => AttributeValue = value => AttributeValue.builder.s(value).build
val doubleAttr: Int => AttributeValue = value => AttributeValue.builder().n(value.toString).build
Expand Down Expand Up @@ -84,8 +86,7 @@ trait DynamoDbFixture {
def createTableRequest(
tableName: String = Gen.identifier.sample.get,
schema: List[KeySchemaElement],
attributeDefinition: List[AttributeDefinition],
provisionedThroughput: ProvisionedThroughput = baseProvisionedThroughput): CreateTableRequest = {
attributeDefinition: List[AttributeDefinition]): CreateTableRequest = {
CreateTableRequest
.builder
.tableName(tableName)
Expand Down
21 changes: 10 additions & 11 deletions dynamodb/src/it/scala/monix/connect/dynamodb/DynamoDbSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import software.amazon.awssdk.regions.Region
import software.amazon.awssdk.services.dynamodb.model.{GetItemRequest, ListTablesRequest, ListTablesResponse, PutItemRequest}

import scala.concurrent.duration._
import scala.collection.JavaConverters._

class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with DynamoDbFixture with BeforeAndAfterAll {

Expand All @@ -24,9 +23,9 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
import monix.connect.dynamodb.DynamoDbOp.Implicits.listTablesOp
val listRequest = ListTablesRequest.builder.build

DynamoDb.fromConfig.use(_.single(listRequest)).asserting { listedTables =>
DynamoDb.fromConfig().use(_.single(listRequest)).asserting { listedTables =>
listedTables shouldBe a[ListTablesResponse]
listedTables.tableNames().asScala.contains(tableName) shouldBe true
listedTables.tableNames().contains(tableName) shouldBe true
}
}

Expand All @@ -36,7 +35,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with

MonixAwsConf.load().memoizeOnSuccess.flatMap(DynamoDb.fromConfig(_).use(_.single(listRequest))).asserting { listTables =>
listTables shouldBe a[ListTablesResponse]
listTables.tableNames().asScala.contains(tableName) shouldBe true
listTables.tableNames().contains(tableName) shouldBe true
}
}

Expand All @@ -47,7 +46,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
val monixAwsConf = MonixAwsConf.load().memoizeOnSuccess
DynamoDb.fromConfig(monixAwsConf).use(_.single(listRequest)).asserting { listTables =>
listTables shouldBe a[ListTablesResponse]
listTables.tableNames().asScala.contains(tableName) shouldBe true
listTables.tableNames().contains(tableName) shouldBe true
}
}

Expand All @@ -61,7 +60,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
Observable.now(listRequest).transform(dynamodb.transformer()).headL
}.asserting { listedTables =>
listedTables shouldBe a[ListTablesResponse]
listedTables.tableNames().asScala.contains(tableName) shouldBe true
listedTables.tableNames().contains(tableName) shouldBe true
}
}

Expand All @@ -74,7 +73,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
_ <- Observable.now(request).consumeWith(DynamoDb.createUnsafe(client).sink())
getResponse <- Task.from(client.getItem(getItemRequest(tableName, citizen.citizenId, citizen.city)))
} yield {
getResponse.item().values().asScala.head.n().toDouble shouldBe citizen.age
getResponse.item().get(0).n().toDouble shouldBe citizen.age
}
}

Expand All @@ -84,7 +83,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
val putItemRequests: List[PutItemRequest] = citizens.map(putItemRequest(tableName, _))

for {
_ <- DynamoDb.fromConfig.use { dynamoDb =>
_ <- DynamoDb.fromConfig().use { dynamoDb =>
Observable
.fromIterable(putItemRequests)
.consumeWith(dynamoDb.sink(RetryStrategy(retries = 3, backoffDelay = 1.second)))
Expand All @@ -93,7 +92,7 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
Task.from(client.getItem(getItemRequest(tableName, citizen.citizenId, citizen.city)))
}
} yield {
val actualCitizens = getResponses.map(_.item().values().asScala.head.n().toDouble)
val actualCitizens = getResponses.map(_.item().get(0).n().toDouble)
actualCitizens should contain theSameElementsAs citizens.map(_.age)
}
}
Expand All @@ -105,13 +104,13 @@ class DynamoDbSuite extends AsyncFlatSpec with Matchers with MonixTaskTest with
val getItemRequests: List[GetItemRequest] = List("citizen1", "citizen2").map(getItemRequest(tableName, _, city = "Rome"))

Task.traverse(putItemRequests)(req => Task.from(client.putItem(req))) >>
DynamoDb.fromConfig.use { dynamoDb =>
DynamoDb.fromConfig().use { dynamoDb =>
Observable
.fromIterable(getItemRequests)
.transform(dynamoDb.transformer(RetryStrategy(retries = 3, backoffDelay = 1.second)))
.toListL
}.map { result =>
val actualCitizens = result.map(_.item().values().asScala.head.n().toInt)
val actualCitizens = result.map(_.item().get(0).n().toInt)
actualCitizens should contain theSameElementsAs citizens.map(_.age)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package monix.connect.dynamodb

import monix.connect.dynamodb.domain.RetryStrategy
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import monix.execution.exceptions.DummyException
import monix.execution.schedulers.TestScheduler
import org.scalatest.matchers.should.Matchers
Expand Down
Loading