Skip to content

Commit

Permalink
native image with h2 inmem passing locally
Browse files Browse the repository at this point in the history
  • Loading branch information
johanandren committed Feb 21, 2024
1 parent 1532507 commit 12456d6
Show file tree
Hide file tree
Showing 15 changed files with 346 additions and 5 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/native-image-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ jobs:
run: |-
sbt "publishLocal"
#- name: Akka Persistence R2DBC native image test app build
# run: |-
# cd native-image-tests/
# sbt nativeImage -Dakka.http.version=`cat ~/.version`
- name: Akka Persistence R2DBC native image test app build
run: |-
cd native-image-tests/
sbt nativeImage -Dakka.r2dbc.version=`cat ~/.version`
# run the binary
# target/native-image/native-image-tests
target/native-image/native-image-tests
- name: Email on failure
if: ${{ failure() }}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[
{
"name": "akka.persistence.r2dbc.journal.R2dbcJournal",
"methods": [
{
"name": "<init>",
"parameterTypes": [
"com.typesafe.config.Config",
"java.lang.String"
]
}
]
},
{
"name": "akka.persistence.r2dbc.query.R2dbcReadJournalProvider",
"methods": [
{
"name": "<init>",
"parameterTypes": [
"akka.actor.ExtendedActorSystem",
"com.typesafe.config.Config",
"java.lang.String"
]
}
]
},
{
"name": "akka.persistence.r2dbc.snapshot.R2dbcSnapshotStore",
"methods": [
{
"name": "<init>",
"parameterTypes": [
"com.typesafe.config.Config",
"java.lang.String"
]
}
]
}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Args = --initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils
12 changes: 12 additions & 0 deletions native-image-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
target/

.settings
.project
.classpath

.idea
*.iml

.metals
.bloop
.bsp
34 changes: 34 additions & 0 deletions native-image-tests/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name := "native-image-tests"

version := "1.0"

scalaVersion := "2.13.12"

resolvers += "Akka library repository".at("https://repo.akka.io/maven")

lazy val akkaVersion = sys.props.getOrElse("akka.version", "2.9.1")
lazy val akkaR2dbcVersion = sys.props.getOrElse("akka.r2dbc.version", "1.2.2")

// Run in a separate JVM, to make sure sbt waits until all threads have
// finished before returning.
// If you want to keep the application running while executing other
// sbt tasks, consider https://github.com/spray/sbt-revolver/
fork := true

// GraalVM native image build
enablePlugins(NativeImagePlugin)
nativeImageJvm := "graalvm-community"
nativeImageVersion := "21.0.2"
nativeImageOptions := Seq("--no-fallback", "--verbose", "-Dakka.native-image.debug=true")

libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % akkaVersion,
"com.typesafe.akka" %% "akka-persistence-typed" % akkaVersion,
"com.typesafe.akka" %% "akka-persistence-query" % akkaVersion,
"com.typesafe.akka" %% "akka-slf4j" % akkaVersion,
"com.typesafe.akka" %% "akka-serialization-jackson" % akkaVersion,
"com.lightbend.akka" %% "akka-persistence-r2dbc" % akkaR2dbcVersion,
"ch.qos.logback" % "logback-classic" % "1.2.13",
// H2
"com.h2database" % "h2" % "2.2.224",
"io.r2dbc" % "r2dbc-h2" % "1.0.0.RELEASE")
1 change: 1 addition & 0 deletions native-image-tests/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.9.8
1 change: 1 addition & 0 deletions native-image-tests/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("org.scalameta" % "sbt-native-image" % "0.3.4")
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Custom config here is for logging using logback, loading keystore from classpath for TLS tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
[
{
"name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder",
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.DateConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.LevelConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.LineSeparatorConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.LoggerConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.MDCConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.MarkerConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.MessageConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.classic.pattern.ThreadConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.core.ConsoleAppender",
"queryAllPublicMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"ch.qos.logback.core.OutputStreamAppender",
"methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"] }]
},
{
"name":"ch.qos.logback.core.encoder.Encoder",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
},
{
"name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder",
"methods":[{"name":"setParent","parameterTypes":["ch.qos.logback.core.spi.ContextAware"] }]
},
{
"name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase",
"methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }]
},
{
"name":"ch.qos.logback.core.spi.ContextAware",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
}

]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Args = --initialize-at-build-time=org.slf4j.LoggerFactory,ch.qos.logback,org.slf4j.impl.StaticLoggerBinder,org.slf4j.MDC
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"resources":{
"includes":[{
"pattern":"\\Qlogback.xml\\E"
}]
},
"bundles":[]
}
10 changes: 10 additions & 0 deletions native-image-tests/src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
akka.persistence.journal.plugin = "akka.persistence.r2dbc.journal"
akka.persistence.snapshot-store.plugin = "akka.persistence.r2dbc.snapshot"
akka.persistence.state.plugin = "akka.persistence.r2dbc.state"

akka.persistence.r2dbc.connection-factory = ${akka.persistence.r2dbc.h2}
akka.persistence.r2dbc.connection-factory = {
# overrides for default values from the 'akka.persistence.r2dbc.h2' config block
protocol = "mem"
database = "mydb"
}
13 changes: 13 additions & 0 deletions native-image-tests/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appender name="STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%date{ISO8601}] [%level] [%logger] [%X{akkaAddress}] [%marker] [%thread] - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>

</configuration>
121 changes: 121 additions & 0 deletions native-image-tests/src/main/scala/com/lightbend/EsbTester.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (C) 2009-2024 Lightbend Inc. <https://www.lightbend.com>
*/
package com.lightbend

import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import akka.pattern.StatusReply
import akka.persistence.typed.PersistenceId
import akka.persistence.typed.scaladsl.Effect
import akka.persistence.typed.scaladsl.EventSourcedBehavior
import akka.serialization.jackson.JsonSerializable
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty

import scala.concurrent.duration.DurationInt

object EventSourcedCounter {
sealed trait Command extends JsonSerializable

final case class Increase(amount: Int, replyTo: ActorRef[StatusReply[Increased]]) extends Command
@JsonCreator
final case class GetValue(replyTo: ActorRef[StatusReply[GetValueResponse]]) extends Command
final case class GetValueResponse(value: Int)

sealed trait Event extends JsonSerializable

// FIXME why doesn't @JsonCreator work as usual? is it something missing from the akka jackson feature?
final case class Increased(@JsonProperty("amount") amount: Int) extends Event

final case class State(@JsonProperty("value") value: Int) extends JsonSerializable

def apply(id: String): Behavior[Command] = EventSourcedBehavior[Command, Event, State](
PersistenceId("EventSourcedHelloWorld", id),
State(0),
{ (state, command) =>
command match {
case Increase(increment, replyTo) =>
val increased = Increased(increment)
Effect.persist(increased).thenReply(replyTo)(_ => StatusReply.success(increased))
case GetValue(replyTo) =>
Effect.reply(replyTo)(StatusReply.success(GetValueResponse(state.value)))
}
},
{ (_, event) =>
event match {
case Increased(newGreeting) => State(newGreeting)
}
}).snapshotWhen((_, _, seqNr) => seqNr % 2 == 0)
}

object EsbTester {

object EsbStopped

def apply(whenDone: ActorRef[String]): Behavior[AnyRef] = Behaviors.setup { context =>
Behaviors.withTimers { timers =>

timers.startSingleTimer("Timeout", 10.seconds)

var eventSourcedHelloWorld = context.spawn(EventSourcedCounter("one"), "EsbOne")
context.watchWith(eventSourcedHelloWorld, EsbStopped)
eventSourcedHelloWorld ! EventSourcedCounter.Increase(1, context.self)

def messageOrTimeout(step: String)(partial: PartialFunction[AnyRef, Behavior[AnyRef]]): Behavior[AnyRef] = {
context.log.info("On {}", step)
Behaviors.receiveMessage(message =>
partial.orElse[AnyRef, Behavior[AnyRef]] {
case "Timeout" =>
context.log.error(s"ESB checks timed out in {}", step)
System.exit(1)
Behaviors.same

case other =>
context.log.warn("Unexpected message in {}: {}", step, other)
Behaviors.same
}(message))
}

def step1() = messageOrTimeout("step1") { case StatusReply.Success(EventSourcedCounter.Increased(1)) =>
eventSourcedHelloWorld ! EventSourcedCounter.Increase(2, context.self)
step2()
}

def step2() =
messageOrTimeout("step2") { case StatusReply.Success(EventSourcedCounter.Increased(2)) =>
// triggers snapshot
eventSourcedHelloWorld ! EventSourcedCounter.Increase(2, context.self)
step3()
}

def step3() =
messageOrTimeout("step3") { case StatusReply.Success(EventSourcedCounter.Increased(2)) =>
eventSourcedHelloWorld ! EventSourcedCounter.GetValue(context.self)
step4()
}

def step4() = messageOrTimeout("step4") { case StatusReply.Success(EventSourcedCounter.GetValueResponse(2)) =>
context.stop(eventSourcedHelloWorld)
step5()
}

def step5() = messageOrTimeout("step5") { case EsbStopped =>
// start anew to trigger replay
eventSourcedHelloWorld = context.spawn(EventSourcedCounter("one"), "EsbOneIncarnation2")
eventSourcedHelloWorld ! EventSourcedCounter.GetValue(context.self)
step6()

}

def step6() = messageOrTimeout("step6") { case StatusReply.Success(EventSourcedCounter.GetValueResponse(2)) =>
// replay was fine
whenDone ! "ESB works"
Behaviors.stopped
}

step1()
}
}
}
33 changes: 33 additions & 0 deletions native-image-tests/src/main/scala/com/lightbend/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.lightbend

import akka.actor.typed.ActorSystem
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors

object RootBehavior {
def apply(): Behavior[AnyRef] = Behaviors.setup { context =>
context.spawn(EsbTester(context.self), "ESBTester")

var awaitedOks = Set("ESB works")

Behaviors.receiveMessage {
case string: String =>
awaitedOks -= string
if (awaitedOks.isEmpty) {
context.log.info("All checks ok, shutting down")
Behaviors.stopped
} else {
Behaviors.same
}
case other =>
context.log.warn("Unexpected message: {}", other)
Behaviors.same
}
}
}

object Main extends App {

ActorSystem(RootBehavior(), "R2dbcTester")

}

0 comments on commit 12456d6

Please sign in to comment.