Skip to content

Commit

Permalink
refactor: Replace Akka with Pekko (#2848)
Browse files Browse the repository at this point in the history
  • Loading branch information
seakayone committed Sep 28, 2023
1 parent 35187ca commit d343d8e
Show file tree
Hide file tree
Showing 143 changed files with 887 additions and 675 deletions.
8 changes: 4 additions & 4 deletions build.sbt
Expand Up @@ -262,9 +262,9 @@ lazy val webapi: Project = Project(id = "webapi", base = file("webapi"))
buildInfoKeys ++= Seq[BuildInfoKey](
name,
version,
"akkaHttp" -> Dependencies.AkkaHttpVersion,
"sipi" -> Dependencies.sipiImage,
"fuseki" -> Dependencies.fusekiImage
"sipi" -> Dependencies.sipiImage,
"fuseki" -> Dependencies.fusekiImage,
"pekkoHttp" -> Dependencies.pekkoHttp
),
buildInfoPackage := "org.knora.webapi.http.version"
)
Expand Down Expand Up @@ -299,7 +299,7 @@ lazy val integration: Project = Project(id = "integration", base = file("integra
Test / fork := true, // run tests in a forked JVM
Test / testForkedParallel := false,
Test / parallelExecution := false,
Test / javaOptions += "-Dkey=" + sys.props.getOrElse("key", "akka"),
Test / javaOptions += "-Dkey=" + sys.props.getOrElse("key", "pekko"),
Test / testOptions += Tests.Argument("-oDF"), // show full stack traces and test case durations
libraryDependencies ++= Dependencies.webapiDependencies ++ Dependencies.webapiTestDependencies ++ Dependencies.integrationTestDependencies
)
Expand Down
4 changes: 2 additions & 2 deletions docs/03-endpoints/api-util/version.md
Expand Up @@ -11,7 +11,7 @@ The response has the type `application/json` and contains the following informat
1. name: has the value "version"

2. version numbers for the following components:
- akkaHttp
- pekkoHttp
- gdbFree
- gdbSE
- sbt
Expand All @@ -29,7 +29,7 @@ The response has the type `application/json` and contains the following informat

```json
{
"akkaHttp": "10.1.7",
"pekkoHttp": "10.1.7",
"gdbFree": "8.10.0-free",
"gdbSE": "8.5.0-se",
"name": "version",
Expand Down
2 changes: 1 addition & 1 deletion docs/03-endpoints/instrumentation/metrics.md
Expand Up @@ -42,7 +42,7 @@ zio_fiber_lifetimes_bucket{le="2.0"} 17.0 1671021037947

Metrics of all routes served by ZIO-HTTP (default: port `5555`) are exposed through a default metrics middleware.
However, instead of `http_concurrent_requests_total` etc. they are labeled `zio_http_concurrent_requests_total` etc.
with `zio` prepended, so that they are clearly distinguishable while we still run ZIO-HTTP and Akka-HTTP in parallel.
with `zio` prepended, so that they are clearly distinguishable while we still run ZIO-HTTP and Pekko-HTTP in parallel.

To prevent excessive amounts of labels, it is considered good practice,
to replace dynamic path segments with slugs (e.g. `/projects/shortcode/0000` with `/projects/shortcode/:shortcode`).
Expand Down
28 changes: 14 additions & 14 deletions docs/04-publishing-deployment/configuration.md
Expand Up @@ -6,26 +6,26 @@
# Configuration

All configuration for Knora is done in `application.conf`. Besides the Knora application
specific configuration, there we can also find configuration for the underlying Akka library.
specific configuration, there we can also find configuration for the underlying Pekko library.

For optimal performance it is important to tune the configuration to the hardware used, mainly
to the number of CPUs and cores per CPU.

The relevant sections for tuning are:

- `akka.actor.deployment`
- `knora-actor-dispatcher`
- `knora-blocking-dispatcher`
- `pekko.actor.deployment`
- `knora-actor-dispatcher`
- `knora-blocking-dispatcher`

## System Environment Variables

A number of core settings is additionally configurable through system environment variables. These are:

| key in application.conf | environment variable | default value |
|----------------------------------------|-------------------------------------------------|-----------------------|
| akka.log-config-on-start | KNORA_AKKA_LOG_CONFIG_ON_START | off |
| akka.loglevel | KNORA_AKKA_LOGLEVEL | INFO |
| akka.stdout-loglevel | KNORA_AKKA_STDOUT_LOGLEVEL | INFO |
| pekko.log-config-on-start | KNORA_AKKA_LOG_CONFIG_ON_START | off |
| pekko.loglevel | KNORA_AKKA_LOGLEVEL | INFO |
| pekko.stdout-loglevel | KNORA_AKKA_STDOUT_LOGLEVEL | INFO |
| app.print-extended-config | KNORA_WEBAPI_PRINT_EXTENDED_CONFIG | false |
| app.bcrypt-password-strength | KNORA_WEBAPI_BCRYPT_PASSWORD_STRENGTH | 12 |
| app.jwt.secret | KNORA_WEBAPI_JWT_SECRET_KEY | super-secret-key |
Expand Down Expand Up @@ -74,8 +74,8 @@ route which contains this string.
There is a number of flags that can be set on startup, they will
override any value set in the application configuration file:

- `loadDemoData`, `--loadDemoData`, `-d`: Loads the demo data.
- `allowReloadOverHTTP`, `--allow-reload-over-http`, `-r`: Allows
reloading of data over HTTP.
- `-c`: Print the configuration at startup.
- `--help`: Shows the help message with all startup flags.
- `loadDemoData`, `--loadDemoData`, `-d`: Loads the demo data.
- `allowReloadOverHTTP`, `--allow-reload-over-http`, `-r`: Allows
reloading of data over HTTP.
- `-c`: Print the configuration at startup.
- `--help`: Shows the help message with all startup flags.
38 changes: 38 additions & 0 deletions docs/05-internals/design/adr/ADR-0008-replace-akka-with-pekko.md
@@ -0,0 +1,38 @@
# ADR-0006 Replace Akka with Pekko


## Status

Accepted

# Context

On 7. September 2022 Lightbend announced a [license change](https://www.lightbend.com/blog/why-we-are-changing-the-license-for-akka) for the Akka project, the TL;DR being that you will need a commercial license to use future versions of Akka (2.7+) in production if you exceed a certain revenue threshold.

*For now*, we have staid on Akka 2.6, the current latest version that is still available under the original license. Historically Akka has been incredibly stable, and combined with our
limited use of features, we did not expect this to be a problem.

However, the [last update of Akka 2.6 is announced to be in September 2023](https://www.lightbend.com/akka/license-faq).

> **Will critical vulnerabilities and bugs be patched in 2.6.x?**
> Yes, critical security updates and critical bugs will be patched in Akka v2.6.x under the current Apache 2 license until September of 2023.
As a result, we will not receive further updates and we will never get support for Scala 3 for Akka.

# Proposal

[Apache Pekko](https://pekko.apache.org/) is based on the latest version of Akka in the v2.6.x series. It is currently an incubator project in the ASF. [All Akka modules currently in use in the dsp-api are already released and ported to pekko](https://pekko.apache.org/modules.html): [https://mvnrepository.com/artifact/org.apache.pekko](https://mvnrepository.com/artifact/org.apache.pekko)

The latest stable version [1.0.1](https://pekko.apache.org/docs/pekko/current/release-notes/index.html#1-0-1) is compatible with Akka v2.6.x series and meant to be a plug in replacement.

Scala 3.3.0 is the minimum Scala 3 version supported. Scala 2.12 and 2.13 are still supported.

The migration guide: [https://pekko.apache.org/docs/pekko/current/project/migration-guides.html](https://pekko.apache.org/docs/pekko/current/project/migration-guides.html)

Our current migration to another http server implementation is on currently on hold but we might want to switch to Pekko so that we could receive security updates and bugfixes.

The proof of concept implementation has been shared in the pull request [here](https://github.com/dasch-swiss/dsp-api/pull/2848), allowing for further testing and validation of the proposed switch to Pekko.

# Decision

We replace Akka and Akka/Http with Apache Pekko.
53 changes: 0 additions & 53 deletions docs/05-internals/design/api-v1/how-to-add-a-route.md

This file was deleted.

30 changes: 0 additions & 30 deletions docs/05-internals/design/api-v1/json.md

This file was deleted.

6 changes: 3 additions & 3 deletions docs/05-internals/design/api-v2/how-to-add-a-route.md
Expand Up @@ -25,7 +25,7 @@ request messages should extend a responder-specific trait, so that

## Write a Responder

Write an Akka actor class that extends `org.knora.webapi.responders.Responder`,
Write a Pekko actor class that extends `org.knora.webapi.responders.Responder`,
and add it to the `org.knora.webapi.responders.v2` package.

Give your responder a `receive(msg: YourCustomType)` method that handles each of your
Expand All @@ -36,13 +36,13 @@ and add code to `ResponderManager` to instantiate the new responder. Then add a
the `receive` method in `ResponderManager`, to match messages that extend your request
message trait, and pass them them to that responder's receive method.
The responder's resulting `Future` must be passed to the `ActorUtil.future2Message`.
See [Futures with Akka](../principles/futures-with-akka.md) and
See [Futures with Pekko](../principles/futures-with-pekko.md) and
[Error Handling](../principles/design-overview.md#error-handling) for details.

## Write a Route

Add a class to the `org.knora.webapi.routing.v2` package for your
route, using the Akka HTTP [Routing DSL](https://doc.akka.io/docs/akka-http/current/routing-dsl/index.html).
route, using the Pekko HTTP [Routing DSL](https://pekko.apache.org/docs/pekko-http/current/routing-dsl/index.html).
See the routes in that package for examples. Typically, each route
route will construct a responder request message and pass it to
`RouteUtilV2.runRdfRouteWithFuture` to handle the request.
Expand Down
10 changes: 5 additions & 5 deletions docs/05-internals/design/principles/design-overview.md
Expand Up @@ -45,7 +45,7 @@ The error-handling design has these aims:
4. Ensure that `ask` requests are properly terminated with an
`akka.actor.Status.Failure` message in the event of an error,
without which they will simply time out (see
[Ask: Send and Receive Future](https://doc.akka.io/docs/akka/current/actors.html?language=scala#ask-send-and-receive-future)).
[Ask: Send and Receive Future](https://pekko.apache.org/docs/pekko/current/actors.html?language=scala#ask-send-and-receive-future)).
5. When a actor encounters an error that isn't the client's fault (e.g.
a triplestore failure), log it, but don't do this with errors caused
by bad input.
Expand Down Expand Up @@ -92,20 +92,20 @@ If you want to add a new exception class, see the comments in
### Transformation of Exception to Client Responses

The `org.knora.webapi.KnoraExceptionHandler` is brought implicitly into
scope of `akka-http`, and by doing so registered and used to handle the
scope of `pekko-http`, and by doing so registered and used to handle the
transformation of all `KnoraExceptions` into `HttpResponses`. This
handler handles only exceptions thrown inside the route and not the
actors. However, the design of reply message passing from actors (by
using `future2Message`), makes sure that any exceptions thrown inside
actors, will reach the route, where they will be handled.

See also [Futures with Akka](futures-with-akka.md).
See also [Futures with Akka](futures-with-pekko.md).

## API Routing

The API routes in the `routing` package are defined using the DSL
provided by the
[akka-http](https://doc.akka.io/docs/akka-http/current/index.html)
[pekko-http](https://pekko.apache.org/docs/pekko-http/current/index.html)
library. A routing function has to do the following:

1. Authenticate the client.
Expand Down Expand Up @@ -137,6 +137,6 @@ in the appropriate format, and handles any errors.
Logging in DSP-API is configurable through `logback.xml`, allowing fine
grain configuration of what classes / objects should be logged from which level.

The Akka Actors use [Akka Logging](https://doc.akka.io/docs/akka/current/logging.html)
The Akka Actors use [Akka Logging](https://pekko.apache.org/docs/pekko/current/logging.html)
while logging inside plain Scala Objects and Classes is done through
[Scala Logging](https://github.com/lightbend/scala-logging).
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
-->

# Futures with Akka
# Futures with Pekko

## Introduction

Expand All @@ -22,14 +22,14 @@ introduces them in this way:
The rest of that page is well worth reading to get an overview of how
futures work and what you can do with them.

In [Akka](http://akka.io/), one of the standard patterns for
communication between actors is the [ask pattern](https://doc.akka.io/docs/akka/current/actors.html?language=scala#ask-send-and-receive-future),
In [Pekko](http://pekko.apache.org/), one of the standard patterns for
communication between actors is the [ask pattern](https://pekko.apache.org/docs/pekko/current/actors.html?language=scala#ask-send-and-receive-future),
in which you send a message to an actor and you expect a reply. When you
call the `ask` function (which can be written as a question mark, `?`,
which acts as an infix operator), it immediately returns a `Future`,
which will complete when the reply is sent. As the Akka documentation
which will complete when the reply is sent. As the Pekko documentation
explains in [Use with
Actors](https://doc.akka.io/docs/akka/snapshot/futures.html?language=scala#Use_With_Actors),
Actors](https://pekko.apache.org/docs/pekko/snapshot/futures.html?language=scala#Use_With_Actors),
it is possible to block the calling thread until the future completes,
using `Await.result`. However, they say: 'Blocking is discouraged though
as it will cause performance problems.' In particular, by not blocking,
Expand Down Expand Up @@ -182,7 +182,7 @@ for a future to complete. The normal flow of control works like this:
1. Incoming HTTP requests are handled by an actor called
`KnoraService`, which delegates them to routing functions (in
the `routing` package).
2. For each request, a routing function gets an Akka HTTP
2. For each request, a routing function gets an Pekko HTTP
`RequestContext`, and calls `RouteUtilV1.runJsonRoute` (in API v1)
or `RouteUtilV2.runRdfRouteWithFuture` (in API v2) to send a
message to a supervisor actor to fulfil the request. This creates
Expand Down
2 changes: 1 addition & 1 deletion docs/05-internals/design/principles/http-module.md
Expand Up @@ -7,5 +7,5 @@

The http module holds only a convenience method for adding CORS support
to api routes. The CORS implementation uses the
[akka-http-cors](https://github.com/lomigmegard/akka-http-cors)
[pekko-http-cors](https://github.com/lomigmegard/pekko-http-cors)
directives implementation.
2 changes: 1 addition & 1 deletion docs/05-internals/development/third-party.md
Expand Up @@ -12,7 +12,7 @@ All third party dependencies need to be declared there.
There is an object `Dependencies` where each library should be declared in a `val`.

```scala
val akkaHttpCors = "ch.megard" %% "akka-http-cors" % "1.0.0"
val akkaHttpCors = "ch.megard" %% "pekko-http-cors" % "1.0.0"
```

The first string corresponds to the group/organization in the library's maven artefact,
Expand Down
8 changes: 5 additions & 3 deletions integration/src/test/scala/org/knora/webapi/CoreSpec.scala
Expand Up @@ -5,10 +5,8 @@

package org.knora.webapi

import akka.actor
import akka.testkit.ImplicitSender
import akka.testkit.TestKitBase
import com.typesafe.scalalogging.Logger
import org.apache.pekko
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
Expand All @@ -27,6 +25,10 @@ import org.knora.webapi.messages.store.triplestoremessages.RdfDataObject
import org.knora.webapi.routing.UnsafeZioRun
import org.knora.webapi.util.LogAspect

import pekko.actor
import pekko.testkit.ImplicitSender
import pekko.testkit.TestKitBase

abstract class CoreSpec
extends AnyWordSpec
with TestKitBase
Expand Down
10 changes: 6 additions & 4 deletions integration/src/test/scala/org/knora/webapi/E2ESpec.scala
Expand Up @@ -5,10 +5,8 @@

package org.knora.webapi

import akka.http.scaladsl.client.RequestBuilding
import akka.http.scaladsl.model._
import akka.testkit.TestKitBase
import com.typesafe.scalalogging._
import org.apache.pekko
import org.scalatest.BeforeAndAfterAll
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
Expand Down Expand Up @@ -41,6 +39,10 @@ import org.knora.webapi.testservices.TestClientService
import org.knora.webapi.util.FileUtil
import org.knora.webapi.util.LogAspect

import pekko.http.scaladsl.client.RequestBuilding
import pekko.http.scaladsl.model._
import pekko.testkit.TestKitBase

/**
* This class can be used in End-to-End testing. It starts the DSP stack
* and provides access to settings and logging.
Expand Down Expand Up @@ -96,7 +98,7 @@ abstract class E2ESpec
.getOrThrowFiberFailure()
}

implicit lazy val system: akka.actor.ActorSystem = router.system
implicit lazy val system: pekko.actor.ActorSystem = router.system
implicit lazy val executionContext: ExecutionContext = system.dispatcher
lazy val rdfDataObjects = List.empty[RdfDataObject]
val log: Logger = Logger(this.getClass())
Expand Down

0 comments on commit d343d8e

Please sign in to comment.