Skip to content

Commit

Permalink
Merge pull request #158 from kaizen-solutions/modules
Browse files Browse the repository at this point in the history
Modules
  • Loading branch information
calvinlfer authored Jun 3, 2023
2 parents 6f872c2 + da71ba0 commit af9f60f
Show file tree
Hide file tree
Showing 166 changed files with 2,798 additions and 1,319 deletions.
2 changes: 0 additions & 2 deletions .git-blame-ignore-revs

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.12.17, 2.13.10, 3.2.2]
scala: [2.12.17, 2.13.10, 3.3.0]
java: [temurin@11]
runs-on: ${{ matrix.os }}
steps:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
.idea/
.metals/
target/
.vscode/
.vscode/
metals.sbt
6 changes: 6 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rules = [OrganizeImports]

OrganizeImports {
// Scala 3.3.x does not support remove unused (although there is a compiler option that detects unused)
removeUnused = false
}
53 changes: 44 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Virgil
_Virgil is a functional Cassandra client built using ZIO, Magnolia and the Datastax 4.x Java drivers_
_Virgil is a functional Cassandra client built using ZIO 2.x, Cats Effect 3.x, Magnolia and the Datastax 4.x Java drivers_

![Build Status](https://github.com/kaizen-solutions/virgil/actions/workflows/ci.yml/badge.svg)

Expand All @@ -14,14 +14,29 @@ _Virgil is a functional Cassandra client built using ZIO, Magnolia and the Datas

## Quick Start

Add the JitPack resolver and import Virgil (this will transitively import the Datastax Java Driver, Magnolia and ZIO 1.x):
Add the JitPack resolver:
```sbt
resolvers += "jitpack" at "https://jitpack.io"
libraryDependencies += "com.github.kaizen-solutions.virgil" %% "virgil" % "<please-see-jitpack-badge-for-latest-version>"
resolvers += "jitpack" at "https://jitpack.io"
```

Please note that Virgil is built for Scala 2.12.x, 2.13.x and 3.1.x but fully-automatic derivation is not present for 3.1.x.
Virgil also supports both **ZIO 1.x** and **ZIO 2.x** (select an artifact with the `zio2` suffix).
### ZIO 2.x
```sbt
libraryDependencies += "com.github.kaizen-solutions.virgil" %% "virgil-zio" % "<please-see-jitpack-badge-for-latest-version>"
```

## Cats Effect 3.x
```sbt
libraryDependencies += "com.github.kaizen-solutions.virgil" %% "virgil-cats-effect" % "<please-see-jitpack-badge-for-latest-version>"
```

If you want to integrate another effect system (or runtime), depend on the `core` module and reference the implementations
for ZIO & Cats Effect for inspiration:

```sbt
libraryDependencies += "com.github.kaizen-solutions.virgil" %% "virgil-core" % "<please-see-jitpack-badge-for-latest-version>"
```

Please note that Virgil is built for Scala 2.12.x, 2.13.x and 3.3.x but fully-automatic derivation is not present for 3.3.x.

## Introduction

Expand Down Expand Up @@ -98,7 +113,7 @@ Scala representation. This can also be used inside User Defined Types as well.

### Scala 3 caveats

If you are using Scala 3.1.x, you will need to use semi-automatic derivation as I have not yet figured out how to enable
If you are using Scala 3.3.x, you will need to use semi-automatic derivation as I have not yet figured out how to enable
fully automatic derivation like Scala 2.x has.

```scala
Expand Down Expand Up @@ -242,10 +257,30 @@ implicit val javaTimeInstantDecoder: CqlPrimitiveDecoder[LocalDateTime] =
)
```

### Underlying driver configuration
This library is built on the Datastax Java Driver, please see the
[Datastax Java Driver documentation](https://docs.datastax.com/en/developer/java-driver/4.15) if you would like to
configure the driver.

### Why the name Virgil?
Virgil was an ancient Roman poet who composed an epic poem about Cassandra and so we thought it would be appropriate.

### Inspiration
We were heavily inspired by Doobie, Cassandra4IO and Quill and wanted a more native ZIO solution for Cassandra focused
on ergonomics, ease of use and performance (compile-time and runtime). Special thanks to John De Goes, Francis Toth and
Nigel Benns for their help, mentorship, and guidance.
on ergonomics, ease of use and performance (compile-time and runtime).

### Acknowledgements
Special thanks to [John De Goes](https://degoes.net), [Francis Toth](https://contramap.dev) and
[Nigel Benns](https://github.com/nbenns) for their help, mentorship, and guidance. Shout out to
[Samuel Gómez](https://samuelgomez.co) for his significant contribution to the Cats Effect 3.x module.

We stand on the shoulders of giants, this work would not be possible without the effect systems and libraries that were
used to build Virgil.


### Users
Virgil is used in production at the following companies:
- [Caesars Digital](https://www.caesars.com)
- [Kaizen Solutions](https://www.kaizen-solutions.io)

Please let us know if you are using Virgil in production and would like to be added to this list.
2 changes: 2 additions & 0 deletions aliases.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
addCommandAlias("coverme", "; clean; coverage; test; coverageReport; coverageAggregate")
addCommandAlias("lint", "; scalafmtAll; scalafixAll")
129 changes: 97 additions & 32 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import ReleaseTransformations._
inThisBuild {
val scala212 = "2.12.17"
val scala213 = "2.13.10"
val scala3 = "3.2.2"
val scala3 = "3.3.0"

List(
scalaVersion := scala3,
scalaVersion := scala213,
crossScalaVersions := Seq(scala212, scala213, scala3),
githubWorkflowPublishTargetBranches := Seq.empty,
githubWorkflowBuild := Seq(
Expand All @@ -25,24 +25,33 @@ inThisBuild {
"COVERALLS_FLAG_NAME" -> "Scala ${{ matrix.scala }}"
)
)
)
),
testFrameworks ++= Seq(
new TestFramework("zio.test.sbt.ZTestFramework"),
new TestFramework("weaver.framework.CatsEffect")
),
semanticdbEnabled := true,
scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.6.0"
)
}
addCommandAlias("coverme", "; clean; coverage; test; coverageReport; coverageAggregate")

lazy val root =
(project in file("."))
project
.in(file("."))
.settings(publishTo := None)
.aggregate(core, zio, catsEffect)

lazy val core =
(project in file("core"))
.settings(organizationSettings *)
.settings(
licenses := List("MPL-2.0" -> url("https://www.mozilla.org/en-US/MPL/2.0/")),
organization := "io.kaizensolutions",
organizationName := "kaizen-solutions",
name := "virgil",
name := "virgil-core",
libraryDependencies ++= {
val datastax = "com.datastax.oss"
val datastaxV = "4.15.0"

val zio = "dev.zio"
val zioV = "2.0.13"
val zioV = "2.0.14"
val magnoliaForScala2 = "com.softwaremill.magnolia1_2" %% "magnolia" % "1.1.3"
val scalaReflectForScala2 = "org.scala-lang" % "scala-reflect" % scalaVersion.value
val magnoliaForScala3 = "com.softwaremill.magnolia1_3" %% "magnolia" % "1.3.0"
Expand All @@ -51,34 +60,90 @@ lazy val root =
Seq(
datastax % "java-driver-core" % datastaxV,
"org.scala-lang.modules" %% "scala-collection-compat" % "2.10.0",
zio %% "zio" % zioV,
zio %% "zio-streams" % zioV,
zio %% "zio-test" % zioV % Test,
zio %% "zio-test-scalacheck" % zioV % Test,
zio %% "zio-test-sbt" % zioV % Test,
"com.dimafeng" %% "testcontainers-scala" % "0.40.15" % Test,
"com.outr" %% "scribe-slf4j" % "3.11.1" % Test
"com.dimafeng" %% "testcontainers-scala" % "0.40.16" % Test,
"com.outr" %% "scribe-slf4j" % "3.11.5" % Test
)

val isScala2x = scalaVersion.value.startsWith("2")

val magnolia =
if (scalaVersion.value.startsWith("2")) Seq(magnoliaForScala2, scalaReflectForScala2)
if (isScala2x) Seq(magnoliaForScala2, scalaReflectForScala2)
else Seq(magnoliaForScala3)

coreDependencies ++ magnolia
val betterMonadicFor =
if (isScala2x) Seq(compilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1"))
else Seq.empty

coreDependencies ++ magnolia ++ betterMonadicFor
},
testFrameworks += new TestFramework("zio.test.sbt.ZTestFramework"),
Test / fork := true,
releaseIgnoreUntrackedFiles := true,
releaseTagName := s"${version.value}",
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
setNextVersion,
commitNextVersion,
pushChanges
)
Test / fork := true
)
.settings(releaseSettings *)

lazy val zio =
project
.in(file("zio"))
.settings(organizationSettings *)
.settings(
name := "virgil-zio",
libraryDependencies ++= {
val zio = "dev.zio"
val zioV = "2.0.14"

Seq(
zio %% "zio" % zioV,
zio %% "zio-streams" % zioV
)
}
)
.settings(releaseSettings *)
.dependsOn(core % "compile->compile;test->test")

lazy val catsEffect =
project
.in(file("cats-effect"))
.settings(organizationSettings *)
.settings(
name := "virgil-cats-effect",
libraryDependencies ++= {
val disney = "com.disneystreaming"
val weaverV = "0.8.3"
Seq(
"org.typelevel" %% "cats-effect" % "3.5.0",
"co.fs2" %% "fs2-core" % "3.7.0",
"co.fs2" %% "fs2-io" % "3.7.0",
disney %% "weaver-cats" % weaverV % Test,
disney %% "weaver-scalacheck" % weaverV % Test
)
},
Test / fork := true
)
.settings(releaseSettings)
.dependsOn(core % "compile->compile;test->test")

def organizationSettings =
Seq(
licenses := List("MPL-2.0" -> url("https://www.mozilla.org/en-US/MPL/2.0/")),
organization := "io.kaizensolutions",
organizationName := "kaizen-solutions"
)

def releaseSettings = Seq(
releaseIgnoreUntrackedFiles := true,
releaseTagName := s"${version.value}",
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
setNextVersion,
commitNextVersion,
pushChanges
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.kaizensolutions.virgil

import cats.effect._
import com.datastax.oss.driver.api.core.CqlSession
import com.datastax.oss.driver.api.core.CqlSessionBuilder
import com.datastax.oss.driver.api.core.metrics.Metrics
import fs2.Stream
import io.kaizensolutions.virgil.configuration.PageState
import io.kaizensolutions.virgil.internal.CQLExecutorImpl
import io.kaizensolutions.virgil.internal.Proofs.=:!=

trait CQLExecutor[F[_]] {
def execute[A](in: CQL[A]): Stream[F, A]

def executeMutation(in: CQL[MutationResult]): F[MutationResult]

def executePage[A](in: CQL[A], pageState: Option[PageState])(implicit
ev: A =:!= MutationResult
): F[Paged[A]]

def metrics: F[Option[Metrics]]
}
object CQLExecutor {

/**
* Create a CQL Executor from an existing Datastax Java Driver's CqlSession
* Note that the user is responsible for the lifecycle of the underlying
* CqlSession
* @param session
* is the underlying Datastax Java Driver's CqlSession
* @return
* the CQLExecutor
*/
def fromCqlSession[F[_]: Async](session: CqlSession): CQLExecutor[F] =
new CQLExecutorImpl[F](session)

def apply[F[_]](builder: => CqlSessionBuilder)(implicit F: Async[F]): Resource[F, CQLExecutor[F]] = {
val acquire: F[CqlSession] = F.delay(builder.build())
val release: CqlSession => F[Unit] = (session: CqlSession) => F.delay(session.close())
Resource
.make[F, CqlSession](acquire)(release)
.map(new CQLExecutorImpl[F](_))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.kaizensolutions.virgil

import fs2.Chunk
import io.kaizensolutions.virgil.configuration.PageState

final case class Paged[A](data: Chunk[A], pageState: Option[PageState])
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.kaizensolutions.virgil.codecs

import fs2.Chunk
import io.kaizensolutions.virgil.codecs.CqlPrimitiveDecoder.ListPrimitiveDecoder

import scala.jdk.CollectionConverters._

trait CqlPrimitiveDecoderFS2Instances {
implicit def chunkCqlPrimitiveDecoder[A](implicit
element: CqlPrimitiveDecoder[A]
): CqlPrimitiveDecoder.WithDriver[Chunk[A], java.util.List[element.DriverType]] =
ListPrimitiveDecoder[Chunk, A, element.DriverType](
element,
(driverList, transformElement) => Chunk.iterable(driverList.asScala.map(transformElement))
)
}
object CqlPrimitiveDecoderFS2Instances extends CqlPrimitiveDecoderFS2Instances
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.kaizensolutions.virgil.codecs

import fs2.Chunk
import io.kaizensolutions.virgil.codecs.CqlPrimitiveEncoder.ListPrimitiveEncoder

import scala.jdk.CollectionConverters._

trait CqlPrimitiveEncoderFS2Instances {
implicit def chunkCqlPrimitiveEncoder[A](implicit
element: CqlPrimitiveEncoder[A]
): ListPrimitiveEncoder[Chunk, A, element.DriverType] =
ListPrimitiveEncoder[Chunk, A, element.DriverType](
element,
(chunk, transform) => chunk.map(transform).toList.asJava
)
}

object CqlPrimitiveEncoderFS2Instances extends CqlPrimitiveEncoderFS2Instances
Loading

0 comments on commit af9f60f

Please sign in to comment.