Giter Site home page Giter Site logo

usommerl / graalnative4s Goto Github PK

View Code? Open in Web Editor NEW
67.0 8.0 5.0 858 KB

Employ Scala for serverless applications

Home Page: https://graalnative4s.usommerl.dev

License: Apache License 2.0

Dockerfile 6.13% Scala 88.21% Shell 5.66%
scala graalvm graal-native graalvm-native-image graal http4s cats cats-effect tapir circe

graalnative4s's Introduction

graalnative4s

build codecov Scala Steward badge

This is a showcase for a combination of purely functional Scala libraries that can be used with GraalVM native-image without much effort. It employs http4s for general server functionality, circe for JSON processing, ciris to load runtime configuration, tapir to describe HTTP endpoints and odin for logging. Applications that were built with native-image have beneficial properties such as a lower memory footprint and fast startup. This makes them suitable for serverless applications.

Build

Use sbt docker to build a docker image with the native image binary. You don't need to install anything besides docker and sbt, the build process downloads all required GraalVM tooling. The created image will be as minimal as possible by using a multi-stage build.

You can create an even smaller image by utilizing UPX compression. Use the UPX_COMPRESSION environment variable at build time to specify the compression level. Please note that while this reduces the size of the image significantly it also has an impact on startup performance and memory consumption.

Example: export UPX_COMPRESSION="--best"; sbt docker

Deploy

This repository contains a workflow that will deploy the created image to Google Cloud Run. You could also use the button below to deploy it to your own GCP account.

Run on Google Cloud

Try

The most recent version of this small example is online here: https://graalnative4s.usommerl.dev

Acknowledgements & Participation

I have taken a lot of inspiration and knowledge from this blog post by James Ward. You should check out his hello-uzhttp example. Another project that helped me to connect the dots regarding native-image configuration was vasilmkd/docker-stats-monitor. Suggestions and contributions to this repository are welcome!

graalnative4s's People

Contributors

dependabot[bot] avatar mergify[bot] avatar scala-steward avatar usommerl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graalnative4s's Issues

Update GraalVM to 21.0.0

I have made an attempt to upgrade to GraalVM v21.0.0 on branch feature/upgrade-to-graal-v21.x.x but the created image fails at runtime:

Exception in thread "main" java.lang.NoSuchMethodError: java.lang.invoke.VarHandle.releaseFence()
	at java.lang.invoke.MethodHandleNatives.resolve(MethodHandleNatives.java:230)
	at java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:75)
	at java.lang.invoke.MethodHandle.invokeBasic(MethodHandle.java:0)
	at java.lang.invoke.LambdaForm$MH/1617744704.invoke_MT(LambdaForm$MH)
	at scala.runtime.Statics.releaseFence(Statics.java:148)
	at scala.collection.immutable.$colon$colon.<init>(List.scala:623)
	at scala.collection.immutable.List.prependedAll(List.scala:153)
	at scala.collection.IterableOnceOps.toList(IterableOnce.scala:1258)
	at scala.collection.IterableOnceOps.toList$(IterableOnce.scala:1258)
	at scala.collection.AbstractIterable.toList(Iterable.scala:920)
	at cats.effect.internals.IOTracing$.buildFrame(IOTracing.scala:48)
	at cats.effect.internals.IOTracing$.buildCachedFrame(IOTracing.scala:39)
	at cats.effect.internals.IOTracing$.cached(IOTracing.scala:34)
	at cats.effect.IO.flatMap(IO.scala:133)
	at cats.effect.IOLowPriorityInstances$IOEffect.flatMap(IO.scala:886)
	at cats.effect.IOLowPriorityInstances$IOEffect.flatMap(IO.scala:863)
	at cats.FlatMap$Ops.flatMap(FlatMap.scala:229)
	at cats.FlatMap$Ops.flatMap$(FlatMap.scala:229)
	at cats.FlatMap$ToFlatMapOps$$anon$2.flatMap(FlatMap.scala:243)
	at io.odin.loggers.DefaultLogger.$anonfun$log$1(DefaultLogger.scala:23)
	at cats.Applicative.whenA(Applicative.scala:187)
	at cats.Applicative.whenA$(Applicative.scala:186)
	at cats.effect.IOLowPriorityInstances$IOEffect.whenA(IO.scala:863)
	at io.odin.loggers.DefaultLogger.log(DefaultLogger.scala:23)
	at io.odin.loggers.DefaultLogger.$anonfun$info$1(DefaultLogger.scala:98)
	at cats.Applicative.whenA(Applicative.scala:187)
	at cats.Applicative.whenA$(Applicative.scala:186)
	at cats.effect.IOLowPriorityInstances$IOEffect.whenA(IO.scala:863)
	at io.odin.loggers.DefaultLogger.info(DefaultLogger.scala:98)
	at server.Main$.runF(Main.scala:26)
	at server.Main$.run(Main.scala:21)
	at cats.effect.IOApp.$anonfun$main$3(IOApp.scala:69)
	at cats.effect.internals.IOAppPlatform$.mainFiber(IOAppPlatform.scala:45)
	at cats.effect.internals.IOAppPlatform$.main(IOAppPlatform.scala:27)
	at cats.effect.IOApp.main(IOApp.scala:69)
	at cats.effect.IOApp.main$(IOApp.scala:68)
	at server.Main$.main(Main.scala:17)
	at server.Main.main(Main.scala)

This is a follow-up of #16

v0.8.4 creates an OpenAPI document that does not pass the validation

image

Here is the entire error message from the OpenAPI validator:

{
  "messages": [
    "attribute info.summary is unexpected"
  ],
  "schemaValidationMessages": [
    {
      "level": "error",
      "domain": "validation",
      "keyword": "additionalProperties",
      "message": "object instance has properties which are not allowed by the schema: [\"summary\"]",
      "schema": {
        "loadingURI": "#",
        "pointer": "/definitions/Info"
      },
      "instance": {
        "pointer": "/info"
      }
    }
  ]
}

Upgrade to GraalVM 20.3.x

I have made an attempt to upgrade to GraalVM v20.3.0 on branch feature/upgrade-to-graal-v20.3.0 but the created image fails at runtime:

Exception in thread "main" com.oracle.svm.core.jdk.UnsupportedFeatureError: Invoke with MethodHandle argument could not be reduced to at most a single call or single field access. The method handle must be a compile time constant, e.g., be loaded from a `static final` field. Method that contains the method handle invocation: java.lang.invoke.LambdaForm$MH/1782707390.invoke_MT(Object, Object)va:148)
            at scala.collection.immutable.$colon$colon.<init>(List.scala:623)
            at scala.collection.immutable.List.prependedAll(List.scala:153)
            at scala.collection.IterableOnceOps.toList(IterableOnce.scala:1258)
            at scala.collection.IterableOnceOps.toList$(IterableOnce.scala:1258)
            at scala.collection.AbstractIterable.toList(Iterable.scala:920)
            at cats.effect.internals.IOTracing$.buildFrame(IOTracing.scala:48)
            at cats.effect.internals.IOTracing$.buildCachedFrame(IOTracing.scala:39)
            at cats.effect.internals.IOTracing$.cached(IOTracing.scala:34)
            at cats.effect.IO.flatMap(IO.scala:133)
            at cats.effect.IOLowPriorityInstances$IOEffect.flatMap(IO.scala:886)
            at cats.effect.IOLowPriorityInstances$IOEffect.flatMap(IO.scala:863)
            at cats.FlatMap$Ops.flatMap(FlatMap.scala:229)
            at cats.FlatMap$Ops.flatMap$(FlatMap.scala:229)
            at cats.FlatMap$ToFlatMapOps$$anon$2.flatMap(FlatMap.scala:243)
            at io.odin.loggers.DefaultLogger.$anonfun$log$1(DefaultLogger.scala:23)
            at cats.Applicative.whenA(Applicative.scala:187)
            at cats.Applicative.whenA$(Applicative.scala:186)
            at cats.effect.IOLowPriorityInstances$IOEffect.whenA(IO.scala:863)
            at io.odin.loggers.DefaultLogger.log(DefaultLogger.scala:23)
            at io.odin.loggers.DefaultLogger.$anonfun$info$1(DefaultLogger.scala:98)
            at cats.Applicative.whenA(Applicative.scala:187)
            at cats.Applicative.whenA$(Applicative.scala:186)
            at cats.effect.IOLowPriorityInstances$IOEffect.whenA(IO.scala:863)
            at io.odin.loggers.DefaultLogger.info(DefaultLogger.scala:98)
            at server.Main$.runF(Main.scala:26)
            at server.Main$.run(Main.scala:21)
            at cats.effect.IOApp.$anonfun$main$3(IOApp.scala:68)
            at cats.effect.internals.IOAppPlatform$.mainFiber(IOAppPlatform.scala:40)
            at cats.effect.internals.IOAppPlatform$.main(IOAppPlatform.scala:25)
            at cats.effect.IOApp.main(IOApp.scala:68)
            at cats.effect.IOApp.main$(IOApp.scala:67)
            at server.Main$.main(Main.scala:17)
            at server.Main.main(Main.scala)

See graal#2761

Replace pureconfig with ciris

While I have had good experiences with pureconfig, I think that ciris is the more reasonable choice for this demonstrator. Here is why:

Transition to Artifact Registry before May 15, 2024

Transition to Artifact Registry to ensure uninterrupted service.

Container Registry will be phased out, starting May 15, 2024. Please review the options below for how to upgrade your projects to Artifact Registry.

Hello Uwe,

We’re writing to let you know that Container Registry will be phased out starting May 15, 2024, and replaced by Artifact Registry, which offers a variety of new capabilities.

What do you need to know?

Starting May 15, 2024, we’ll limit the projects allowed to host images in Container Registry. The only projects allowed to host the images will be the ones in which:

    1. The Container Registry API was enabled before May 15, 2024.
    1. Images were pushed to Container Registry.

For all other projects, once the discontinuation starts, images will be automatically hosted in Artifact Registry, and you will no longer have the option to host images in Container Registry. Container Registry is in maintenance and only receives critical legal or security fixes.

Once you’ve transitioned to Artifact Registry you’ll be able to store images in:

Artifact Registry pricing model is not based on the underlying storage and egress costs in Cloud Storage like Container Registry. Storage costs are higher in Artifact Registry, but it provides better options to manage egress costs. For details about how this new pricing might impact your projects and options for managing costs, see our pricing documentation.

Note that if you use Container Registry through a dependent service such as Cloud Build, you will be billed for Artifact Registry instead of Container Registry within new projects after May 15, 2024. Requests will also use Artifact Registry quota instead of Container Registry quota. See our documentation for Artifact Registry quota limits.

What do you need to do?

These are the two transition paths we recommend you follow depending on your project’s architecture:

For projects where you use Container Registry:

Consider moving to Artifact Registry. Learn about options to transition to Artifact Registry to prepare for discontinuation of Container Registry.

For projects where you are not currently using Container Registry:

Prepare for automatic hosting of gcr.io in Artifact Registry before May 15, 2024:

  1. Change any automation or workflows to enable the Artifact Registry API instead of the Container Registry API
  2. Grant Artifact Registry roles to users and service accounts that interact with Container Registry.
  3. Update automation that configures storage buckets for Container Registry to perform equivalent actions on Artifact Registry repositories.
  4. Test gcr.io hosted in Artifact Registry using a test project, or transition a project where you are currently using Container Registry.

If you don’t take any of these transition paths, your existing automation workflows for Container Registry might not work in new projects after May 15, 2024.

We’ll send additional communications about future phases, how it will impact your existing Container Registry usage, and any required actions.

We’re here to help

We thank you for your patience and understanding as we make this important change.

– The Google Container Registry Team

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.