From 9ccc05ca9298c20cb568c108008ec47c1fff43d5 Mon Sep 17 00:00:00 2001 From: aashikam Date: Tue, 20 Jun 2023 20:31:05 +0530 Subject: [PATCH 1/3] Add BBEs for NATS JetStream --- examples/index.json | 18 ++++++++++ .../nats-jetstream-pub/nats_jetstream_pub.bal | 35 +++++++++++++++++++ .../nats-jetstream-pub/nats_jetstream_pub.md | 20 +++++++++++ .../nats_jetstream_pub.metatags | 2 ++ .../nats-jetstream-pub/nats_jetstream_pub.out | 1 + .../nats_jetstream_pub.server.out | 1 + .../nats-jetstream-sub/nats_jestream_sub.bal | 29 +++++++++++++++ .../nats-jetstream-sub/nats_jestream_sub.md | 17 +++++++++ .../nats_jestream_sub.metatags | 2 ++ .../nats-jetstream-sub/nats_jestream_sub.out | 2 ++ 10 files changed, 127 insertions(+) create mode 100644 examples/nats-jetstream-pub/nats_jetstream_pub.bal create mode 100644 examples/nats-jetstream-pub/nats_jetstream_pub.md create mode 100644 examples/nats-jetstream-pub/nats_jetstream_pub.metatags create mode 100644 examples/nats-jetstream-pub/nats_jetstream_pub.out create mode 100644 examples/nats-jetstream-pub/nats_jetstream_pub.server.out create mode 100644 examples/nats-jetstream-sub/nats_jestream_sub.bal create mode 100644 examples/nats-jetstream-sub/nats_jestream_sub.md create mode 100644 examples/nats-jetstream-sub/nats_jestream_sub.metatags create mode 100644 examples/nats-jetstream-sub/nats_jestream_sub.out diff --git a/examples/index.json b/examples/index.json index fc1d5f809d..a38a413e7f 100644 --- a/examples/index.json +++ b/examples/index.json @@ -3159,6 +3159,15 @@ "disableVerificationReason": "Includes ballerinax components", "disablePlayground": true, "isLearnByExample": false + }, + { + "name": "Consume JetStream message", + "url": "nats-jestream-sub", + "verifyBuild": false, + "verifyOutput": false, + "disableVerificationReason": "Includes ballerinax components", + "disablePlayground": true, + "isLearnByExample": false } ] }, @@ -3184,6 +3193,15 @@ "disableVerificationReason": "Includes ballerinax components", "disablePlayground": true, "isLearnByExample": false + }, + { + "name": "Publish message", + "url": "nats-jestream-pub", + "verifyBuild": false, + "verifyOutput": false, + "disableVerificationReason": "Includes ballerinax components", + "disablePlayground": true, + "isLearnByExample": false } ] }, diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.bal b/examples/nats-jetstream-pub/nats_jetstream_pub.bal new file mode 100644 index 0000000000..c2856cbc80 --- /dev/null +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.bal @@ -0,0 +1,35 @@ +import ballerina/http; +import ballerinax/nats; + +type Order readonly & record { + int orderId; + string productName; + decimal price; + boolean isValid; +}; + +service / on new http:Listener(9092) { + private final string SUBJECT_NAME = "orders"; + private final nats:JetStreamClient orderClient; + + function init() returns error? { + // Initiate the NATS JetStreamClient at the start of the service. This will be used + // throughout the lifetime of the service. + self.orderClient = check new (check new nats:Client(nats:DEFAULT_URL)); + nats:StreamConfiguration config = { + name: "demo", + subjects: [self.SUBJECT_NAME], + storageType: nats:MEMORY + }; + _ = check self.orderClient->addStream(config); + } + + resource function post orders(@http:Payload Order newOrder) returns http:Accepted|error { + // Produces a message to the specified subject. + check self.orderClient->publishMessage({ + subject: self.SUBJECT_NAME, + content: newOrder.toString().toBytes() + }); + return http:ACCEPTED; + } +} diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.md b/examples/nats-jetstream-pub/nats_jetstream_pub.md new file mode 100644 index 0000000000..125cc53b86 --- /dev/null +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.md @@ -0,0 +1,20 @@ +# NATS JetStream client - Publish message + +The `nats:JetStreamClient` allows you to publish messages to a specific subject. To create a `nats:JetStreamClient`, you need to provide a valid instance of the `nats:Client`. Before publishing messages, you should call the addStream function to configure the stream. This function requires a `nats:JetStreamConfiguration` object with the values `name`, `subjects`, and `storageType`. To publish messages, you can use the `publishMessage` method, which takes the message content and subject as arguments. This method allows you to send messages that can be received by one or more subscribers. + +::: code nats_jetstream_pub.bal ::: + +## Prerequisites +- Start an instance of the [NATS JetStream erver](https://docs.nats.io/running-a-nats-service/configuration/resource_management). +- Run the NATS JetStream service given in the [NATS JetStream service - Consume message](/learn/by-example/nats-jetstream-sub/) example. + +Run the client program by executing the following command. + +::: out nats_jetstream_pub.server.out ::: + +Invoke the service by executing the following cURL command in a new terminal. + +::: out nats_jetstream_pub.client.out ::: + +## Related links +- [`nats:JetStreamClient` client object - API documentation](https://lib.ballerina.io/ballerinax/nats/latest/clients/JetStreamClient) diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.metatags b/examples/nats-jetstream-pub/nats_jetstream_pub.metatags new file mode 100644 index 0000000000..361ee38951 --- /dev/null +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.metatags @@ -0,0 +1,2 @@ +description: BBE on producing and consuming a message from a subject in the NATS JetStream server using Ballerina. +keywords: ballerina, ballerina by example, bbe, nats, jetstream, server, publish, subscribe diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.out b/examples/nats-jetstream-pub/nats_jetstream_pub.out new file mode 100644 index 0000000000..b13e03a2e6 --- /dev/null +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.out @@ -0,0 +1 @@ +$ curl http://localhost:9092/orders -H "Content-type:application/json" -d "{\"orderId\": 1, \"productName\": \"Sport shoe\", \"price\": 27.5, \"isValid\": true}" diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.server.out b/examples/nats-jetstream-pub/nats_jetstream_pub.server.out new file mode 100644 index 0000000000..31d98c6b7f --- /dev/null +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.server.out @@ -0,0 +1 @@ +$ bal run nats_jetstream_pub.bal diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.bal b/examples/nats-jetstream-sub/nats_jestream_sub.bal new file mode 100644 index 0000000000..05626798c8 --- /dev/null +++ b/examples/nats-jetstream-sub/nats_jestream_sub.bal @@ -0,0 +1,29 @@ +import ballerina/log; +import ballerinax/nats; + +type Order readonly & record { + int orderId; + string productName; + decimal price; + boolean isValid; +}; + +// Initializes a NATS JetStream listener. +listener nats:JetStreamListener subscription = new (check new nats:Client(nats:DEFAULT_URL)); +const string SUBJECT_NAME = "orders"; + +@nats:StreamServiceConfig { + subject: SUBJECT_NAME, + autoAck: false +} +// Binds the consumer to listen to the messages published to the 'bbe.jetstream' subject. +service nats:JetStreamService on subscription { + remote function onMessage(nats:JetStreamMessage message) returns error? { + string stringContent = check string:fromBytes(message.content); + json jsonContent = check stringContent.fromJsonString(); + Order 'order = check jsonContent.cloneWithType(); + if 'order.isValid { + log:printInfo(string `Received valid order for ${'order.productName}`); + } + } +} diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.md b/examples/nats-jetstream-sub/nats_jestream_sub.md new file mode 100644 index 0000000000..a548047b32 --- /dev/null +++ b/examples/nats-jetstream-sub/nats_jestream_sub.md @@ -0,0 +1,17 @@ +# NATS JetStream service - Consume message + +The `nats:JetStreamService` listens to a specified subject for incoming messages. Whenever a publisher sends a message to that subject, any active service listening to it will receive the message. To create a `nats:JetStreamListener`, you need to provide an instance of the `nats:Client`. Once you have a `nats:JetStreamListener`, you can attach a `nats:JetStreamService` to it in order to listen to a specific subject and consume incoming messages. The subject to listen to can be either specified as the service `name` or provided in the `subject` field of the `nats:StreamServiceConfig`. This setup allows you to effectively listen to messages sent to a particular subject. + +::: code nats_jestream_sub.bal ::: + +## Prerequisites +- Start an instance of the [NATS JetStream erver](https://docs.nats.io/running-a-nats-service/configuration/resource_management). + +Run the service by executing the following command. + +::: out nats_jestream_sub.out ::: + +>**Tip:** You can invoke the above service via the [NATS JetStream client](/learn/by-example/nats-jetstream-pub/). + +## Related links +- [`nats` package - API documentation](https://lib.ballerina.io/ballerinax/nats/latest) diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.metatags b/examples/nats-jetstream-sub/nats_jestream_sub.metatags new file mode 100644 index 0000000000..361ee38951 --- /dev/null +++ b/examples/nats-jetstream-sub/nats_jestream_sub.metatags @@ -0,0 +1,2 @@ +description: BBE on producing and consuming a message from a subject in the NATS JetStream server using Ballerina. +keywords: ballerina, ballerina by example, bbe, nats, jetstream, server, publish, subscribe diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.out b/examples/nats-jetstream-sub/nats_jestream_sub.out new file mode 100644 index 0000000000..f9126c710a --- /dev/null +++ b/examples/nats-jetstream-sub/nats_jestream_sub.out @@ -0,0 +1,2 @@ +$ bal run nats_jetstream_sub.bal +time = 2023-06-20T20:17:28.026+05:30 level = INFO module = "" message = "Received valid order for Sport shoe" From 62beba5b212fca87546e5e13834cebe48787e4b7 Mon Sep 17 00:00:00 2001 From: aashikam Date: Tue, 20 Jun 2023 22:07:24 +0530 Subject: [PATCH 2/3] Add changes from code review --- examples/nats-jetstream-pub/nats_jetstream_pub.bal | 7 +++++-- examples/nats-jetstream-pub/nats_jetstream_pub.md | 2 +- examples/nats-jetstream-sub/nats_jestream_sub.bal | 7 +++++-- examples/nats-jetstream-sub/nats_jestream_sub.md | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.bal b/examples/nats-jetstream-pub/nats_jetstream_pub.bal index c2856cbc80..d64fd67298 100644 --- a/examples/nats-jetstream-pub/nats_jetstream_pub.bal +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.bal @@ -13,9 +13,12 @@ service / on new http:Listener(9092) { private final nats:JetStreamClient orderClient; function init() returns error? { + // Initiate a NATS client passing the URL of the NATS broker. + nats:Client natsClient = check new (nats:DEFAULT_URL); + // Initiate the NATS JetStreamClient at the start of the service. This will be used // throughout the lifetime of the service. - self.orderClient = check new (check new nats:Client(nats:DEFAULT_URL)); + self.orderClient = check new (natsClient); nats:StreamConfiguration config = { name: "demo", subjects: [self.SUBJECT_NAME], @@ -24,7 +27,7 @@ service / on new http:Listener(9092) { _ = check self.orderClient->addStream(config); } - resource function post orders(@http:Payload Order newOrder) returns http:Accepted|error { + resource function post orders(Order newOrder) returns http:Accepted|error { // Produces a message to the specified subject. check self.orderClient->publishMessage({ subject: self.SUBJECT_NAME, diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.md b/examples/nats-jetstream-pub/nats_jetstream_pub.md index 125cc53b86..c93868b8b2 100644 --- a/examples/nats-jetstream-pub/nats_jetstream_pub.md +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.md @@ -5,7 +5,7 @@ The `nats:JetStreamClient` allows you to publish messages to a specific subject. ::: code nats_jetstream_pub.bal ::: ## Prerequisites -- Start an instance of the [NATS JetStream erver](https://docs.nats.io/running-a-nats-service/configuration/resource_management). +- Start an instance of the [NATS JetStream server](https://docs.nats.io/running-a-nats-service/configuration/resource_management). - Run the NATS JetStream service given in the [NATS JetStream service - Consume message](/learn/by-example/nats-jetstream-sub/) example. Run the client program by executing the following command. diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.bal b/examples/nats-jetstream-sub/nats_jestream_sub.bal index 05626798c8..146a800d14 100644 --- a/examples/nats-jetstream-sub/nats_jestream_sub.bal +++ b/examples/nats-jetstream-sub/nats_jestream_sub.bal @@ -8,15 +8,18 @@ type Order readonly & record { boolean isValid; }; +// Initiate a NATS client passing the URL of the NATS broker. +nats:Client natsClient = check new (nats:DEFAULT_URL); + // Initializes a NATS JetStream listener. -listener nats:JetStreamListener subscription = new (check new nats:Client(nats:DEFAULT_URL)); +listener nats:JetStreamListener subscription = new (natsClient); const string SUBJECT_NAME = "orders"; @nats:StreamServiceConfig { subject: SUBJECT_NAME, autoAck: false } -// Binds the consumer to listen to the messages published to the 'bbe.jetstream' subject. +// Binds the consumer to listen to the messages published to the 'orders' subject. service nats:JetStreamService on subscription { remote function onMessage(nats:JetStreamMessage message) returns error? { string stringContent = check string:fromBytes(message.content); diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.md b/examples/nats-jetstream-sub/nats_jestream_sub.md index a548047b32..5b1a657168 100644 --- a/examples/nats-jetstream-sub/nats_jestream_sub.md +++ b/examples/nats-jetstream-sub/nats_jestream_sub.md @@ -1,11 +1,11 @@ # NATS JetStream service - Consume message -The `nats:JetStreamService` listens to a specified subject for incoming messages. Whenever a publisher sends a message to that subject, any active service listening to it will receive the message. To create a `nats:JetStreamListener`, you need to provide an instance of the `nats:Client`. Once you have a `nats:JetStreamListener`, you can attach a `nats:JetStreamService` to it in order to listen to a specific subject and consume incoming messages. The subject to listen to can be either specified as the service `name` or provided in the `subject` field of the `nats:StreamServiceConfig`. This setup allows you to effectively listen to messages sent to a particular subject. +The `nats:JetStreamService` listens to a specified subject for incoming messages. Whenever a publisher sends a message to that subject, any active service listening to it will receive the message. To create a `nats:JetStreamListener`, you need to provide an instance of the `nats:Client`. Once you have a `nats:JetStreamListener`, you can attach a `nats:JetStreamService` to it in order to listen to a specific subject and consume incoming messages. The subject to listen to can be either specified as the service path or provided in the `subject` field of the `nats:StreamServiceConfig`. This setup allows you to effectively listen to messages sent to a particular subject. ::: code nats_jestream_sub.bal ::: ## Prerequisites -- Start an instance of the [NATS JetStream erver](https://docs.nats.io/running-a-nats-service/configuration/resource_management). +- Start an instance of the [NATS JetStream server](https://docs.nats.io/running-a-nats-service/configuration/resource_management). Run the service by executing the following command. From 7c9f3c68b106804a81b0c7c95f104dbbca5d5fdd Mon Sep 17 00:00:00 2001 From: aashikam Date: Wed, 21 Jun 2023 08:54:55 +0530 Subject: [PATCH 3/3] Add suggestions from code review --- examples/nats-jetstream-pub/nats_jetstream_pub.bal | 4 ++-- examples/nats-jetstream-pub/nats_jetstream_pub.md | 2 +- examples/nats-jetstream-sub/nats_jestream_sub.bal | 4 ++-- examples/nats-jetstream-sub/nats_jestream_sub.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.bal b/examples/nats-jetstream-pub/nats_jetstream_pub.bal index d64fd67298..db4235b772 100644 --- a/examples/nats-jetstream-pub/nats_jetstream_pub.bal +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.bal @@ -16,7 +16,7 @@ service / on new http:Listener(9092) { // Initiate a NATS client passing the URL of the NATS broker. nats:Client natsClient = check new (nats:DEFAULT_URL); - // Initiate the NATS JetStreamClient at the start of the service. This will be used + // Initiate the NATS `JetStreamClient` at the start of the service. This will be used // throughout the lifetime of the service. self.orderClient = check new (natsClient); nats:StreamConfiguration config = { @@ -28,7 +28,7 @@ service / on new http:Listener(9092) { } resource function post orders(Order newOrder) returns http:Accepted|error { - // Produces a message to the specified subject. + // Produce a message to the specified subject. check self.orderClient->publishMessage({ subject: self.SUBJECT_NAME, content: newOrder.toString().toBytes() diff --git a/examples/nats-jetstream-pub/nats_jetstream_pub.md b/examples/nats-jetstream-pub/nats_jetstream_pub.md index c93868b8b2..1af04eea49 100644 --- a/examples/nats-jetstream-pub/nats_jetstream_pub.md +++ b/examples/nats-jetstream-pub/nats_jetstream_pub.md @@ -1,6 +1,6 @@ # NATS JetStream client - Publish message -The `nats:JetStreamClient` allows you to publish messages to a specific subject. To create a `nats:JetStreamClient`, you need to provide a valid instance of the `nats:Client`. Before publishing messages, you should call the addStream function to configure the stream. This function requires a `nats:JetStreamConfiguration` object with the values `name`, `subjects`, and `storageType`. To publish messages, you can use the `publishMessage` method, which takes the message content and subject as arguments. This method allows you to send messages that can be received by one or more subscribers. +The `nats:JetStreamClient` allows you to publish messages to a specific subject. To create a `nats:JetStreamClient`, you need to provide a valid instance of the `nats:Client`. Before publishing messages, you should call the `addStream` function to configure the stream. This function requires a `nats:JetStreamConfiguration` object with the `name`, `subjects`, and `storageType` values. To publish messages, you can use the `publishMessage` method, which takes the message content and subject as arguments. This method allows you to send messages that can be received by one or more subscribers. ::: code nats_jetstream_pub.bal ::: diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.bal b/examples/nats-jetstream-sub/nats_jestream_sub.bal index 146a800d14..13c26f7d20 100644 --- a/examples/nats-jetstream-sub/nats_jestream_sub.bal +++ b/examples/nats-jetstream-sub/nats_jestream_sub.bal @@ -11,7 +11,7 @@ type Order readonly & record { // Initiate a NATS client passing the URL of the NATS broker. nats:Client natsClient = check new (nats:DEFAULT_URL); -// Initializes a NATS JetStream listener. +// Initialize a NATS JetStream listener. listener nats:JetStreamListener subscription = new (natsClient); const string SUBJECT_NAME = "orders"; @@ -19,7 +19,7 @@ const string SUBJECT_NAME = "orders"; subject: SUBJECT_NAME, autoAck: false } -// Binds the consumer to listen to the messages published to the 'orders' subject. +// Bind the consumer to listen to the messages published to the 'orders' subject. service nats:JetStreamService on subscription { remote function onMessage(nats:JetStreamMessage message) returns error? { string stringContent = check string:fromBytes(message.content); diff --git a/examples/nats-jetstream-sub/nats_jestream_sub.md b/examples/nats-jetstream-sub/nats_jestream_sub.md index 5b1a657168..678a23ce79 100644 --- a/examples/nats-jetstream-sub/nats_jestream_sub.md +++ b/examples/nats-jetstream-sub/nats_jestream_sub.md @@ -1,6 +1,6 @@ # NATS JetStream service - Consume message -The `nats:JetStreamService` listens to a specified subject for incoming messages. Whenever a publisher sends a message to that subject, any active service listening to it will receive the message. To create a `nats:JetStreamListener`, you need to provide an instance of the `nats:Client`. Once you have a `nats:JetStreamListener`, you can attach a `nats:JetStreamService` to it in order to listen to a specific subject and consume incoming messages. The subject to listen to can be either specified as the service path or provided in the `subject` field of the `nats:StreamServiceConfig`. This setup allows you to effectively listen to messages sent to a particular subject. +The `nats:JetStreamService` listens to a specified subject for incoming messages. Whenever a publisher sends a message to that subject, any active service listening to it will receive the message. You need to provide an instance of the `nats:Client` to create a `nats:JetStreamListener`. Once you have a `nats:JetStreamListener`, you can attach a `nats:JetStreamService` to it in order to listen to a specific subject and consume incoming messages. The subject to listen to can be either specified as the service path or provided in the `subject` field of the `nats:StreamServiceConfig`. This setup allows you to effectively listen to messages sent to a particular subject. ::: code nats_jestream_sub.bal :::