Skip to content

Instantly share code, notes, and snippets.

View oxbowlakes's full-sized avatar

Christopher Marshall oxbowlakes

View GitHub Profile
@oxbowlakes
oxbowlakes / scala_java_enums.scala
Created November 30, 2018 14:40
Incorrect scalac warnings on aliased java enum
Welcome to Scala 2.12.3 (OpenJDK 64-Bit Server VM, Java 1.8.0_181).
Type in expressions for evaluation. Or try :help.
scala> :paste
// Entering paste mode (ctrl-D to finish)
type TU = java.util.concurrent.TimeUnit
val NANOSECONDS: TU = java.util.concurrent.TimeUnit.NANOSECONDS
val MICROSECONDS: TU = java.util.concurrent.TimeUnit.MICROSECONDS
val MILLISECONDS: TU = java.util.concurrent.TimeUnit.MILLISECONDS
@oxbowlakes
oxbowlakes / ZioTransactions.scala
Created October 10, 2018 11:37
Using scalaz ZIO to provide a transactional database commit
import java.sql.{Connection, SQLException}
import javax.sql.DataSource
import scalaz.zio.{IO, KleisliIO}
object Transactions {
sealed abstract class Isolation(private[Transactions] val i: Int)
object Isolation {
case object Serialized

Description of Program

I have a program which looks roughly like this

  1. Waits for some files
  2. When they arrive, parses them to extract data
  3. Reads database state
  4. Performs calculation
  5. Saves new state to database
  6. Generates emails on the basis of computed data

WTF is going on?

Don't let anyone mislead you that there are no big changes. The big change is that fixes and security updates will no longer be provided to old versions of Java unless:

  1. You are a paying customer, in which case Oracle will be patching 8 years' worth of LTS versions, as well as the current version
  2. The community backports these fixes to OpenJDK and makes them available

Step back a bit. What is OpenJDK and what does LTS mean?

Historically OpenJDK was quite separate from OracleJDK. This is no longer the case. Oracle are basically providing two separate distributions of Java: OracleJDK and OpenJDK. They are meant to be technically equivalent, although it should be pretty obvious that OracleJDK is likely to ship with add-on features aimed at enterprises (e.g. management tooling or better GC).

//In scalaz 8 IO
IO.fail(new Error("1"))
.ensuring(IO.fail(new Error("2")))
.ensuring(IO.fail(new Error("3")))
.catchAll[E](e4 => IO.sync(println(e4.toString)))
//is (I think) equivalent to this?
try {
try {
try {

I have a monad transformer stack that looks like this (for some user-defined types R, S and E):

EitherT[RWST[IO, R, Unit, S, ?], E, ?]

I used to be very rigorous when using this, in wrapping Java calls such that any thrown exceptions would be caught at turned into an E of my choosing. This kind of thing:

MyStack.fromTryCatch( javaApi.foo(), t => FooFailed(t) )

Over a (not very long) period, I realied that I was on a hiding to nothing: I would inevitably miss wrapping some calls and, even more inevitably, these calls would occasionally fail by throwing exceptions [1]. These would bubble up out of my stack and ... DISAPPEAR!

That's fine, though. "Let it crash" and all that. Except that often the programs would not crash. Because exceptions had bubbled out of my stack, resources were not freed and non-daemon threads would be hanging around, the rest of my program clinging on for dear life. There may be no exceptions in the logs, nothing! How could there be, my program having

object EquationalReasoningBreakdown extends SafeApp {
import scalaz.effect._
def parse(ioa: IO[String]): IO[Int] =
ioa
.flatMap { s =>
IO(s.toInt)
}
.except { case NonFatal(_) =>
IO(-1)
// Does the Java memory model guarantee that this program will *always* print
// x=1 and y=2
//
//Or might the JVM decide that the changes made to x and y in t2 do not need to be visible from t1 because neither x nor
// y is volatile and nor are they modified within a sychronized block (or within the confines of a j.u.c Lock)?
// i.e. I am unsure whether you can observe
// x=0 and y=0
//
//I believe that the memory model *definitely makes the guarantee* that t1 will *never* print something like:

I spent a lot of time tryig to understand why, when I appeared to be following the minimal example from the akka HTTP server documentation, scalac was refusing to compile my code.

Here is the minimal example in its entirety:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer

import scala.io.StdIn

In this page of the Spray migration guide, we are told that marshalling a response looks like this:


Marshaller.of can be replaced with Marshaller.withFixedContentType.

Was:

Marshaller.of[JsonApiObject](`application/json`) { (value, contentType, ctx) =>

ctx.marshalTo(HttpEntity(contentType, value.toJson.toString))