diff --git a/_posts/2020-11-02-quarkus-native-on-a-raspberry-pi.adoc b/_posts/2020-11-02-quarkus-native-on-a-raspberry-pi.adoc index 6f58f695341..23ce112de88 100644 --- a/_posts/2020-11-02-quarkus-native-on-a-raspberry-pi.adoc +++ b/_posts/2020-11-02-quarkus-native-on-a-raspberry-pi.adoc @@ -2,7 +2,7 @@ layout: post title: 'Quarkus native running on a Raspberry Pi' date: 2020-11-02 -tags: armv8 arm raspberrypi native +tags: arm raspberrypi native synopsis: Running a Quarkus native app inside a container on a Raspberry Pi author: abattagl --- @@ -18,9 +18,9 @@ To achieve the above goal, I’ve picked up a single-board computer with an inte ## Prerequisites -* *Single-board computer:* The ARM-compatible CPU integrated into the single-board computer must support 64-bit mode. +* *Single-board computer:* The ARM-compatible CPU integrated into the single-board computer must support 64-bit mode. -* *Operating system:* +* *Operating system:* ** To make a Quarkus native container image run in a container, a 64-bit Linux OS is required; ** The OS must support aarch64 CPUs, which leads us to the need for an aarch64-base distribution available for that OS; @@ -29,7 +29,7 @@ To achieve the above goal, I’ve picked up a single-board computer with an inte * *Container technology:* surprise, surprise! an OCI standard container engine is compulsory to run containers on Linux :-) -* *Build tools:* as per the large amount of resources required by the GraalVM to compile Quarkus in native mode, an additional we need an ARM server / Virtual machine to achieve that goal. The server should meet the following minimum requirements: +* *Build tools:* as per the large amount of resources required by the GraalVM to compile Quarkus in native mode, an additional we need an ARM server / Virtual machine to achieve that goal. The server should meet the following minimum requirements: ** CPU: same ARM model as the one embedded in the target single-board computer ** Cores: 4 ** Ram: 8Gb @@ -127,7 +127,7 @@ The remote container registry of choice is https://quay.io/[Quay.io]. More detai ## Implementation -This section will guide you through the following +This section will guide you through the following . Setting up the VM . Setting up the RPi and Fedora IoT @@ -207,7 +207,7 @@ export JAVA_HOME=${GRAALVM_HOME} export PATH=${GRAALVM_HOME}/bin:$PATH ---- -Example: +Example: [source,] ---- @@ -343,7 +343,7 @@ $ systemctl stop firewalld #### Create a new user for the device -Thanks to the fedora-arm-installer tool, we've added out public key to the root user. +Thanks to the fedora-arm-installer tool, we've added out public key to the root user. Using root user on a linux system is never a good idea or, let’s say, a good practice. For this reason, we’re going to add a new administrative user with wheel privileges to our OS: @@ -478,19 +478,19 @@ This paragraph shows the outcome produced by the above steps: [edge@localhost ~]$ sudo podman run -it --rm -p 8090:8080 --name quarkus-getting-started quay.io/abattagl/quarkus-getting-started:1-aarch64 Trying to pull quay.io/abattagl/quarkus-getting-started:1-aarch64... Getting image source signatures -Copying blob d44f88e7704f done -Copying blob 8c4861605060 done -Copying blob c5a0fdbc0d7a done -Copying blob 5dd9a2ffef88 done -Copying config f08559ac50 done +Copying blob d44f88e7704f done +Copying blob 8c4861605060 done +Copying blob c5a0fdbc0d7a done +Copying blob 5dd9a2ffef88 done +Copying config f08559ac50 done Writing manifest to image destination Storing signatures -__ ____ __ _____ ___ __ ____ ______ - --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ - -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ ---\___\_\____/_/ |_/_/|_/_/|_|\____/___/ +__ ____ __ _____ ___ __ ____ ______ + --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ + -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ +--\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2020-10-01 08:49:34,566 INFO [io.quarkus] (main) getting-started 1.0-SNAPSHOT native (powered by Quarkus 1.8.1.Final) started in 0.055s. Listening on: http://0.0.0.0:8080 -2020-10-01 08:49:34,566 INFO [io.quarkus] (main) Profile prod activated. +2020-10-01 08:49:34,566 INFO [io.quarkus] (main) Profile prod activated. 2020-10-01 08:49:34,566 INFO [io.quarkus] (main) Installed features: [cdi, resteasy] ^C 2020-10-01 08:49:49,061 INFO [io.quarkus] (Shutdown thread) getting-started stopped in 0.007s @@ -528,7 +528,7 @@ This article reproduces the steps to compile and run a Quarkus native app on a R ### Building tools -For this PoC I've used a QEmu-base VM. That promotes reusability, but it's still expensive in terms of usability (QEmu works like a charm on linux OS, but not on Windows and MacOS). As stated at the beginning of this article, a more flexible, portable and scalable solution still based on cpu emulation and container technology is under investiogation at the moment. That would help the delegation and scalability of build process. +For this PoC I've used a QEmu-base VM. That promotes reusability, but it's still expensive in terms of usability (QEmu works like a charm on linux OS, but not on Windows and MacOS). As stated at the beginning of this article, a more flexible, portable and scalable solution still based on cpu emulation and container technology is under investiogation at the moment. That would help the delegation and scalability of build process. Be aware that QEmu-based tools are still a workaround. GraalVM is missing the cross-compile feature and it will take a while to release it. @@ -536,6 +536,6 @@ Be aware that QEmu-based tools are still a workaround. GraalVM is missing the cr It's clear that Quarkus can potentially run everywhere. It is, of course, a matter of supportability from GraalVM to the underlying architecture. -So far I feel comfortable in stating that this is just the beginning and lots more features and capabilities are yet to come. +So far I feel comfortable in stating that this is just the beginning and lots more features and capabilities are yet to come. It would very nice to have a distribution of Mandrel for aarch64. Mandrel is aligned with the `native-image` capabilities from GraalVM with OpenJDK and Red Hat Enterprise Linux libraries to improve maintainability. Looking forward to testing it ;-) diff --git a/_posts/2023-07-05-lts-releases.adoc b/_posts/2023-07-05-lts-releases.adoc index bad3463f86c..ae541b245d7 100644 --- a/_posts/2023-07-05-lts-releases.adoc +++ b/_posts/2023-07-05-lts-releases.adoc @@ -2,7 +2,7 @@ layout: post title: 'Long-Term Support (LTS) for Quarkus' date: 2023-07-06 -tags: announcements +tags: announcement synopsis: 'We are introducing Quarkus Long Term Support releases, Quarkus 3.2.x will be the first.' author: maxandersen --- @@ -33,7 +33,7 @@ Here's what you need to know as a Quarkus user: All of the above applies to Quarkus extension maintainers and contributors as well. In addition, we will be recommending that extension maintainers and contributors consider bug fixes and enhancements for LTS releases. This will ensure that LTS releases are as stable and robust as possible. -This means that extension maintainers and contributors will need to consider having branches and versioning in place for LTS releases. +This means that extension maintainers and contributors will need to consider having branches and versioning in place for LTS releases. Many extensions already have done this in the context of Quarkus 2 to 3 move. For example, Neo4j has a 1.x for Quarkus 2 and a 2.x branch for Quarkus 3. Going forward we will recommend that extensions have a branch for the LTS version (currently 3.2.x) and one for main Quarkus 3 features, a 3.x. diff --git a/_posts/2023-09-25-virtual-threads-3.adoc b/_posts/2023-09-25-virtual-threads-3.adoc index 623ac9cf7ec..c8e6a3ee81f 100644 --- a/_posts/2023-09-25-virtual-threads-3.adoc +++ b/_posts/2023-09-25-virtual-threads-3.adoc @@ -2,13 +2,13 @@ layout: post title: 'Testing virtual thread applications' date: 2023-10-02 -tags: virtual threads, reactive, test +tags: virtual-threads reactive test synopsis: 'How to detect pinning while running tests.' author: cescoffier --- :imagesdir: /assets/images/posts/virtual-threads -https://quarkus.io/blog/virtual-threads-2/[In a previous post], we have seen how to implement a CRUD application using virtual threads in Quarkus. +https://quarkus.io/blog/virtual-threads-2/[In a previous post], we have seen how to implement a CRUD application using virtual threads in Quarkus. The following video shows how to test this application and, specifically, how to detect pinning. +++ @@ -20,11 +20,11 @@ The complete code of the application and the tests are available in the https:// ## Pinning and Monopolization Virtual threads combine an imperative development model with a reactive execution mode. -It may provide a simple way to increase the concurrency of an application. +It may provide a simple way to increase the concurrency of an application. However, this might not always be the case. -As described in https://quarkus.io/blog/virtual-thread-1/[another blog post], there are a few limitations, including monopolizing and pinning carrier threads. -When this happens, the application's performance can drastically decrease and increase memory usage. +As described in https://quarkus.io/blog/virtual-thread-1/[another blog post], there are a few limitations, including monopolizing and pinning carrier threads. +When this happens, the application's performance can drastically decrease and increase memory usage. Pinning for a short period can be tolerated, but it can be dramatic under load. While, at the moment, there are no reliable ways to detect monopolization, there are mechanisms to detect pinning. @@ -32,7 +32,7 @@ While, at the moment, there are no reliable ways to detect monopolization, there ## Printing stack traces when a carrier thread gets pinned Suppose you have your application, and your code base contains tests. -You can configure Surefire (or the plugin you use to execute your tests) to dump a stack trace as soon as a virtual thread is going to pin the carrier thread (instead of being unmounted smoothly). +You can configure Surefire (or the plugin you use to execute your tests) to dump a stack trace as soon as a virtual thread is going to pin the carrier thread (instead of being unmounted smoothly). You must set the `jdk.tracePinnedThreads` system property to achieve this. For the Surefire Maven plugin, add the `argLine` parameter to the configuration: @@ -63,9 +63,9 @@ Thread[#141,ForkJoinPool-1-worker-1,5,CarrierThreads] java.base/java.lang.VirtualThread.run(VirtualThread.java:311) ---- -Analyzing the application logs will tell you whether your application is pinning. +Analyzing the application logs will tell you whether your application is pinning. Furthermore, a closer look at the stack trace will give you the reason. -In our example, the `pinTheCarrierThread` method is taking a lock. +In our example, the `pinTheCarrierThread` method is taking a lock. This is indicated by the `monitors:1` text: [source, text] @@ -79,10 +79,10 @@ You can also determine how long the carrier thread was blocked by correlating th ## Failing tests Dumping the stack trace may not be very convenient when your logs are already long. -Fortunately, we released a small Junit 5 extension that allows you to fail the tests when pinning is detected. -It's advantageous when you integrate a third-party library, and you need to know how virtual-thread-friendly it is (to decide between regular worker threads and virtual threads) +Fortunately, we released a small Junit 5 extension that allows you to fail the tests when pinning is detected. +It's advantageous when you integrate a third-party library, and you need to know how virtual-thread-friendly it is (to decide between regular worker threads and virtual threads) -The loom-unit Junit5 extension is currently a separated project. +The loom-unit Junit5 extension is currently a separated project. We are integrating it into the Quarkus test framework (under the `junit5-virtual-threads` name), so some of the steps mentioned below won't be necessary anymore or will be changed slightly. To use this extension, make sure you have the loom-unit extension in your project: @@ -92,7 +92,7 @@ To use this extension, make sure you have the loom-unit extension in your projec me.escoffier.loom loom-unit - 0.3.0 + 0.3.0 test ---- @@ -113,13 +113,13 @@ class TodoResourceTest { Finally, use the `@ShouldNotPin` annotation to indicate to fail the test if any of the methods of the test case pins the carrier thread. You can also use the `@ShouldNotPin` annotation on methods. -If, during the execution of a test, a pinning event is captured, the test fails. +If, during the execution of a test, a pinning event is captured, the test fails. The stack trace of the event is attached to the test failure: [source, text] ---- java.lang.AssertionError: The test testInitialItems() was expected to NOT pin the carrier thread, but we collected 1 event(s) -* Pinning event captured: +* Pinning event captured: java.lang.VirtualThread.parkOnCarrierThread(java.lang.VirtualThread.java:687) java.lang.VirtualThread.parkNanos(java.lang.VirtualThread.java:646) java.lang.VirtualThread.sleepNanos(java.lang.VirtualThread.java:803) @@ -145,7 +145,7 @@ Find more about the loom-unit extension on https://github.com/cescoffier/loom-un ## Summary This blog explains how you can detect pinning events while running your tests. -First, you can dump the stack trace in the log. +First, you can dump the stack trace in the log. Second, you can use the `@ShouldNotPin` annotation to fail the tests if a pinning event is captured. Thanks to this https://github.com/quarkusio/quarkus/pull/35992[PR], the loom-unit extension will be integrated into the `@QuarkusTest` to provide a simpler developer experience. It will be part of Quarkus in the next release (3.5.x). diff --git a/_posts/2023-11-16-quarkus-meets-langchain4j.adoc b/_posts/2023-11-16-quarkus-meets-langchain4j.adoc index e6d011971af..1e087343dc5 100644 --- a/_posts/2023-11-16-quarkus-meets-langchain4j.adoc +++ b/_posts/2023-11-16-quarkus-meets-langchain4j.adoc @@ -2,7 +2,7 @@ layout: post title: 'When Quarkus meets LangChain4j' date: 2023-11-15 -tags: AI langchain +tags: ai langchain synopsis: 'Learn about the new quarkus-langchain4j extension to integrate LLMs in Quarkus applications.' author: cescoffier --- @@ -70,14 +70,14 @@ Speaking about methods, that's where the magic happens. You will describe what y @RegisterAiService public interface TriageService { @SystemMessage(""" - You are working for a bank, processing reviews about - financial products. Triage reviews into positive and + You are working for a bank, processing reviews about + financial products. Triage reviews into positive and negative ones, responding with a JSON document. """ ) @UserMessage(""" Your task is to process the review delimited by ---. - Apply sentiment analysis to the review to determine + Apply sentiment analysis to the review to determine if it is positive or negative, considering various languages. For example: @@ -86,10 +86,10 @@ public interface TriageService { - `I hate your bank, you are the worst!` is a 'NEGATIVE' review Respond with a JSON document containing: - - the 'evaluation' key set to 'POSITIVE' if the review is + - the 'evaluation' key set to 'POSITIVE' if the review is positive, 'NEGATIVE' otherwise - - the 'message' key set to a message thanking or apologizing - to the customer. These messages must be polite and match the + - the 'message' key set to a message thanking or apologizing + to the customer. These messages must be polite and match the review's language. --- @@ -179,7 +179,7 @@ public class ChatMemoryBean implements ChatMemoryProvider { @Override public ChatMemory get(Object memoryId) { - return memories.computeIfAbsent(memoryId, + return memories.computeIfAbsent(memoryId, id -> MessageWindowChatMemory.builder() .maxMessages(20) .id(memoryId) @@ -232,7 +232,7 @@ public class IngestorExample { .embeddingStore(store) .embeddingModel(embeddingModel) .documentSplitter(recursive(500, 0)) - .build(); + .build(); ingestor.ingest(documents); } }