From 399d3b4a0ddf9852be459b1862fad7e9ad1cc2fb Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:11:35 -0800 Subject: [PATCH 1/9] update links --- modules/ROOT/nav.adoc | 11 ++++----- modules/ROOT/pages/index.adoc | 4 ++-- .../pages/starlight/index.adoc | 23 ------------------- 3 files changed, 7 insertions(+), 31 deletions(-) delete mode 100644 modules/use-cases-architectures/pages/starlight/index.adoc diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index e218c39..8f8c741 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -1,4 +1,4 @@ -.Processing data +.Process data * Change Data Capture (CDC) ** xref:use-cases-architectures:change-data-capture/index.adoc[] ** xref:use-cases-architectures:change-data-capture/table-schema-evolution.adoc[] @@ -6,11 +6,10 @@ ** xref:use-cases-architectures:change-data-capture/questions-and-patterns.adoc[] * xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with {product}] -.Migrating to {pulsar} -* xref:use-cases-architectures:starlight/index.adoc[] -* xref:use-cases-architectures:starlight/kafka/index.adoc[] -* xref:use-cases-architectures:starlight/rabbitmq/index.adoc[] -* xref:use-cases-architectures:starlight/jms/index.adoc[] +.Migrate to {pulsar} +* xref:starlight-for-kafka:ROOT:index.adoc[] +* xref:starlight-for-rabbitmq:ROOT:index.adoc[] +* xref:starlight-for-jms:ROOT:index.adoc[] .APIs and References * Connectors diff --git a/modules/ROOT/pages/index.adoc b/modules/ROOT/pages/index.adoc index 8806857..cc795d8 100644 --- a/modules/ROOT/pages/index.adoc +++ b/modules/ROOT/pages/index.adoc @@ -106,8 +106,8 @@ diff --git a/modules/use-cases-architectures/pages/starlight/index.adoc b/modules/use-cases-architectures/pages/starlight/index.adoc deleted file mode 100644 index 2ca23cd..0000000 --- a/modules/use-cases-architectures/pages/starlight/index.adoc +++ /dev/null @@ -1,23 +0,0 @@ -= {company} Starlight Suite of {pulsar-reg} Extensions -:navtitle: Starlight Extensions - -The Starlight suite of extensions is a collection of {pulsar-reg} protocol handlers that extend an existing {pulsar-short} cluster. -The goal of all the extensions is to create a native, seamless interaction with a {pulsar-short} cluster using existing tooling and clients. - -== {kafka-for-astra} - -{kafka-for-astra} brings native Apache Kafka(R) protocol support to {pulsar} by introducing a Kafka protocol handler on {pulsar-short} brokers. - -xref:use-cases-architectures:starlight/kafka/index.adoc[Get started now] | xref:starlight-for-kafka:ROOT:index.adoc[Configuring] | https://github.com/datastax/starlight-for-kafka[Source Code] - -== {starlight-rabbitmq} - -{starlight-rabbitmq} combines the industry-standard AMQP 0.9.1 (RabbitMQ) API with the cloud-native and horizontally scalable {pulsar-short} streaming platform, providing a powerful way to modernize your RabbitMQ infrastructure, improve performance, and reduce costs. - -xref:use-cases-architectures:starlight/rabbitmq/index.adoc[Get started now] | xref:starlight-for-rabbitmq:ROOT:index.adoc[Configuring] | https://github.com/datastax/starlight-for-rabbitmq[Source Code] - -== Starlight for JMS - -Starlight for JMS allows enterprises to take advantage of the scalability and resiliency of a modern streaming platform to run their existing JMS applications. Because {pulsar-short} is open-source and cloud-native, Starlight for JMS enables enterprises to move their JMS applications to run on-premises and in any cloud environment. - -xref:use-cases-architectures:starlight/jms/index.adoc[Get started now] | xref:starlight-for-jms:ROOT:index.adoc[Configuring] | https://github.com/datastax/pulsar-jms[Source Code] \ No newline at end of file From eac2dba52267d17a5e63fb7fd0484737581f2df0 Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Wed, 7 Jan 2026 09:37:01 -0800 Subject: [PATCH 2/9] combine Luna Streaming starlight content --- antora.yml | 2 - example-guide.adoc | 2 +- modules/ROOT/nav.adoc | 2 +- modules/ROOT/pages/index.adoc | 2 +- .../functions/pages/astream-functions.adoc | 36 ++-- modules/functions/pages/deploy-in-sink.adoc | 4 +- modules/functions/pages/index.adoc | 2 +- modules/pulsar-io/pages/connectors/index.adoc | 12 +- .../pages/connectors/sinks/astra-db.adoc | 2 +- .../pages/connectors/sinks/cloud-storage.adoc | 4 +- .../connectors/sinks/elastic-search.adoc | 6 +- .../connectors/sinks/google-bigquery.adoc | 4 +- .../connectors/sinks/jdbc-clickhouse.adoc | 6 +- .../pages/connectors/sinks/jdbc-mariadb.adoc | 6 +- .../pages/connectors/sinks/jdbc-postgres.adoc | 6 +- .../pages/connectors/sinks/jdbc-sqllite.adoc | 6 +- .../pages/connectors/sinks/kafka.adoc | 6 +- .../pages/connectors/sinks/kinesis.adoc | 6 +- .../pages/connectors/sinks/snowflake.adoc | 4 +- .../connectors/sources/data-generator.adoc | 4 +- .../connectors/sources/debezium-mongodb.adoc | 4 +- .../connectors/sources/debezium-mysql.adoc | 6 +- .../connectors/sources/debezium-oracle.adoc | 6 +- .../connectors/sources/debezium-postgres.adoc | 6 +- .../sources/debezium-sqlserver.adoc | 6 +- .../pages/connectors/sources/kafka.adoc | 4 +- .../pages/connectors/sources/kinesis.adoc | 4 +- .../partials/connectors/sinks/monitoring.adoc | 2 +- .../connectors/sources/monitoring.adoc | 2 +- .../partials/subscription-prereq.adoc | 4 +- .../consuming-change-data.adoc | 4 +- .../pages/starlight/jms/index.adoc | 14 +- .../pages/starlight/kafka/index.adoc | 178 +++++++++++++++++- .../pages/starlight/rabbitmq/index.adoc | 143 +++++++++++++- 34 files changed, 393 insertions(+), 112 deletions(-) diff --git a/antora.yml b/antora.yml index 07823f3..54b8ec9 100644 --- a/antora.yml +++ b/antora.yml @@ -9,8 +9,6 @@ nav: asciidoc: attributes: company: 'DataStax' - product: 'Astra Streaming' - product-short: 'Astra' astra-db: 'Astra DB' astra-ui: 'Astra Portal' astra-url: 'https://astra.datastax.com' diff --git a/example-guide.adoc b/example-guide.adoc index 507185c..8969c71 100644 --- a/example-guide.adoc +++ b/example-guide.adoc @@ -9,7 +9,7 @@ A guide is a document offering step by step instruction to reach some goal. Guides are technical in nature and tend to make assumptions about the consumer's environment. To help create guides that will work in most environments, please follow these ideas. * *Keep links to a minimum* - when someone is learning a new concept for the first time and xref:README.adoc[every] other xref:README.adoc[word] is linked it xref:README.adoc[makes] things xref:README.adoc[confusing] and hard to get a good flow going. Instead, annotate a word or phrase and provide a "Resources" area at the bottom of the guide. -* *Separate products and runtimes in tabs* - it is common to reach the same result through multiple ways. An example is creating a tenant/namespace/topic in {product} and Luna Streaming. Both have the same result but get there in very different ways. Offer each as a tab and let the consumer choose their path. The step after the tabbed step can assume the consumer has complete the previious step and is in a known state. Runtimes follow the same pattern. Weather one is using Java or C#, they are still creating a {pulsar-short} client to interact with the cluster. Create a single step in the guide with multiple tabs for each runtime. +* *Separate products and runtimes in tabs* - it is common to reach the same result through multiple ways. An example is creating a tenant/namespace/topic in Astra Streaming and Luna Streaming. Both have the same result but get there in very different ways. Offer each as a tab and let the consumer choose their path. The step after the tabbed step can assume the consumer has complete the previious step and is in a known state. Runtimes follow the same pattern. Weather one is using Java or C#, they are still creating a {pulsar-short} client to interact with the cluster. Create a single step in the guide with multiple tabs for each runtime. * *Be thoughtful about the names you use* - if you are leaning a new concept or feature with no background on the product, words matter. Labeling a tab as "Luna Helm" and then referring to it as "{pulsar-short} Helm Chart" are two distinct things to that reader. The author of the document has such deep understanding that they consider those things the same - and technically they are at {company}. But the read isn't from {company}, so be mindful of their context. * *Talk in first person* - humans create the guides and humans consume the guides. Write as if you are paired with your consumer in doing what ever the guide does. Use "we", "us", "you". ==== diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 8f8c741..28c1349 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -4,7 +4,7 @@ ** xref:use-cases-architectures:change-data-capture/table-schema-evolution.adoc[] ** xref:use-cases-architectures:change-data-capture/consuming-change-data.adoc[] ** xref:use-cases-architectures:change-data-capture/questions-and-patterns.adoc[] -* xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with {product}] +* xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with Astra Streaming] .Migrate to {pulsar} * xref:starlight-for-kafka:ROOT:index.adoc[] diff --git a/modules/ROOT/pages/index.adoc b/modules/ROOT/pages/index.adoc index cc795d8..6a3f2d6 100644 --- a/modules/ROOT/pages/index.adoc +++ b/modules/ROOT/pages/index.adoc @@ -19,7 +19,7 @@ We've included best practices for Apache Pulsar, a full connector reference, and examples for getting the most out of Astra's CDC feature. - xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with {product}] + xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with Astra Streaming] diff --git a/modules/functions/pages/astream-functions.adoc b/modules/functions/pages/astream-functions.adoc index 0caf19b..817c164 100644 --- a/modules/functions/pages/astream-functions.adoc +++ b/modules/functions/pages/astream-functions.adoc @@ -4,7 +4,7 @@ Functions are lightweight compute processes that enable you to process each message received on a topic. You can apply custom logic to that message, transforming or enriching it, and then output it to a different topic. -Functions run inside {product} and are therefore serverless. +Functions run inside Astra Streaming and are therefore serverless. You write the code for your function in Java, Python, or Go, then upload the code. It is automatically run for each message published to the specified input topic. @@ -12,13 +12,13 @@ Functions are implemented using https://pulsar.apache.org/docs/en/functions-over [IMPORTANT] ==== -Custom functions require a xref:astra-streaming:operations:astream-pricing.adoc[paid {product} plan]. +Custom functions require a xref:astra-streaming:operations:astream-pricing.adoc[paid Astra Streaming plan]. ==== == Deploy Python functions in a zip file -{product} supports Python-based {pulsar-short} functions. -These functions can be packaged in a zip file and deployed to {product} or {pulsar-short}. +Astra Streaming supports Python-based {pulsar-short} functions. +These functions can be packaged in a zip file and deployed to Astra Streaming or {pulsar-short}. The same zip file can be deployed to either environment. To demonstrate this, the following steps create function configuration YAML file, package all necessary function files as a zip archive, and then use the `pulsar-admin` CLI to deploy the zip. @@ -152,8 +152,8 @@ Replace the following: * `**INPUT_TOPIC_NAME**`: The input topic for the function * `**OUTPUT_TOPIC_NAME**`: The output topic for the function -. Use `pulsar-admin` to deploy the Python zip to {product} or {pulsar-short}. -The command below assumes you've properly configured the `client.conf` file for `pulsar-admin` commands against your {pulsar-short} cluster. If you are using {product}, see xref:astra-streaming:developing:configure-pulsar-env.adoc[] for more information. +. Use `pulsar-admin` to deploy the Python zip to Astra Streaming or {pulsar-short}. +The command below assumes you've properly configured the `client.conf` file for `pulsar-admin` commands against your {pulsar-short} cluster. If you are using Astra Streaming, see xref:astra-streaming:developing:configure-pulsar-env.adoc[] for more information. + [source,console] ---- @@ -163,7 +163,7 @@ bin/pulsar-admin functions create --function-config-file /absolute/path/to/func- . Verify that the function was deployed: + * Go to the {astra-ui} to see your newly deployed function listed under the **Functions** tab for your tenant. -See <> for more information on testing and monitoring your function in {product}. +See <> for more information on testing and monitoring your function in Astra Streaming. * Use the `pulsar-admin` CLI to list functions for a specific tenant and namespace: + [source,bash,subs="+quotes"] @@ -173,8 +173,8 @@ bin/pulsar-admin functions list --tenant **TENANT_NAME** --namespace **NAMESPACE == Deploy Java functions in a JAR file -{product} supports Java-based {pulsar-short} functions which are packaged in a JAR file. -The JAR can be deployed to {product} or {pulsar-short}. +Astra Streaming supports Java-based {pulsar-short} functions which are packaged in a JAR file. +The JAR can be deployed to Astra Streaming or {pulsar-short}. The same JAR file can be deployed to either environment. In this example, you'll create a function JAR file using Maven, then use the `pulsar-admin` CLI to deploy the JAR. @@ -289,15 +289,15 @@ userConfig: + [IMPORTANT] ==== -{product} requires the `inputs` topic to have a message schema defined before deploying the function. +Astra Streaming requires the `inputs` topic to have a message schema defined before deploying the function. Otherwise, deployment errors may occur. Use the {astra-ui} to define the message schema for a topic. ==== -. Use the `pulsar-admin` CLI to deploy your function JAR to {product} or {pulsar-short}. +. Use the `pulsar-admin` CLI to deploy your function JAR to Astra Streaming or {pulsar-short}. + The following command assumes you've properly configured the `client.conf` file for `pulsar-admin` commands against your {pulsar-short} cluster. -If you are using {product}, see xref:astra-streaming:developing:configure-pulsar-env.adoc[] for more information. +If you are using Astra Streaming, see xref:astra-streaming:developing:configure-pulsar-env.adoc[] for more information. + [source,bash] ---- @@ -307,7 +307,7 @@ bin/pulsar-admin functions create --function-config-file /absolute/path/to/func . Verify that the function was deployed: + * Go to the {astra-ui} to see your newly deployed function listed under the **Functions** tab for your tenant. -See <> for more information on testing and monitoring your function in {product}. +See <> for more information on testing and monitoring your function in Astra Streaming. * Use the `pulsar-admin` CLI to list functions for a specific tenant and namespace: + [source,bash,subs="+quotes"] @@ -315,9 +315,9 @@ See <> for more information bin/pulsar-admin functions list --tenant **TENANT_NAME** --namespace **NAMESPACE_NAME** ---- -== Add functions in {product} dashboard +== Add functions in Astra Streaming dashboard -Add functions in the **Functions** tab of the {product} dashboard. +Add functions in the **Functions** tab of the Astra Streaming dashboard. . Select *Create Function* to get started. @@ -326,7 +326,7 @@ Add functions in the **Functions** tab of the {product} dashboard. image::astream-name-function.png[Function and Namespace] . Select the file you want to pull the function from and which function you want to use within that file. -{product} generates a list of acceptable classes. +Astra Streaming generates a list of acceptable classes. + image::astream-exclamation-function.png[Exclamation Function] + @@ -416,7 +416,7 @@ If you want to use different topics, change `in`, `out`, and `log` accordingly. . Verify that the response is `Created Successfully!`. This indicates that the function was deployed and ready to run when triggered by incoming messages. + -If the response is `402 Payment Required` with `Reason: only qualified organizations can create functions`, then you must upgrade to a xref:astra-streaming:operations:astream-pricing.adoc[paid {product} plan]. +If the response is `402 Payment Required` with `Reason: only qualified organizations can create functions`, then you must upgrade to a xref:astra-streaming:operations:astream-pricing.adoc[paid Astra Streaming plan]. + You can also verify that a function was created by checking the **Functions** tab or by running `./pulsar-admin functions list --tenant **TENANT_NAME**`. @@ -512,4 +512,4 @@ A *Function-name Deleted Successfully!* message confirms the function was perman == Next steps -Learn more about developing functions for {product} and {pulsar-short} https://pulsar.apache.org/docs/en/functions-develop/[here]. \ No newline at end of file +Learn more about developing functions for Astra Streaming and {pulsar-short} https://pulsar.apache.org/docs/en/functions-develop/[here]. \ No newline at end of file diff --git a/modules/functions/pages/deploy-in-sink.adoc b/modules/functions/pages/deploy-in-sink.adoc index a1c5516..5e6f718 100644 --- a/modules/functions/pages/deploy-in-sink.adoc +++ b/modules/functions/pages/deploy-in-sink.adoc @@ -5,11 +5,11 @@ Before this update, functions transformed data either after it was written to a This required either an intermediate topic, with additional storage, IO, and latency, or a custom connector. + Now, functions can be deployed at sink creation and apply preprocessing to sink topic writes. + -== Create sink function in {product} +== Create sink function in Astra Streaming Creating a sink function is similar to creating a sink in the {astra-ui}, but with a few additional steps. -. xref:pulsar-io:connectors/index.adoc[Create a sink] as described in the {product} documentation. +. xref:pulsar-io:connectors/index.adoc[Create a sink] as described in the Astra Streaming documentation. . During sink creation, select the transform function you want to run inside the sink. + diff --git a/modules/functions/pages/index.adoc b/modules/functions/pages/index.adoc index d9d14c2..44485b9 100644 --- a/modules/functions/pages/index.adoc +++ b/modules/functions/pages/index.adoc @@ -158,7 +158,7 @@ transform-function-2 ====== [#deploy-as] -== Deploy with {product} +== Deploy with Astra Streaming Deploy transform functions in the *Functions* tab of the {astra-ui}. diff --git a/modules/pulsar-io/pages/connectors/index.adoc b/modules/pulsar-io/pages/connectors/index.adoc index 119d70f..e553573 100644 --- a/modules/pulsar-io/pages/connectors/index.adoc +++ b/modules/pulsar-io/pages/connectors/index.adoc @@ -1,16 +1,16 @@ = Connectors :navtitle: Connector Overview -{product} offers fully-managed {pulsar-reg} connectors. +Astra Streaming offers fully-managed {pulsar-reg} connectors. Create, monitor, and manage both source and sink connectors through our simple UI, the `pulsar-admin` CLI, or RESTful API. Connect popular data sources to {pulsar} topics or sink data from {pulsar-short} topics to popular systems. -Below is a list of {pulsar} source and sink connectors supported by {product}. +Below is a list of {pulsar} source and sink connectors supported by Astra Streaming. [IMPORTANT] ==== -{product} doesn't support custom sink or source connectors. +Astra Streaming doesn't support custom sink or source connectors. ==== [#sink-connectors] @@ -154,7 +154,7 @@ xref:connectors/sources/kinesis.adoc[Kinesis source connector documentation] == Experimental Connectors -{company} is always experimenting with connectors. Below are the connectors currently in development that have not yet been promoted to official support in *{product}*. +{company} is always experimenting with connectors. Below are the connectors currently in development that have not yet been promoted to official support in *Astra Streaming*. To get access to these connectors, contact {support-url}[{company} Support]. @@ -238,7 +238,7 @@ Zeebe + == Listing Sink Connectors -To list available sink connectors in your {product} tenant, use any of the following. +To list available sink connectors in your Astra Streaming tenant, use any of the following. [tabs] ==== @@ -288,7 +288,7 @@ curl "$WEB_SERVICE_URL/admin/v3/sinks/builtinsinks" -H "Authorization: $ASTRA_ST == Listing Source Connectors -To list available source connectors in your {product} tenant, use any of the following. +To list available source connectors in your Astra Streaming tenant, use any of the following. [tabs] ==== diff --git a/modules/pulsar-io/pages/connectors/sinks/astra-db.adoc b/modules/pulsar-io/pages/connectors/sinks/astra-db.adoc index 0c2d9a5..6e4adfd 100644 --- a/modules/pulsar-io/pages/connectors/sinks/astra-db.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/astra-db.adoc @@ -4,7 +4,7 @@ {company} {astra-db} Sink Connector is based on the open-source xref:pulsar-connector:ROOT:index.adoc[{cass-reg} sink connector for {pulsar-reg}]. Depending on how you deploy the connector, it can be used to sink topic messages with a table in {astra-db} or a table in a {cass-short} cluster outside of DB. -The {product} portal provides simple way to connect this sink and a table in {astra-db} with simply a token. Using `pulsar-admin` or the REST API, you can configure the sink to connect with a {cass-short} connection manually. +The Astra Streaming portal provides simple way to connect this sink and a table in {astra-db} with simply a token. Using `pulsar-admin` or the REST API, you can configure the sink to connect with a {cass-short} connection manually. This reference assumes you are manually connecting to a {cass-short} table. diff --git a/modules/pulsar-io/pages/connectors/sinks/cloud-storage.adoc b/modules/pulsar-io/pages/connectors/sinks/cloud-storage.adoc index 68979f9..4ea937d 100644 --- a/modules/pulsar-io/pages/connectors/sinks/cloud-storage.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/cloud-storage.adoc @@ -141,9 +141,9 @@ include::partial$connectors/sinks/monitoring.adoc[] == Connector Reference -With the Cloud Storage Sink there are two sets of parameters: {product} parameters and cloud storage provider parameters. +With the Cloud Storage Sink there are two sets of parameters: Astra Streaming parameters and cloud storage provider parameters. -=== {product} parameters for Cloud Storage Sink +=== Astra Streaming parameters for Cloud Storage Sink [%header,format=csv,cols="2,1,1,3"] |=== diff --git a/modules/pulsar-io/pages/connectors/sinks/elastic-search.adoc b/modules/pulsar-io/pages/connectors/sinks/elastic-search.adoc index 416c922..9a776ab 100644 --- a/modules/pulsar-io/pages/connectors/sinks/elastic-search.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/elastic-search.adoc @@ -8,7 +8,7 @@ Use Elasticsearch to store, search, and manage data for logs, metrics, search ba [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://opensearch.org/docs/1.2/clients/java-rest-high-level/[OpenSearch 1.2.4 library] to interact with +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://opensearch.org/docs/1.2/clients/java-rest-high-level/[OpenSearch 1.2.4 library] to interact with Elasticsearch. ==== @@ -33,7 +33,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -44,7 +44,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} Elasticsearch sink connector supports all configuration properties provided by {pulsar}. Please refer to the https://pulsar.apache.org/docs/io-elasticsearch-sink/#property[connector properties] for a complete list. +The Astra Streaming Elasticsearch sink connector supports all configuration properties provided by {pulsar}. Please refer to the https://pulsar.apache.org/docs/io-elasticsearch-sink/#property[connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sinks/google-bigquery.adoc b/modules/pulsar-io/pages/connectors/sinks/google-bigquery.adoc index 6a0682f..9c7952c 100644 --- a/modules/pulsar-io/pages/connectors/sinks/google-bigquery.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/google-bigquery.adoc @@ -22,9 +22,9 @@ include::partial$connectors/sinks/monitoring.adoc[] == Connector Reference -The BigQuery sink has multiple sets of parameters: the {product} parameters, the Kafka Connect Adapter parameters, and the Google BigQuery parameters. Each set of parameters provides a way to coordinate how data will be streamed from {pulsar-short} to BigQuery. +The BigQuery sink has multiple sets of parameters: the Astra Streaming parameters, the Kafka Connect Adapter parameters, and the Google BigQuery parameters. Each set of parameters provides a way to coordinate how data will be streamed from {pulsar-short} to BigQuery. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== diff --git a/modules/pulsar-io/pages/connectors/sinks/jdbc-clickhouse.adoc b/modules/pulsar-io/pages/connectors/sinks/jdbc-clickhouse.adoc index c1cc7c6..061c2c7 100644 --- a/modules/pulsar-io/pages/connectors/sinks/jdbc-clickhouse.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/jdbc-clickhouse.adoc @@ -7,7 +7,7 @@ real-time. [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/ClickHouse/clickhouse-jdbc[Clickhouse 0.3.2 library] to interact with Clickhouse. +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/ClickHouse/clickhouse-jdbc[Clickhouse 0.3.2 library] to interact with Clickhouse. ==== == Get Started @@ -26,7 +26,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -37,7 +37,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} JDBC Clickhouse sink connector supports all configuration properties provided by {pulsar}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector +The Astra Streaming JDBC Clickhouse sink connector supports all configuration properties provided by {pulsar}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector properties] for a complete list. diff --git a/modules/pulsar-io/pages/connectors/sinks/jdbc-mariadb.adoc b/modules/pulsar-io/pages/connectors/sinks/jdbc-mariadb.adoc index dfcca38..e961ff2 100644 --- a/modules/pulsar-io/pages/connectors/sinks/jdbc-mariadb.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/jdbc-mariadb.adoc @@ -8,7 +8,7 @@ Read more about {pulsar-reg}'s JDBC sink connector https://pulsar.apache.org/doc [NOTE] ==== -{product} currently supports {pulsar} {pulsar-version}, which uses the https://mariadb.com/kb/en/about-mariadb-connector-j/[MariaDB Connector/J 2.7.5 library] to interact with MariaDB. +Astra Streaming currently supports {pulsar} {pulsar-version}, which uses the https://mariadb.com/kb/en/about-mariadb-connector-j/[MariaDB Connector/J 2.7.5 library] to interact with MariaDB. ==== == Get Started @@ -27,7 +27,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -38,4 +38,4 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} JDBC MariaDB sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector properties] for a complete list. \ No newline at end of file +The Astra Streaming JDBC MariaDB sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector properties] for a complete list. \ No newline at end of file diff --git a/modules/pulsar-io/pages/connectors/sinks/jdbc-postgres.adoc b/modules/pulsar-io/pages/connectors/sinks/jdbc-postgres.adoc index f7f1c8e..66acace 100644 --- a/modules/pulsar-io/pages/connectors/sinks/jdbc-postgres.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/jdbc-postgres.adoc @@ -10,7 +10,7 @@ The PostgreSQL JDBC Driver is an open source JDBC driver written in Pure Java (T [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://jdbc.postgresql.org/documentation/setup/[PostgreSQL JDBC 42.4.1 library] to interact with PostgreSQL. +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://jdbc.postgresql.org/documentation/setup/[PostgreSQL JDBC 42.4.1 library] to interact with PostgreSQL. ==== == Get Started @@ -29,7 +29,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -40,7 +40,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} JDBC PostgreSQL sink connector supports all configuration properties provided by {pulsar-short}. Refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector +The Astra Streaming JDBC PostgreSQL sink connector supports all configuration properties provided by {pulsar-short}. Refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sinks/jdbc-sqllite.adoc b/modules/pulsar-io/pages/connectors/sinks/jdbc-sqllite.adoc index 7a7ee1c..cec3bd7 100644 --- a/modules/pulsar-io/pages/connectors/sinks/jdbc-sqllite.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/jdbc-sqllite.adoc @@ -12,7 +12,7 @@ SQLite JDBC is a library for accessing and creating SQLite database files in Jav [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/xerial/sqlite-jdbc[Xerial 3.8.11.2 library] to interact with SQLite. +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/xerial/sqlite-jdbc[Xerial 3.8.11.2 library] to interact with SQLite. ==== == Get Started @@ -31,7 +31,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -42,7 +42,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} JDBC MariaDB sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector +The Astra Streaming JDBC MariaDB sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-jdbc-sink#property[connector properties] for a complete list. diff --git a/modules/pulsar-io/pages/connectors/sinks/kafka.adoc b/modules/pulsar-io/pages/connectors/sinks/kafka.adoc index 59aeaa2..e0d6548 100644 --- a/modules/pulsar-io/pages/connectors/sinks/kafka.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/kafka.adoc @@ -6,7 +6,7 @@ Apache Kafka(R) is an open-source distributed event streaming platform used by t [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/apache/kafka/tree/2.7[Kafka 2.7.2 library] to interact with +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/apache/kafka/tree/2.7[Kafka 2.7.2 library] to interact with Kafka. ==== @@ -26,7 +26,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -37,7 +37,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} Kafka sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-kafka-sink#property[connector properties] for a complete list. +The Astra Streaming Kafka sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-kafka-sink#property[connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sinks/kinesis.adoc b/modules/pulsar-io/pages/connectors/sinks/kinesis.adoc index c9aaa95..a5cf9e5 100644 --- a/modules/pulsar-io/pages/connectors/sinks/kinesis.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/kinesis.adoc @@ -10,7 +10,7 @@ The Amazon Kinesis Client Library for Java (Amazon KCL) enables Java developers [NOTE] ==== -{product} currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/awslabs/amazon-kinesis-client[Amazon Kinesis 2.2.8 library] and the https://github.com/aws/aws-sdk-java[AWS Java SDK 0.14.0 library] to interact with Kinesis. +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses the https://github.com/awslabs/amazon-kinesis-client[Amazon Kinesis 2.2.8 library] and the https://github.com/aws/aws-sdk-java[AWS Java SDK 0.14.0 library] to interact with Kinesis. ==== == Get Started @@ -29,7 +29,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -40,7 +40,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} Kinesis sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-kinesis-sink#property[connector properties] for a complete list. +The Astra Streaming Kinesis sink connector supports all configuration properties provided by {pulsar-short}. Please refer to the https://pulsar.apache.org/docs/io-kinesis-sink#property[connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sinks/snowflake.adoc b/modules/pulsar-io/pages/connectors/sinks/snowflake.adoc index 73ec8e0..75cb8a7 100644 --- a/modules/pulsar-io/pages/connectors/sinks/snowflake.adoc +++ b/modules/pulsar-io/pages/connectors/sinks/snowflake.adoc @@ -22,7 +22,7 @@ include::partial$connectors/sinks/monitoring.adoc[] There are two sets of parameters that support sink connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -33,7 +33,7 @@ include::example$connectors/sinks/astra.csv[] These values are provided in the "configs" area. -The {product} Snowflake sink connector supports all configuration properties provided by {company}. Please refer to the https://github.com/datastax/snowflake-connector#configuration[connector +The Astra Streaming Snowflake sink connector supports all configuration properties provided by {company}. Please refer to the https://github.com/datastax/snowflake-connector#configuration[connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sources/data-generator.adoc b/modules/pulsar-io/pages/connectors/sources/data-generator.adoc index df248e0..469dc0c 100644 --- a/modules/pulsar-io/pages/connectors/sources/data-generator.adoc +++ b/modules/pulsar-io/pages/connectors/sources/data-generator.adoc @@ -8,7 +8,7 @@ The Data Generator source connector creates fake data on an {pulsar-reg} topic u The connector will produce data indefinitely while it is running. -{product} currently supports {pulsar} {pulsar-version}, which uses version 0.5.9 of the jfairy library. +Astra Streaming currently supports {pulsar} {pulsar-version}, which uses version 0.5.9 of the jfairy library. For a reference of the full "Person" class, https://github.com/apache/pulsar/blob/branch-{pulsar-version}/pulsar-io/data-generator/src/main/java/org/apache/pulsar/io/datagenerator/Person.java[view the source]. @@ -28,7 +28,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== diff --git a/modules/pulsar-io/pages/connectors/sources/debezium-mongodb.adoc b/modules/pulsar-io/pages/connectors/sources/debezium-mongodb.adoc index d6966e6..b05e385 100644 --- a/modules/pulsar-io/pages/connectors/sources/debezium-mongodb.adoc +++ b/modules/pulsar-io/pages/connectors/sources/debezium-mongodb.adoc @@ -6,7 +6,7 @@ Debezium’s MongoDB connector tracks a MongoDB replica set or a MongoDB sharded The connector automatically handles the addition or removal of shards in a sharded cluster, changes in membership of each replica set, elections within each replica set, and the resolution of communications problems. -{product} currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported MongoDB versions, please refer to the https://debezium.io/releases/{debezium-version}/[Debezium documentation]. +Astra Streaming currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported MongoDB versions, please refer to the https://debezium.io/releases/{debezium-version}/[Debezium documentation]. == Get Started @@ -24,7 +24,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== diff --git a/modules/pulsar-io/pages/connectors/sources/debezium-mysql.adoc b/modules/pulsar-io/pages/connectors/sources/debezium-mysql.adoc index d51dd47..3cf3172 100644 --- a/modules/pulsar-io/pages/connectors/sources/debezium-mysql.adoc +++ b/modules/pulsar-io/pages/connectors/sources/debezium-mysql.adoc @@ -4,7 +4,7 @@ The Debezium MySQL connector reads the binlog, produces change events for row-level INSERT, UPDATE, and DELETE operations, and emits these change events as messages in an {pulsar-reg} topic. -{product} currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. +Astra Streaming currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. == Get Started @@ -22,7 +22,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -33,7 +33,7 @@ include::example$connectors/sources/astra.csv[] These values are provided in the "configs" area. -The {product} MySQL source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/mysql.html#mysql-connector-properties[Debezium MySQL connector properties] for a complete list. +The Astra Streaming MySQL source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/mysql.html#mysql-connector-properties[Debezium MySQL connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sources/debezium-oracle.adoc b/modules/pulsar-io/pages/connectors/sources/debezium-oracle.adoc index 316faad..2634b47 100644 --- a/modules/pulsar-io/pages/connectors/sources/debezium-oracle.adoc +++ b/modules/pulsar-io/pages/connectors/sources/debezium-oracle.adoc @@ -6,7 +6,7 @@ Debezium’s Oracle connector captures and records row-level changes that occur The connector can be configured to emit change events for specific subsets of schemas and tables, or to ignore, mask, or truncate values in specific columns. -{product} currently supports {pulsar-reg} {pulsar-version}, which uses Debezium {debezium-version} libraries. +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses Debezium {debezium-version} libraries. == Get Started @@ -24,7 +24,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -33,7 +33,7 @@ include::example$connectors/sources/astra.csv[] === Debezium Oracle -The {product} Oracle source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/mysql.html#oracle-connector-properties[Debezium Oracle connector properties] for a complete list. +The Astra Streaming Oracle source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/mysql.html#oracle-connector-properties[Debezium Oracle connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sources/debezium-postgres.adoc b/modules/pulsar-io/pages/connectors/sources/debezium-postgres.adoc index 26a92cc..f05326d 100644 --- a/modules/pulsar-io/pages/connectors/sources/debezium-postgres.adoc +++ b/modules/pulsar-io/pages/connectors/sources/debezium-postgres.adoc @@ -4,7 +4,7 @@ The PostgreSQL connector produces a change event for every row-level insert, update, and delete operation that it captures, and sends change event records for each table in a separate {pulsar-reg} topic. -{product} currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported PostgreSQL versions, please refer to the +Astra Streaming currently supports {pulsar} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported PostgreSQL versions, please refer to the https://debezium.io/releases/{debezium-version}/[Debezium documentation]. == Get Started @@ -23,7 +23,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -34,7 +34,7 @@ include::example$connectors/sources/astra.csv[] These values are provided in the "configs" area. -The {product} PostgreSQL source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/postgresql.html#postgresql-connector-properties[Debezium PostgreSQL connector properties] for a complete list. +The Astra Streaming PostgreSQL source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/postgresql.html#postgresql-connector-properties[Debezium PostgreSQL connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sources/debezium-sqlserver.adoc b/modules/pulsar-io/pages/connectors/sources/debezium-sqlserver.adoc index 28fcf79..1ad9c47 100644 --- a/modules/pulsar-io/pages/connectors/sources/debezium-sqlserver.adoc +++ b/modules/pulsar-io/pages/connectors/sources/debezium-sqlserver.adoc @@ -6,7 +6,7 @@ The Debezium SQL Server connector is based on the change data capture feature av The SQL Server capture process monitors designated databases and tables and stores changes into specifically created change tables with stored procedure facades. -{product} currently supports {pulsar-reg} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported SQL Server versions, please refer to the +Astra Streaming currently supports {pulsar-reg} {pulsar-version}, which uses Debezium {debezium-version} libraries. For a list of supported SQL Server versions, please refer to the https://debezium.io/releases/{debezium-version}/[Debezium documentation]. == Get Started @@ -51,7 +51,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -62,7 +62,7 @@ include::example$connectors/sources/astra.csv[] These values are provided in the "configs" area. -The {product} SQL Server source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/sqlserver.html#sqlserver-connector-properties[Debezium SQL Server connector properties] for a complete list. +The Astra Streaming SQL Server source connector supports all configuration properties provided in Debezium's connector. Please refer to https://debezium.io/documentation/reference/{debezium-version}/connectors/sqlserver.html#sqlserver-connector-properties[Debezium SQL Server connector properties] for a complete list. == What's next? diff --git a/modules/pulsar-io/pages/connectors/sources/kafka.adoc b/modules/pulsar-io/pages/connectors/sources/kafka.adoc index 287f4a9..d27fc37 100644 --- a/modules/pulsar-io/pages/connectors/sources/kafka.adoc +++ b/modules/pulsar-io/pages/connectors/sources/kafka.adoc @@ -22,7 +22,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -60,5 +60,5 @@ The deserializer is set by a specific implementation of https://github.com/apach |=== -The {product} Kafka source connector supports all configuration properties provided by {pulsar}. +The Astra Streaming Kafka source connector supports all configuration properties provided by {pulsar}. For a complete list, see the https://pulsar.apache.org/docs/io-kafka-source#property[Kafka source connector properties]. diff --git a/modules/pulsar-io/pages/connectors/sources/kinesis.adoc b/modules/pulsar-io/pages/connectors/sources/kinesis.adoc index bb601ea..9c5bde9 100644 --- a/modules/pulsar-io/pages/connectors/sources/kinesis.adoc +++ b/modules/pulsar-io/pages/connectors/sources/kinesis.adoc @@ -22,7 +22,7 @@ include::partial$connectors/sources/monitoring.adoc[] There are two sets of parameters that support source connectors. -=== {product} +=== Astra Streaming [%header,format=csv,cols="2,1,1,3"] |=== @@ -71,5 +71,5 @@ If `awsCredentialPluginName` set to empty, the Kinesis sink creates a default AW |=== -The {product} Kinesis source connector supports all configuration properties provided by {pulsar}. +The Astra Streaming Kinesis source connector supports all configuration properties provided by {pulsar}. For a complete list, see the https://pulsar.apache.org/docs/io-kinesis-source#configuration[Kinesis source connector properties]. diff --git a/modules/pulsar-io/partials/connectors/sinks/monitoring.adoc b/modules/pulsar-io/partials/connectors/sinks/monitoring.adoc index 0dab3e4..14ec323 100644 --- a/modules/pulsar-io/partials/connectors/sinks/monitoring.adoc +++ b/modules/pulsar-io/partials/connectors/sinks/monitoring.adoc @@ -261,4 +261,4 @@ Status response for individual connector instance: === Metrics -{product} exposes Prometheus formatted metrics for every connector. Refer to the xref:astra-streaming:operations:astream-scrape-metrics.adoc[scrape metrics with Prometheus] page for more detail. \ No newline at end of file +Astra Streaming exposes Prometheus formatted metrics for every connector. Refer to the xref:astra-streaming:operations:astream-scrape-metrics.adoc[scrape metrics with Prometheus] page for more detail. \ No newline at end of file diff --git a/modules/pulsar-io/partials/connectors/sources/monitoring.adoc b/modules/pulsar-io/partials/connectors/sources/monitoring.adoc index c9e4d67..c3bcf2f 100644 --- a/modules/pulsar-io/partials/connectors/sources/monitoring.adoc +++ b/modules/pulsar-io/partials/connectors/sources/monitoring.adoc @@ -193,4 +193,4 @@ Status response for individual connector instance: === Metrics -{product} exposes Prometheus formatted metrics for every connector. Refer to xref:astra-streaming:operations:astream-scrape-metrics.adoc[scrape metrics with Prometheus] page for more detail. \ No newline at end of file +Astra Streaming exposes Prometheus formatted metrics for every connector. Refer to xref:astra-streaming:operations:astream-scrape-metrics.adoc[scrape metrics with Prometheus] page for more detail. \ No newline at end of file diff --git a/modules/subscriptions/partials/subscription-prereq.adoc b/modules/subscriptions/partials/subscription-prereq.adoc index 6cacdae..f5070da 100644 --- a/modules/subscriptions/partials/subscription-prereq.adoc +++ b/modules/subscriptions/partials/subscription-prereq.adoc @@ -6,11 +6,11 @@ To run this example, you'll need: * https://openjdk.java.net/install/[Java OpenJDK 11] -* A configured {product} instance with at least one streaming tenant and one topic. See the xref:astra-streaming:getting-started:index.adoc[{product} quick start] for instructions. +* A configured Astra Streaming instance with at least one streaming tenant and one topic. See the xref:astra-streaming:getting-started:index.adoc[Astra Streaming quick start] for instructions. * A local clone of the https://github.com/datastax/pulsar-subscription-example[{company} {pulsar-short} Subscription Example repository] -* Modify the `src/main/resources/application.properties` in the `pulsar-subscription-example` repo to connect to your {product} cluster, as below: +* Modify the `src/main/resources/application.properties` in the `pulsar-subscription-example` repo to connect to your Astra Streaming cluster, as below: + [source,bash] ---- diff --git a/modules/use-cases-architectures/pages/change-data-capture/consuming-change-data.adoc b/modules/use-cases-architectures/pages/change-data-capture/consuming-change-data.adoc index 56a295b..2d881b8 100644 --- a/modules/use-cases-architectures/pages/change-data-capture/consuming-change-data.adoc +++ b/modules/use-cases-architectures/pages/change-data-capture/consuming-change-data.adoc @@ -14,7 +14,7 @@ Each client handles message consumption a little differently but there is one ov Below are example implementations for each runtime consuming messages from the CDC data topic. -While these examples are in the `astra-streaming-examples` repository, they are not {product}-specific. +While these examples are in the `astra-streaming-examples` repository, they are not Astra Streaming-specific. You can use these examples to consume CDC data topics in your own {cass-short}/{pulsar-short} clusters. * svg:common::icons/logos/csharp.svg[role="icon text-xl",name="C#"] https://github.com/datastax/astra-streaming-examples/blob/master/csharp/astra-cdc/Program.cs[{csharp} CDC project example] @@ -27,7 +27,7 @@ You can use these examples to consume CDC data topics in your own {cass-short}/{ It is very common to have a function consuming the CDC data. Functions usually perform additional processing on the data and pass it to another topic. Similar to a client consumer, it will need to deserialize the message data. Below are examples of different functions consuming messages from the CDC data topic. -While these examples are in the `astra-streaming-examples` repository, they are not {product}-specific. You can use these examples to consume CDC data topics in your own {cass-short}/{pulsar-short} clusters. +While these examples are in the `astra-streaming-examples` repository, they are not Astra Streaming-specific. You can use these examples to consume CDC data topics in your own {cass-short}/{pulsar-short} clusters. * svg:common::icons/logos/go.svg[role="icon text-xl",name="Go"] https://github.com/datastax/astra-streaming-examples/blob/master/go/astra-cdc/main/main.go[Golang CDC project example] * svg:common::icons/logos/java.svg[role="icon text-xl",name="Java"] https://github.com/datastax/astra-streaming-examples/blob/master/java/astra-cdc/javaexamples/functions/CDCFunction.java[Java CDC function example] diff --git a/modules/use-cases-architectures/pages/starlight/jms/index.adoc b/modules/use-cases-architectures/pages/starlight/jms/index.adoc index 2758aae..c6c8221 100644 --- a/modules/use-cases-architectures/pages/starlight/jms/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/jms/index.adoc @@ -12,16 +12,16 @@ To get started, you need the following: * A working {pulsar-short} cluster. * Access to the cluster's admin port 8080 and the binary port 6650. -This guide uses {product} to get started with Starlight for JMS. +This guide uses Astra Streaming to get started with Starlight for JMS. For more information, see the xref:starlight-for-jms:ROOT:index.adoc[Starlight for JMS documentation]. [tabs] ==== -{product}:: +Astra Streaming:: + -- -If you don't have a tenant in {product}, follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. +If you don't have a tenant in Astra Streaming, follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. -- Luna Streaming:: @@ -38,9 +38,9 @@ Using a standalone cluster? The Starlight for JMS docs provide the "xref:starlig == Messaging with Starlight for JMS -=== Retrieve connection properties in {product} +=== Retrieve connection properties in Astra Streaming -. In the {product} portal "Connect" tab, the "{pulsar-short}" area provides important connection information. +. In the Astra Streaming portal "Connect" tab, the "{pulsar-short}" area provides important connection information. . Scroll down to the "Tenant Details" area to find your {pulsar-short} connection information. + @@ -51,7 +51,7 @@ image:pulsar-client-settings.png[] This example uses Maven for the project structure. If you prefer Gradle or another tool, this code should still be a good fit. -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[{product} examples repository]. +For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. . Create a new Maven project. + @@ -81,7 +81,7 @@ cd StarlightForJMSClient If you cloned the example repository, replace the entire contents of the file with the following code. Your editor will report an error because this isn't a complete script yet. + -Replace placeholders with the values you previously retrieved from {product}. +Replace placeholders with the values you previously retrieved from Astra Streaming. + [source,java] ---- diff --git a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc index e7a18cd..2767930 100644 --- a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc @@ -20,14 +20,14 @@ Choose the option that best fits your needs. [tabs] ==== -{product}:: +Astra Streaming:: + -- If you want a working Kafka extension as quickly as possible, this is your best bet. This is also a good option for those that already have a streaming tenant and are looking to extend it. -. Sign in to your {product-short} account and navigate to your streaming tenant. +. Sign in to your Astra account and navigate to your streaming tenant. + TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. @@ -39,12 +39,170 @@ TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-sta . Select the "Enable Kafka" button to confirm your understanding. -Your {product} tenant is ready for prime time! Continue to the next section of the guide to see it in action. +Your Astra Streaming tenant is ready for prime time! Continue to the next section of the guide to see it in action. -- Luna Streaming:: + -- The {kafka-for-astra} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. The Luna helm chart makes deploying the Kafka extension quite easy. Follow the "xref:luna-streaming:components:starlight-for-kafka.adoc[]" guide to create a simple {pulsar-short} cluster with the {kafka-for-astra} extension ready for use. + +== Use Starlight for Kafka with Luna Streaming + +Starlight for Kafka brings the native Apache Kafka protocol support to {pulsar} by introducing a Kafka protocol handler on {pulsar-short} brokers. +By adding the Starlight for Kafka protocol handler to your {pulsar-short} cluster, you can migrate your existing Kafka applications and services to {pulsar-short} without modifying the code. + +The following steps explain how to deploy a Luna Streaming Helm chart with the Starlight for Kafka protocol handler extension. + +=== Prerequisites + +* https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) +* https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[Kafka CLI] (we used version 3.3.1) +* https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) +* Enough access to a K8s cluster to create a namespace, deployments, and pods + +=== Install Luna Streaming Helm chart + +. Add the {company} Helm chart repo to your Helm store. ++ +[source,shell] +---- +helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart +---- + +. Install the Helm chart using a minimalist values file. +This command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart, within the K8s namespace `datastax-pulsar`. +The minimal cluster creates only the essential components and has no ingress or load balanced services. ++ +[source,shell] +---- +VALUES_URL="https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main/starlight-for-kafka/values.yaml" +helm install \ + --namespace datastax-pulsar \ + --create-namespace \ + --values $VALUES_URL \ + --version 3.0.4 \ + my-pulsar-cluster \ + datastax-pulsar/pulsar +---- + +. Wait for the broker pod to be in a running state. You might see a few restarts as your components start up. ++ +[source,shell] +---- +kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s +---- + +=== Forward service port + +You'll need to interact with a few of the services in the K8s cluster. +Map a few ports to those services. + +In a new terminal, port forward {pulsar-short}'s admin service: + +[source,shell] +---- +kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 +---- + +In a separate terminal window, port forward the Starlight for Kafka serivce: + +[source,shell] +---- +kubectl port-forward -n datastax-pulsar service/pulsar-proxy 9092:9092 +---- + +=== Inspect the created namespaces and topics + +The Luna Streaming Helm Chart automatically creates a tenant named "public" and a namespace within that tenant named "default". + +The Starlight for Kafka extension creates a few namespaces and topics to function correctly. + +List the namespaces in the "public" tenant to see what was created: + +[source,shell] +---- +~/apache-pulsar-2.10.1$ ./bin/pulsar-admin namespaces list public +---- + +The output should be similar to the following. + +[source,shell] +---- +public/__kafka +public/__kafka_producerid +public/default +---- + +Notice the namespaces prefixed with "__kafka". +These are used by the service for different functions. +To learn more about Starlight for Kafka operations, see the S4K xref:starlight-for-kafka:ROOT:index.adoc[documentation]. + +=== Produce a message with the Kafka CLI + +If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. +Only the admin port and the Kafka port are open. +To further show how native Starlight for Kafka is to {pulsar-short}, we will use the Kafka CLI to produce and consume messages from {pulsar-short}. + +From within the Kafka directory, run the following command to start the shell: + +[source,shell] +---- +~/kafka_2.13-3.3.1$ ./bin/kafka-console-producer.sh --topic quickstart --bootstrap-server localhost:9092 +---- + +Type a message, press Enter to send it, then Ctrl-C to exit the producer shell. + +[source,shell] +---- +This my first message +---- + +Wait a second! We never created a topic! And where did the "quickstart" topic come from?! + +The default behavior of Starlight for Kafka is to create a new single partition, persistent topic when one is not present. +You can configure this behavior and many other S4K parameters in the https://github.com/datastaxdevs/luna-streaming-examples/blob/main/starlight-for-kafka/values.yaml[Helm chart]. +Learn more about the configuration values xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[here]. + +Let's have a look at the topic that was created. From your {pulsar-short} home folder, run the following command: + +[source,shell] +---- +~/apache-pulsar-2.10.1$ ./bin/pulsar-admin topics list public/default +---- + +The output will include the newly created topic: + +[source,shell] +---- +persistent://public/default/quickstart-partition-0 +---- + +== Consume the new message with the Kafka CLI + +Let's use the Kafka CLI to consume the message we just produced. + +Start the consumer shell from the Kafka home folder with the following command: + +[source,shell] +---- +~/kafka_2.13-3.3.1$ ./bin/kafka-console-consumer.sh --topic quickstart --from-beginning --bootstrap-server localhost:9092 +---- + +The data of our new message will be output. Enter Ctrl-C to exit the shell. + +[source,shell] +---- +This my first message +---- + +=== Next steps + +Kafka users and existing applications using Kafka can enjoy the many benefits of a {pulsar-short} cluster, while never having to change tooling or libraries. +Other folks that are more comfortable with {pulsar-short} tooling and clients can also interact with the same topics. Together, new and legacy applications work together to create modern solutions. + +Here are links to other guides and resource you might be interested in. + +* xref:streaming-learning:use-cases-architectures:starlight/kafka/index.adoc[Messaging with Starlight for Kafka] -- Self Managed:: + @@ -57,14 +215,14 @@ Already have your own {pulsar-short} cluster? Or maybe you're using a standalone {kafka-for-astra} supports quite a few different use cases. With a {pulsar-short} cluster between producers and consumers you can interchange the type of producer and consumer to fit your needs. -*The below examples are using an {product} tenant as the Kafka bootstrap server.* If you are using Luna Streaming or a self-managed tenant, switch the bootstrap server URL for your own. +*The below examples are using an Astra Streaming tenant as the Kafka bootstrap server.* If you are using Luna Streaming or a self-managed tenant, switch the bootstrap server URL for your own. -=== Retrieve Kafka connection properties in {product} +=== Retrieve Kafka connection properties in Astra Streaming -In the {product} portal "Connect" tab, the "kafka" area provides important connection information. +In the Astra Streaming portal "Connect" tab, the "kafka" area provides important connection information. You will need this connection information to create a working Kafka client or use the CLI. -image:kafka-client-settings.png[{product} kafka settings] +image:kafka-client-settings.png[Astra Streaming kafka settings] TIP: Click the clipboard icon to copy the Kafka connection values, as well as a working token to paste in code. @@ -78,7 +236,7 @@ Kafka CLI:: Download the latest Kafka distribution https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[here]. With the tarball extracted, the producer and consumer CLIs are in the 'bin' folder. -. To get started, let's set a few variables. If you've completed our "xref:astra-streaming:getting-started:index.adoc[Getting started with {product}]" guide, the below values will be a perfect fit for your existing tenant. +. To get started, let's set a few variables. If you've completed our "xref:astra-streaming:getting-started:index.adoc[Getting started with Astra Streaming]" guide, the below values will be a perfect fit for your existing tenant. + [source,shell] ---- @@ -127,7 +285,7 @@ Kafka Client (Java):: This example uses Maven for the project structure. If you prefer Gradle or another tool, this code should still be a good fit. -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[{product} examples repository]. +For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. . Create a new Maven project. + @@ -157,7 +315,7 @@ cd StarlightForKafkaClient If you cloned the example repo, replace the entire contents of `App.java` with the following code. Your editor will report an error because this isn't a complete script yet. + -Replace placeholders with the values you previously retrieved from {product}. +Replace placeholders with the values you previously retrieved from Astra Streaming. + [source,java] ---- diff --git a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc index fa704ec..c12db8f 100644 --- a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc @@ -21,12 +21,12 @@ Choose the option that best fits your needs. [tabs] ==== -{product}:: +Astra Streaming:: + -- If you want a working RabbitMQ extension as quickly as possible, this is your best bet. This is also a good option for those that already have a streaming tenant and are looking to extend it. -. Sign in to your {product-short} account and navigate to your streaming tenant. +. Sign in to your Astra account and navigate to your streaming tenant. + TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. @@ -38,12 +38,137 @@ TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-sta . Click the "Enable RabbitMQ" button to confirm your understanding. -Your {product} tenant is ready for prime time! Continue to the next section of the guide to see it in action. +Your Astra Streaming tenant is ready for prime time! Continue to the next section of the guide to see it in action. -- Luna Streaming:: + -- The {starlight-rabbitmq} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. The Luna helm chart makes deploying the Kafka extension quite easy. Follow the "xref:luna-streaming:components:starlight-for-rabbitmq.adoc[]" guide to create a simple {pulsar-short} cluster with the {starlight-rabbitmq} extension ready for use. + +== Use Starlight for RabbitMQ with Luna Streaming + +Starlight for RabbitMQ brings native https://www.rabbitmq.com/[RabbitMQ] protocol support to https://pulsar.apache.org/[{pulsar-reg}] by introducing a RabbitMQ protocol handler on {pulsar-short} brokers or {pulsar-short} proxies. +By adding the Starlight for RabbitMQ protocol handler to your {pulsar-short} cluster, you can migrate your existing RabbitMQ applications and services to {pulsar-short} without modifying the code. + +The following steps explain how to deploy a Luna Streaming Helm chart with the Starlight for RabbitMQ protocol handler extension. + +=== Prerequisites + +* https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) +* https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) +* Python (we used version 3.8.10) +* Enough access to a K8s cluster to create a namespace, deployments, and pods + +=== Install Luna Streaming Helm chart + +. Add the {company} Helm chart repo to your Helm store. ++ +[source,shell] +---- +helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart +---- + +. Install the Helm chart using a minimalist values file. +This command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart, within the K8s namespace `datastax-pulsar`. +The minimal cluster creates only the essential components and has no ingress or load balanced services. ++ +[source,shell] +---- +VALUES_URL="https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main/starlight-for-rabbitmq/values.yaml" +helm install \ + --namespace datastax-pulsar \ + --create-namespace \ + --values $VALUES_URL \ + --version 3.0.4 \ + my-pulsar-cluster \ + datastax-pulsar/pulsar +---- + +. Wait for the broker pod to be in a running state. You might see a few restarts as your components start up. ++ +[source,shell] +---- +kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s +---- + +=== Forward service port + +You'll need to interact with a few of the services in the K8s cluster. +Map a few ports to those services. + +In a new terminal, port forward {pulsar-short}'s admin service: + +[source,shell] +---- +kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 +---- + +In a separate terminal window, port forward the Starlight for RabbitMQ service: + +[source,shell] +---- +kubectl port-forward -n datastax-pulsar service/pulsar-proxy 5672:5672 +---- + +=== Produce a message with the RabbitMQ Python client + +If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. +Only the admin port and the RabbitMQ port are open. +To further demonstrate how native Starlight for RabbitMQ is, we will use the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. + +Save the following Python script to a safe place as `test-queue.py`. +The script assumes you have opened the localhost:5672 port. + +[source,python] +---- +#!/usr/bin/env python +import pika + +connection = pika.BlockingConnection(pika.ConnectionParameters(port=5672)) +channel = connection.channel() + +try: + channel.queue_declare("test-queue") + print("created test-queue queue") + + channel.basic_publish(exchange="", routing_key="test-queue", body="test".encode('utf-8')) + print("published message test") + + _, _, res = channel.basic_get(queue="test-queue", auto_ack=True) + assert res is not None, "should have received a message" + print("received message: " + res.decode()) + + channel.queue_delete("test-queue") + print("deleted test-queue queue") + +finally: + connection.close() +---- + +Open a terminal and return to the safe place where you saved the Python script. +Run the following command to execute the Python program. + +[source,shell] +---- +python ./test-queue.py +---- + +The output should look like the following. + +[source,shell] +---- +created test-queue queue +published message test +received message: test +deleted test-queue queue +---- + +=== Next steps + +The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. +Your application will now "talk" to {pulsar-short} as if it were a real RabbitMQ host. + +* xref:streaming-learning:use-cases-architectures:starlight/rabbitmq/index.adoc[Messaging with Starlight for RabbitMQ] -- Self Managed:: + @@ -57,14 +182,14 @@ Already have your own {pulsar-short} Cluster? Or maybe you're using a standalone {starlight-rabbitmq} supports quite a few different use cases. With a {pulsar-short} cluster between publishers and consumers you can interchange the type of publisher and consumer to fit your needs. -*The below examples are using an {product} tenant as the AMQP listener.* If you are using Luna Streaming or a self-managed tenant, switch the listener URL for your own. +*The below examples are using an Astra Streaming tenant as the AMQP listener.* If you are using Luna Streaming or a self-managed tenant, switch the listener URL for your own. -=== Retrieve RabbitMQ connection properties in {product} +=== Retrieve RabbitMQ connection properties in Astra Streaming -In the {product} portal "Connect" tab, the "RabbitMQ" area provides important connection information. +In the Astra Streaming portal "Connect" tab, the "RabbitMQ" area provides important connection information. You will need this connection information to create a working RabbitMQ client or use the CLI. -image:rabbitmq-client-settings.png[{product} RabbitMQ settings] +image:rabbitmq-client-settings.png[Astra Streaming RabbitMQ settings] TIP: Click the clipboard icon to copy the RabbitMQ connection values, as well as a working token to paste in code. @@ -73,7 +198,7 @@ TIP: Click the clipboard icon to copy the RabbitMQ connection values, as well as This example uses Maven for the project structure for a Rabbit MQ Java client. If you prefer Gradle or another tool, this code should still be a good fit. -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[{product} examples repository]. +For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. . Create a new Maven project. + @@ -103,7 +228,7 @@ cd StarlightForRabbitMqClient If you cloned the example repo, replace the entire contents with the following code. Your editor will report errors because this isn't a complete program yet. + -Replace placeholders with the values you previously retrieved from {product}. +Replace placeholders with the values you previously retrieved from Astra Streaming. + [source,java] ---- From 2eae7afba90fb8caccfe9323b40aaf88f2c2258c Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:29:03 -0800 Subject: [PATCH 3/9] revising unified pages b4 move to starlight repos --- antora.yml | 2 +- modules/ROOT/nav.adoc | 6 +- .../pages/starlight/kafka/index.adoc | 222 ++++++++++------ .../pages/starlight/rabbitmq/index.adoc | 248 +++++++++++++----- 4 files changed, 336 insertions(+), 142 deletions(-) diff --git a/antora.yml b/antora.yml index 54b8ec9..448e154 100644 --- a/antora.yml +++ b/antora.yml @@ -19,7 +19,7 @@ asciidoc: pulsar-version: '3.1' #DO NOT INCLUDE PATCH VERSION .. debezium-version: '1.7' astra-streaming-examples-repo: 'https://raw.githubusercontent.com/datastax/astra-streaming-examples/master' - kafka-for-astra: 'Starlight for Kafka' + starlight-kafka: 'Starlight for Kafka' starlight-rabbitmq: 'Starlight for RabbitMQ' cass: Apache Cassandra cass-short: Cassandra diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 28c1349..0ad3b74 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -7,9 +7,9 @@ * xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with Astra Streaming] .Migrate to {pulsar} -* xref:starlight-for-kafka:ROOT:index.adoc[] -* xref:starlight-for-rabbitmq:ROOT:index.adoc[] -* xref:starlight-for-jms:ROOT:index.adoc[] +* xref:starlight-for-kafka:ROOT:index.adoc[{starlight-kafka}] +* xref:starlight-for-rabbitmq:ROOT:index.adoc[{starlight-rabbitmq}] +* xref:starlight-for-jms:ROOT:index.adoc[Starlight for JMS] .APIs and References * Connectors diff --git a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc index 2767930..b2ec8fc 100644 --- a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc @@ -1,68 +1,134 @@ -= Getting started with the {kafka-for-astra} extension -:navtitle: {kafka-for-astra} -:description: Learn how to get started using the {kafka-for-astra} extension with {pulsar-reg} and get hands on with Kafka producer and consumer interacting with a topic. += Get started with the {starlight-kafka} extension +:navtitle: {starlight-kafka} +:description: Use the {starlight-kafka} extension with {pulsar-reg}. -{kafka-for-astra} brings the native Apache Kafka(R) protocol support to {pulsar-reg} by introducing a Kafka protocol handler on {pulsar-short} brokers. By adding the {kafka-for-astra} protocol handler to your existing {pulsar-short} cluster, you can migrate your existing Kafka applications and services to {pulsar-short} without modifying the code. +The https://github.com/datastax/starlight-for-kafka[{starlight-kafka} extension] brings the native Apache Kafka(R) protocol support to {pulsar-reg} by introducing a Kafka protocol handler on {pulsar-short} brokers. +By adding the {starlight-kafka} protocol handler to your existing {pulsar-short} cluster, you can migrate your existing Kafka applications and services to {pulsar-short} without modifying the code. -If source code is your thing, visit the https://github.com/datastax/starlight-for-kafka[project's repo on GitHub]. +For more information about the {starlight-kafka} architecture, see the xref:starlight-for-kafka:ROOT:index.adoc[{starlight-kafka} documentation]. -== Architecture reference +image:s4k-architecture.png[{starlight-kafka} Architecture] -If you would like to get deep into how {kafka-for-astra} works, xref:starlight-for-kafka:ROOT:index.adoc[read the docs]. +== Establish the Kafka protocol handler -image:s4k-architecture.png[{kafka-for-astra} Architecture] - -== Establishing the Kafka protocol handler - -Before a Kafka client can interact with your {pulsar-short} cluster, you need the {kafka-for-astra} protocol handler installed in the cluster. +Before a Kafka client can interact with your {pulsar-short} cluster, you need the {starlight-kafka} protocol handler installed in the cluster. Installation looks a bit different depending on where your {pulsar-short} cluster is running. Choose the option that best fits your needs. [tabs] -==== +====== Astra Streaming:: + -- +Get started producing and consuming Kafka messages on a {pulsar-short} cluster. + +=== Enable {starlight-kafka} on an Astra Streaming tenant -If you want a working Kafka extension as quickly as possible, this is your best bet. -This is also a good option for those that already have a streaming tenant and are looking to extend it. +. Sign in to your Astra account, go to Astra Streaming, and then xref:astra-streaming:getting-started:index.adoc[create a tenant] or click an existing tenant. -. Sign in to your Astra account and navigate to your streaming tenant. +. Go to your tenant's **Connect** tab, select **Kafka**, and then click **Enable Kafka**. + +. Review the information about the {starlight-kafka} extension, and then click **Enable Kafka** to confirm that you want to enable this extension on your tenant. + -TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. +[IMPORTANT] +==== +This action creates a configuration file and the following three namespaces in your Astra Streaming tenant automatically: -. Go to the "Connect" tab and choose the "Kafka" option. +* `kafka`: Produces and consumes messages +* `+__kafka+`: Supports required Kafka functionality +* `+__kafka_unlimited+`: Stores metadata + +These namespaces are required for the {starlight-kafka} extension to function properly. +These are permanent namespaces that cannot be removed except by deleting the entire tenant and all of its data. +==== -. Click "Enable Kafka". +. Save the Kafka configuration details to a file named `ssl.properties`. +The actual values depend on your Astra Streaming tenant's configuration and cloud provider. ++ +.ssl.properties +[source,plain,subs="+quotes"] +---- +username: **TENANT_NAME** +password: token:*** +bootstrap.servers: kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 +schema.registry.url: https://kafka-**PROVIDER**-**REGION**.streaming.datastax.com:8081 +security.protocol: SASL_SSL +sasl.mechanism: PLAIN +---- -. A message will let you know of the additions (and restrictions) that come with using {kafka-for-astra}. +=== Connect Kafka and {pulsar-short} +// Move to messaging section? +This example uses tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball]. -. Select the "Enable Kafka" button to confirm your understanding. +. In Astra Streaming, create a new topic in the `kafka` namespace. ++ +No specific name is required. -Your Astra Streaming tenant is ready for prime time! Continue to the next section of the guide to see it in action. --- -Luna Streaming:: +. In your Kafka instance, move your `ssl.properties` file to your `Kafka_2.13-3.1.0/config` folder. +These values are required for SSL encryption. +The exact values depend on your Astra Streaming tenant's configuration. + --- -The {kafka-for-astra} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. The Luna helm chart makes deploying the Kafka extension quite easy. Follow the "xref:luna-streaming:components:starlight-for-kafka.adoc[]" guide to create a simple {pulsar-short} cluster with the {kafka-for-astra} extension ready for use. +[source,properties,subs="+quotes"] +---- +bootstrap.servers=kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 +security.protocol=SASL_SSL +sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username='**TENANT_NAME**' password='token:{pulsar tenant token}' +sasl.mechanism=PLAIN +session.timeout.ms=45000 +---- -== Use Starlight for Kafka with Luna Streaming +. In the `Kafka` directory, create a Kafka producer to produce messages on the topic you created in the `kafka` namespace: ++ +[source,shell,subs="+quotes"] +---- +bin/kafka-console-producer \ +--broker-list kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ +--topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ +--producer.config config/ssl.properties +---- ++ +Once the producer is ready, it accepts standard input from the user: ++ +[source,console] +---- +>hello pulsar +---- + +. In a new terminal window, create a Kafka consumer to consume messages from the beginning of your topic: ++ +[source,shell] +---- +bin/kafka-console-consumer \ +--bootstrap-server kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ +--topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ +--consumer.config config/ssl.properties \ +--from-beginning +---- -Starlight for Kafka brings the native Apache Kafka protocol support to {pulsar} by introducing a Kafka protocol handler on {pulsar-short} brokers. -By adding the Starlight for Kafka protocol handler to your {pulsar-short} cluster, you can migrate your existing Kafka applications and services to {pulsar-short} without modifying the code. +. Send a few messages in the terminal to generate traffic on the tenant. -The following steps explain how to deploy a Luna Streaming Helm chart with the Starlight for Kafka protocol handler extension. +. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. ++ +To verify that your Kafka messages are being produced and consumed in your Astra Streaming {pulsar-short} cluster, check the **Data In** metrics. +The number of messages should be, at least, equal to the number of messages you sent with your Kafka producer on the command line. +-- + +Luna Streaming:: ++ +-- +The {starlight-kafka} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. +The Luna Helm chart simplifies deployment of the Kafka extension. -=== Prerequisites +The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the Starlight for Kafka protocol handler extension. +. Make sure you meet the following prerequisites: ++ * https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) * https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[Kafka CLI] (we used version 3.3.1) * https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) * Enough access to a K8s cluster to create a namespace, deployments, and pods -=== Install Luna Streaming Helm chart - -. Add the {company} Helm chart repo to your Helm store. +. Add the {company} Helm chart repo to your Helm store: + [source,shell] ---- @@ -85,60 +151,59 @@ helm install \ datastax-pulsar/pulsar ---- -. Wait for the broker pod to be in a running state. You might see a few restarts as your components start up. +. Wait for the broker pod to reach a running state. +It might restart a few times while your components start up. + [source,shell] ---- kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ---- -=== Forward service port - -You'll need to interact with a few of the services in the K8s cluster. -Map a few ports to those services. - -In a new terminal, port forward {pulsar-short}'s admin service: - +. Forward service ports so you can interact with certain services on the Kubernetes cluster: ++ +.. In a new terminal, port forward {pulsar-short}'s admin service: ++ [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ---- -In a separate terminal window, port forward the Starlight for Kafka serivce: - +.. In a separate terminal window, port forward the Starlight for Kafka service: ++ [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-proxy 9092:9092 ---- -=== Inspect the created namespaces and topics - -The Luna Streaming Helm Chart automatically creates a tenant named "public" and a namespace within that tenant named "default". - -The Starlight for Kafka extension creates a few namespaces and topics to function correctly. - -List the namespaces in the "public" tenant to see what was created: - +. Inspect the created namespaces and topics. ++ +The Luna Streaming Helm Chart automatically creates a tenant named `public` and a namespace within that tenant named `default`. +The Starlight for Kafka extension creates a few namespaces and topics automatically because these are required for the extension to function correctly. ++ +List the namespaces in the `public` tenant: ++ [source,shell] ---- -~/apache-pulsar-2.10.1$ ./bin/pulsar-admin namespaces list public +~/apache-pulsar-3.1.3$ ./bin/pulsar-admin namespaces list public ---- - -The output should be similar to the following. - ++ +The output should be similar to the following: ++ [source,shell] ---- public/__kafka public/__kafka_producerid public/default ---- - -Notice the namespaces prefixed with "__kafka". ++ +The automatically generated namespaces prefixed with "+__kafka+". These are used by the service for different functions. -To learn more about Starlight for Kafka operations, see the S4K xref:starlight-for-kafka:ROOT:index.adoc[documentation]. +For more information, see the xref:starlight-for-kafka:ROOT:index.adoc[Starlight for Kafka documentation]. === Produce a message with the Kafka CLI +//Move to messaging section + If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. Only the admin port and the Kafka port are open. To further show how native Starlight for Kafka is to {pulsar-short}, we will use the Kafka CLI to produce and consume messages from {pulsar-short}. @@ -157,9 +222,7 @@ Type a message, press Enter to send it, then Ctrl-C to exit the producer shell. This my first message ---- -Wait a second! We never created a topic! And where did the "quickstart" topic come from?! - -The default behavior of Starlight for Kafka is to create a new single partition, persistent topic when one is not present. +A `quickstart` topic is created automatically because the default behavior of Starlight for Kafka is to create a new single partition, persistent topic when one is not present. You can configure this behavior and many other S4K parameters in the https://github.com/datastaxdevs/luna-streaming-examples/blob/main/starlight-for-kafka/values.yaml[Helm chart]. Learn more about the configuration values xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[here]. @@ -167,7 +230,7 @@ Let's have a look at the topic that was created. From your {pulsar-short} home f [source,shell] ---- -~/apache-pulsar-2.10.1$ ./bin/pulsar-admin topics list public/default +~/apache-pulsar-3.1.3$ ./bin/pulsar-admin topics list public/default ---- The output will include the newly created topic: @@ -178,7 +241,7 @@ persistent://public/default/quickstart-partition-0 ---- == Consume the new message with the Kafka CLI - +//Move to messaging section Let's use the Kafka CLI to consume the message we just produced. Start the consumer shell from the Kafka home folder with the following command: @@ -188,37 +251,40 @@ Start the consumer shell from the Kafka home folder with the following command: ~/kafka_2.13-3.3.1$ ./bin/kafka-console-consumer.sh --topic quickstart --from-beginning --bootstrap-server localhost:9092 ---- -The data of our new message will be output. Enter Ctrl-C to exit the shell. +The data of our new message will be output: [source,shell] ---- This my first message ---- -=== Next steps - -Kafka users and existing applications using Kafka can enjoy the many benefits of a {pulsar-short} cluster, while never having to change tooling or libraries. -Other folks that are more comfortable with {pulsar-short} tooling and clients can also interact with the same topics. Together, new and legacy applications work together to create modern solutions. - -Here are links to other guides and resource you might be interested in. - -* xref:streaming-learning:use-cases-architectures:starlight/kafka/index.adoc[Messaging with Starlight for Kafka] +Enter Ctrl-C to exit the shell. -- + Self Managed:: + -- -Already have your own {pulsar-short} cluster? Or maybe you're using a standalone cluster? {kafka-for-astra} can easily be a part of that cluster! Follow the "xref:starlight-for-kafka:installation:starlight-kafka-quickstart.adoc[]" guide. +Already have your own {pulsar-short} cluster? Or maybe you're using a standalone cluster? {starlight-kafka} can easily be a part of that cluster! Follow the "xref:starlight-for-kafka:installation:starlight-kafka-quickstart.adoc[]" guide. -- -==== +====== -== Messaging with {kafka-for-astra} +== Message with {starlight-kafka} -{kafka-for-astra} supports quite a few different use cases. With a {pulsar-short} cluster between producers and consumers you can interchange the type of producer and consumer to fit your needs. +{starlight-kafka} supports quite a few different use cases. With a {pulsar-short} cluster between producers and consumers you can interchange the type of producer and consumer to fit your needs. -*The below examples are using an Astra Streaming tenant as the Kafka bootstrap server.* If you are using Luna Streaming or a self-managed tenant, switch the bootstrap server URL for your own. +//Use tabs instead of astra only. Compare with what is already in the target Starlight topics. +[TIP] +==== +The following examples use an Astra Streaming tenant as the Kafka bootstrap server. + +If you are using Luna Streaming or a self-managed tenant, use the bootstrap server URL for your tenant. +==== === Retrieve Kafka connection properties in Astra Streaming +//Already covered on the Astra tab above. Image isn't needed. +//See if this can be made generic or already provided for both in the Starlight docs + In the Astra Streaming portal "Connect" tab, the "kafka" area provides important connection information. You will need this connection information to create a working Kafka client or use the CLI. diff --git a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc index c12db8f..2c53427 100644 --- a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc @@ -1,67 +1,196 @@ -= Getting started with the {starlight-rabbitmq} extension += Get started with the {starlight-rabbitmq} extension :navtitle: {starlight-rabbitmq} -:description: Learn how to get started using the {starlight-rabbitmq} extension with {pulsar-short} and get hands on by publishing and consuming messages from a topic. +:description: Use the {starlight-rabbitmq} extension with {pulsar-reg}. -{starlight-rabbitmq} acts as a proxy between your https://www.rabbitmq.com/[RabbitMQ] application and https://pulsar.apache.org/[{pulsar-reg}] cluster. -It implements the AMQP 0.9.1 protocol used by RabbitMQ clients and translates AMQP frames and concepts to {pulsar-short} concepts. +The https://github.com/datastax/starlight-for-rabbitmq[{starlight-rabbitmq} extension] enables https://www.rabbitmq.com/[RabbitMQ] protocol support for https://pulsar.apache.org/[{pulsar-reg}] by introducing a RabbitMQ protocol handler on {pulsar-short} brokers or {pulsar-short} proxies. -If source code is your thing, visit the https://github.com/datastax/starlight-for-rabbitmq[project's repo on GitHub]. +The extension acts as a proxy between your https://www.rabbitmq.com/[RabbitMQ] application and https://pulsar.apache.org/[{pulsar-reg}] cluster. +It implements the AMQP 0.9.1 protocol used by RabbitMQ clients and translates AMQP frames and concepts to {pulsar-short} concepts. -== Architecture reference +By adding the Starlight for RabbitMQ protocol handler to your {pulsar-short} cluster, you can migrate your existing RabbitMQ applications and services to {pulsar-short} without modifying the code. -If you want to dive deep into how {starlight-rabbitmq} works, xref:starlight-for-rabbitmq:ROOT:index.adoc[read the documentation]. +For more information about the {starlight-rabbitmq} architecture, see the xref:starlight-for-rabbitmq:ROOT:index.adoc[{starlight-rabbitmq} documentation]. image:s4r-architecture.png[{starlight-rabbitmq} Architecture] -== Establishing the RabbitMQ protocol handler +== Establish the RabbitMQ protocol handler Before you can use a RabbitMQ client to interact with your {pulsar-short} cluster, you need the {starlight-rabbitmq} protocol handler installed in the cluster. Installation looks a bit different depending on where your {pulsar-short} cluster is running. Choose the option that best fits your needs. [tabs] -==== +====== Astra Streaming:: + -- -If you want a working RabbitMQ extension as quickly as possible, this is your best bet. This is also a good option for those that already have a streaming tenant and are looking to extend it. +Get started producing and consuming RabbitMQ messages on an Astra Streaming {pulsar-short} cluster. + +. Sign in to your Astra account, go to Astra Streaming, and then xref:astra-streaming:getting-started:index.adoc[create a tenant] or click an existing tenant. -. Sign in to your Astra account and navigate to your streaming tenant. +. Go to your tenant's **Connect** tab, select **RabbitMQ**, and then click **Enable RabbitMQ**. + +. Review the information about the {starlight-rabbitmq} extension, and then click **Enable RabbitMQ** to confirm that you want to enable this extension on your tenant. + -TIP: Don't have a streaming tenant? Follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. +[IMPORTANT] +==== +This action creates a configuration file and a `rabbitmq` namespace in your Astra Streaming tenant automatically. -. Go to the "Connect" tab and choose the "RabbitMQ" option. +The `rabbitmq` namespace is required for the {starlight-rabbitmq} extension to function properly. +It is a permanent namespace that cannot be removed except by deleting the entire tenant and all of its data. +==== -. Click "Enable RabbitMQ". +. Save the RabbitMQ configuration details to a file named `rabbitmq.conf`. +The actual values depend on your Astra Streaming tenant's configuration and cloud provider. ++ +.rabbitmq.conf +[source,conf,subs="+quotes"] +---- +username: **TENANT_NAME** +password: token:*** +host: rabbitmq-**PROVIDER**-**REGION**.streaming.datastax.com +port: 5671 +virtual_host: **PROVIDER**/rabbitmq +---- -. A message will let you know of the additions (and restrictions) that come with using {starlight-rabbitmq}. +=== Connect RabbitMQ and {pulsar-short} +//Move to messaging section? +This example uses a Python script to create a connection between RabbitMQ and your {pulsar-short} tenant. +It also establishes a message queue named `queuename`, prints ten messages, and then closes the connection. -. Click the "Enable RabbitMQ" button to confirm your understanding. +. Create a `connect-test.py` file containing the following code: ++ +.connect-test.py +[source,python,subs="+quotes"] +---- +import ssl +import pika -Your Astra Streaming tenant is ready for prime time! Continue to the next section of the guide to see it in action. --- -Luna Streaming:: +virtual_host = "**VIRTUAL_HOST**" +token = "**TOKEN**" + +context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) +context.verify_mode = ssl.CERT_NONE +context.check_hostname = False +context.load_default_certs() +ssl_options = pika.SSLOptions(context) + +connection = pika.BlockingConnection(pika.ConnectionParameters( + virtual_host=virtual_host, + host="**HOST**", + ssl_options=ssl_options, + port=**PORT**, + credentials=pika.PlainCredentials("", token))) +print("connection success") + +channel = connection.channel() +print("started a channel") + +channel.queue_declare(queue='queuename') + +for x in range(10): + channel.basic_publish(exchange='', + routing_key='routingkey', + body='message body goes here') + print(" sent one") + +connection.close() +---- + --- -The {starlight-rabbitmq} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. The Luna helm chart makes deploying the Kafka extension quite easy. Follow the "xref:luna-streaming:components:starlight-for-rabbitmq.adoc[]" guide to create a simple {pulsar-short} cluster with the {starlight-rabbitmq} extension ready for use. +Replace the following with values from your `rabbitmq.conf` file: ++ +* `**VIRTUAL_HOST**` +* `**TOKEN**` (from the `password` field) +* `**HOST**` +* `**PORT**` -== Use Starlight for RabbitMQ with Luna Streaming +. Save the `connect-test.py` file. -Starlight for RabbitMQ brings native https://www.rabbitmq.com/[RabbitMQ] protocol support to https://pulsar.apache.org/[{pulsar-reg}] by introducing a RabbitMQ protocol handler on {pulsar-short} brokers or {pulsar-short} proxies. -By adding the Starlight for RabbitMQ protocol handler to your {pulsar-short} cluster, you can migrate your existing RabbitMQ applications and services to {pulsar-short} without modifying the code. +. Run `connect-test.py`: ++ +[source,shell] +---- +python3 connect-test.py +---- + +. Make sure the result is similar to the following: ++ +[source,console] +---- +connection success +started a channel + sent one + sent one + sent one + sent one + sent one + sent one + sent one + sent one + sent one + sent one +---- + +. Navigate to your `rabbitmq` namespace dashboard in Astra Streaming, and then monitor the namespace's activity. ++ +If configured correctly, you should have new topics called `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script, as well as an increasing amount of traffic and messages. +Your RabbitMQ messages are being published to a {pulsar-short} topic. + +=== RabbitMQ exchanges and {pulsar-short} topics + +//TBD if duplicated from Starlight docs and/or unique to Astra + +{starlight-rabbitmq} maps RabbitMQ _exchanges_ to {pulsar-short} _topics_, as described in the following table: -The following steps explain how to deploy a Luna Streaming Helm chart with the Starlight for RabbitMQ protocol handler extension. +[cols="1,1,1,1"] +|=== +|Exchange |Routing key |{pulsar-short} topic name |Usage example -=== Prerequisites +|`amp.direct` +|used +|`amq.direct.__{routing key}` +|`channel.basic_publish(exchange='amp.direct',` +|`amp.default` or empty string +|used +|`amq.default.__{routing key}` +|`channel.basic_publish(exchange="),` + +|`amp.match` +|not used +|`amp.match` +|`channel.basic_publish(exchange=amp.match),` + +|`amp.fanout` +|not used +|`amp.fanout` +|`channel.basic_publish(exchange='amp.fanout'),` + +|`headers` +|not used +|Name of the header +|`channel.exchange_declare(exchange='header_logs', exchange_type='headers') +channel.basic_publish(exchange='header_logs'),` + +|=== +-- + +Luna Streaming:: ++ +-- +The {starlight-rabbitmq} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. +The Luna Helm chart simplifies deployment of the the RabbitMQ extension. + +The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the {starlight-rabbitmq} extension ready for use. + +. Make sure you meet the following prerequisites: ++ * https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) * https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) * Python (we used version 3.8.10) * Enough access to a K8s cluster to create a namespace, deployments, and pods -=== Install Luna Streaming Helm chart - -. Add the {company} Helm chart repo to your Helm store. +. Add the {company} Helm chart repo to your Helm store + [source,shell] ---- @@ -84,34 +213,35 @@ helm install \ datastax-pulsar/pulsar ---- -. Wait for the broker pod to be in a running state. You might see a few restarts as your components start up. +. Wait for the broker pod to reach a running state. +It might restart a few times while your components start up. + [source,shell] ---- kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ---- -=== Forward service port - -You'll need to interact with a few of the services in the K8s cluster. -Map a few ports to those services. - -In a new terminal, port forward {pulsar-short}'s admin service: - +. Forward service ports so you can interact with certain services on the Kubernetes cluster: ++ +.. In a new terminal, port forward {pulsar-short}'s admin service: ++ [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ---- -In a separate terminal window, port forward the Starlight for RabbitMQ service: - +.. In a separate terminal window, port forward the Starlight for RabbitMQ service: ++ [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-proxy 5672:5672 ---- -=== Produce a message with the RabbitMQ Python client +The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. +Your application can now communicate with {pulsar-short} as if it were a real RabbitMQ host. +=== Produce a message with the RabbitMQ Python client +//Move to messaging section If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. Only the admin port and the RabbitMQ port are open. To further demonstrate how native Starlight for RabbitMQ is, we will use the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. @@ -163,29 +293,32 @@ received message: test deleted test-queue queue ---- -=== Next steps - -The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. -Your application will now "talk" to {pulsar-short} as if it were a real RabbitMQ host. - -* xref:streaming-learning:use-cases-architectures:starlight/rabbitmq/index.adoc[Messaging with Starlight for RabbitMQ] -- + Self Managed:: + -- Already have your own {pulsar-short} Cluster? Or maybe you're using a standalone cluster? {starlight-rabbitmq} can easily be a part of that cluster! Follow the "xref:starlight-for-rabbitmq:installation:getting-started.adoc[]" guide. -- -==== +====== -== Messaging with {starlight-rabbitmq} +== Message with {starlight-rabbitmq} {starlight-rabbitmq} supports quite a few different use cases. With a {pulsar-short} cluster between publishers and consumers you can interchange the type of publisher and consumer to fit your needs. -*The below examples are using an Astra Streaming tenant as the AMQP listener.* If you are using Luna Streaming or a self-managed tenant, switch the listener URL for your own. +[TIP] +==== +The following examples use an Astra Streaming tenant as the AMQP listener. + +If you are using Luna Streaming or a self-managed tenant, use the listener URL for your tenant. +==== === Retrieve RabbitMQ connection properties in Astra Streaming +//Already covered on the Astra tab above. Image isn't needed. +//See if this can be made generic or already provided for both in the Starlight docs + In the Astra Streaming portal "Connect" tab, the "RabbitMQ" area provides important connection information. You will need this connection information to create a working RabbitMQ client or use the CLI. @@ -230,7 +363,7 @@ Your editor will report errors because this isn't a complete program yet. + Replace placeholders with the values you previously retrieved from Astra Streaming. + -[source,java] +[source,java,subs="+quotes"] ---- package org.example; @@ -245,11 +378,11 @@ import java.util.concurrent.TimeoutException; public class App { private static final String username = ""; - private static final String password = ""; - private static final String host = ""; + private static final String password = "**PULSAR_TOKEN**"; + private static final String host = "**SERVICE_URL**"; private static final int port = 5671; - private static final String virtual_host = "/"; //The "rabbitmq" namespace should have been created when you enabled S4R - private static final String queueName = ""; //This will get created automatically + private static final String virtual_host = "**TENANT_NAME**>/rabbitmq"; //The "rabbitmq" namespace should have been created when you enabled S4R + private static final String queueName = "**TOPIC_NAME**"; //This will get created automatically if it doesn't already exist private static final String amqp_URI = String.format("amqps://%s:%s@%s:%d/%s", username, password, host, port, virtual_host.replace("/","%2f")); public static void main(String[] args) throws IOException, TimeoutException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException, InterruptedException { @@ -323,9 +456,4 @@ java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.j Sent 'Hello World!' Received 'Hello World!' ---- -==== - -== Next steps - -* xref:starlight-for-rabbitmq:ROOT:index.adoc[{starlight-rabbitmq} documentation] -* xref:luna-streaming:components:starlight-for-rabbitmq.adoc[] \ No newline at end of file +==== \ No newline at end of file From 08a919a8269f3691673282e2c2a01309d0243e7a Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Thu, 8 Jan 2026 07:14:59 -0800 Subject: [PATCH 4/9] move table --- .../pages/starlight/rabbitmq/index.adoc | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc index 2c53427..5aca196 100644 --- a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc @@ -135,44 +135,6 @@ started a channel + If configured correctly, you should have new topics called `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script, as well as an increasing amount of traffic and messages. Your RabbitMQ messages are being published to a {pulsar-short} topic. - -=== RabbitMQ exchanges and {pulsar-short} topics - -//TBD if duplicated from Starlight docs and/or unique to Astra - -{starlight-rabbitmq} maps RabbitMQ _exchanges_ to {pulsar-short} _topics_, as described in the following table: - -[cols="1,1,1,1"] -|=== -|Exchange |Routing key |{pulsar-short} topic name |Usage example - -|`amp.direct` -|used -|`amq.direct.__{routing key}` -|`channel.basic_publish(exchange='amp.direct',` - -|`amp.default` or empty string -|used -|`amq.default.__{routing key}` -|`channel.basic_publish(exchange="),` - -|`amp.match` -|not used -|`amp.match` -|`channel.basic_publish(exchange=amp.match),` - -|`amp.fanout` -|not used -|`amp.fanout` -|`channel.basic_publish(exchange='amp.fanout'),` - -|`headers` -|not used -|Name of the header -|`channel.exchange_declare(exchange='header_logs', exchange_type='headers') -channel.basic_publish(exchange='header_logs'),` - -|=== -- Luna Streaming:: @@ -456,4 +418,42 @@ java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.j Sent 'Hello World!' Received 'Hello World!' ---- -==== \ No newline at end of file +==== + +== RabbitMQ exchanges and {pulsar-short} topics + +//Move to Publishing messages section under Pulsar protocol handler in Starlight for RabbitMQ docs. + +{starlight-rabbitmq} maps RabbitMQ _exchanges_ to {pulsar-short} _topics_, as described in the following table: + +[cols="1,1,1,1"] +|=== +|Exchange |Routing key |{pulsar-short} topic name |Usage example + +|`amp.direct` +|used +|`amq.direct.__{routing key}` +|`channel.basic_publish(exchange='amp.direct',` + +|`amp.default` or empty string +|used +|`amq.default.__{routing key}` +|`channel.basic_publish(exchange="),` + +|`amp.match` +|not used +|`amp.match` +|`channel.basic_publish(exchange=amp.match),` + +|`amp.fanout` +|not used +|`amp.fanout` +|`channel.basic_publish(exchange='amp.fanout'),` + +|`headers` +|not used +|Name of the header +|`channel.exchange_declare(exchange='header_logs', exchange_type='headers') +channel.basic_publish(exchange='header_logs'),` + +|=== \ No newline at end of file From 05e83b83b6f074980d226769c7063398190db512 Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:51:17 -0800 Subject: [PATCH 5/9] finish revising rabbitmq tabs --- modules/ROOT/nav.adoc | 2 +- .../images/rabbitmq-client-settings.png | Bin 31342 -> 0 bytes .../pages/starlight/kafka/index.adoc | 22 +- .../pages/starlight/rabbitmq/index.adoc | 540 ++++++++++++------ 4 files changed, 378 insertions(+), 186 deletions(-) delete mode 100644 modules/use-cases-architectures/images/rabbitmq-client-settings.png diff --git a/modules/ROOT/nav.adoc b/modules/ROOT/nav.adoc index 5b28e03..a77c655 100644 --- a/modules/ROOT/nav.adoc +++ b/modules/ROOT/nav.adoc @@ -1,6 +1,6 @@ .Process data * xref:cdc-for-cassandra:ROOT:cdc-concepts.adoc[Change Data Capture (CDC)] -* xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with {product}] +* xref:astra-streaming:getting-started:real-time-data-pipelines-tutorial.adoc[Build real-time data pipelines with Astra Streaming] .Migrate to {pulsar} * xref:starlight-for-kafka:ROOT:index.adoc[{starlight-kafka}] diff --git a/modules/use-cases-architectures/images/rabbitmq-client-settings.png b/modules/use-cases-architectures/images/rabbitmq-client-settings.png deleted file mode 100644 index c5b33aeceb609957570b5891b881e59e70d8808b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31342 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. ++ +. Create a `connect-test.py` file containing the following code, and then replace the placeholders with the values from your `rabbitmq.conf` file: + .connect-test.py [source,python,subs="+quotes"] @@ -67,7 +180,7 @@ import ssl import pika virtual_host = "**VIRTUAL_HOST**" -token = "**TOKEN**" +token = "**PASSWORD**" context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.verify_mode = ssl.CERT_NONE @@ -97,23 +210,18 @@ for x in range(10): connection.close() ---- + -Replace the following with values from your `rabbitmq.conf` file: +. Optional: Change the values for `queue`, `routing_key`, and `body`. +`queuename` and `routingkey` become the names of {pulsar-short} topics in your Astra Streaming tenant. +The `body` is the content of each message that is sent. + -* `**VIRTUAL_HOST**` -* `**TOKEN**` (from the `password` field) -* `**HOST**` -* `**PORT**` - -. Save the `connect-test.py` file. - -. Run `connect-test.py`: +. Save and run the `connect-test.py` script: + [source,shell] ---- python3 connect-test.py ---- - -. Make sure the result is similar to the following: ++ +. Make sure the output shows that the connection was successful and ten messages were sent: + [source,console] ---- @@ -130,87 +238,180 @@ started a channel sent one sent one ---- - -. Navigate to your `rabbitmq` namespace dashboard in Astra Streaming, and then monitor the namespace's activity. + -If configured correctly, you should have new topics called `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script, as well as an increasing amount of traffic and messages. -Your RabbitMQ messages are being published to a {pulsar-short} topic. --- - -Luna Streaming:: +. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `rabbitmq` namespace. + --- -The {starlight-rabbitmq} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. -The Luna Helm chart simplifies deployment of the the RabbitMQ extension. +If you everything was configured correctly, then the `rabbitmq` namespace should have topics named `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script. +Additionally, the namespace's metrics should reflect that at least 10 messages were published and consumed by your Astra Streaming {pulsar-short} topics. -The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the {starlight-rabbitmq} extension ready for use. - -. Make sure you meet the following prerequisites: +Java:: + -* https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) -* https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) -* Python (we used version 3.8.10) -* Enough access to a K8s cluster to create a namespace, deployments, and pods - -. Add the {company} Helm chart repo to your Helm store +The following example uses a Java program to create a connection between RabbitMQ and your Astra Streaming tenant, and then it establishes a message queue and sends a message. ++ +. Enable {starlight-rabbitmq} and get the `rabbitmq.conf` connection details, as explained in <>. ++ +. Create a new Maven project: + [source,shell] ---- -helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart +mvn archetype:generate \ + -DgroupId=org.example \ + -DartifactId=StarlightForRabbitMqClient \ + -DarchetypeArtifactId=maven-archetype-quickstart \ + -DinteractiveMode=false ---- - -. Install the Helm chart using a minimalist values file. -This command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart, within the K8s namespace `datastax-pulsar`. -The minimal cluster creates only the essential components and has no ingress or load balanced services. ++ +. Change to the new project directory: + [source,shell] ---- -VALUES_URL="https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main/starlight-for-rabbitmq/values.yaml" -helm install \ - --namespace datastax-pulsar \ - --create-namespace \ - --values $VALUES_URL \ - --version 3.0.4 \ - my-pulsar-cluster \ - datastax-pulsar/pulsar +cd StarlightForRabbitMqClient +---- ++ +. Open the new project in your IDE, and then add the RabbitMQ client dependency to `pom.xml`: ++ +.pom.xml +[source,xml] +---- + + com.rabbitmq + amqp-client + 5.16.0 + +---- ++ +. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preeixsting code in this file. +In the next steps, you will add code to this file to create a complete program that produces and consumes messages. ++ +. Paste the following code in the file, and then replace the placeholders with the values from your `rabbitmq.conf` file. +Your editor will report errors because this isn't a complete program yet. ++ +.App.java +[source,java,subs="+quotes"] ---- +package org.example; -. Wait for the broker pod to reach a running state. -It might restart a few times while your components start up. +import com.rabbitmq.client.*; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.TimeoutException; + +public class App { + private static final String username = ""; + private static final String password = "**PASSWORD**"; + private static final String host = "**HOST**"; + private static final int port = 5671; + private static final String virtual_host = "**VIRTUAL_HOST**"; + private static final String queueName = "queuename"; + private static final String amqp_URI = String.format("amqps://%s:%s@%s:%d/%s", username, password, host, port, virtual_host.replace("/","%2f")); + + public static void main(String[] args) throws IOException, TimeoutException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException, InterruptedException { +---- + -[source,shell] +. Optional: Replace `queuename` with another name for the queue that publishes and consumes messages. +This name is also used as the corresponding topic name in Astra Streaming. +If the topic doesn't exist, Astra Streaming creates it automatically when the producer sends the first message. ++ +. Add the following code to create a connection, channel, and queue that is used by both the producer and consumer: ++ +.App.java +[source,java] ---- -kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s + ConnectionFactory factory = new ConnectionFactory(); + factory.setUri(amqp_URI); + + /* + You could also set each value individually + factory.setHost(host); + factory.setPort(port); + factory.setUsername(username); + factory.setPassword(password); + factory.setVirtualHost(virtual_host); + factory.useSslProtocol(); + */ + + Connection connection = factory.newConnection(); + Channel channel = connection.createChannel(); + + channel.queueDeclare(queueName, false, false, false, null); +---- ++ +. Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: ++ +.App.java +[source,java] +---- + String publishMessage = "Hello World!"; + channel.basicPublish("", queueName, null, publishMessage.getBytes()); + System.out.println(" Sent '" + publishMessage + "'"); +---- ++ +. Add the consumer code, which creates a basic consumer with callback on message receipt. +Because the consumer isn't a blocking thread, the `sleep` allows time for messages to be received and processed. ++ +.App.java +[source,java] ---- + DeliverCallback deliverCallback = (consumerTag, delivery) -> { + String consumeMessage = new String(delivery.getBody(), StandardCharsets.UTF_8); + System.out.println(" Received '" + consumeMessage + "'"); + }; + + channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { }); -. Forward service ports so you can interact with certain services on the Kubernetes cluster: + Thread.sleep(4000); // wait a bit for messages to be received + + channel.close(); + connection.close(); + } +} +---- + -.. In a new terminal, port forward {pulsar-short}'s admin service: +. Save `App.java`, and then build and run the JAR file for the complete program: + [source,shell] ---- -kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 +mvn clean package assembly:single +java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.jar ---- - -.. In a separate terminal window, port forward the Starlight for RabbitMQ service: ++ +. Make sure the result shows that a message was sent and received: + [source,shell] ---- -kubectl port-forward -n datastax-pulsar service/pulsar-proxy 5672:5672 +Sent 'Hello World!' +Received 'Hello World!' ---- ++ +. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `rabbitmq` namespace. ++ +If you everything was configured correctly, then the `rabbitmq` namespace should have a topic named `amq.default.__queuename` that was created by the Java program. +Additionally, the namespace's metrics should reflect that at least one message was published and consumed by your Astra Streaming {pulsar-short} topic. +==== -The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. -Your application can now communicate with {pulsar-short} as if it were a real RabbitMQ host. - -=== Produce a message with the RabbitMQ Python client -//Move to messaging section -If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. -Only the admin port and the RabbitMQ port are open. -To further demonstrate how native Starlight for RabbitMQ is, we will use the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. +-- -Save the following Python script to a safe place as `test-queue.py`. -The script assumes you have opened the localhost:5672 port. +Luna Streaming:: ++ +-- +To use a RabbitMQ client with {starlight-rabbitmq}, you use your Luna Streaming {pulsar-short} tenant as the AMQP listener. +The following examples use a connection on `localhost:5672`. +For other connection methods, see the documentation for your preferred RabbitMQ client library. +[tabs] +==== +Python:: ++ +The following example uses the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. ++ +. Save the following Python script to a safe place as `test-queue.py`. +The example script assumes you have opened the `localhost:5672` port, as explained in <>. ++ +.test-queue.py [source,python] ---- #!/usr/bin/env python @@ -236,17 +437,18 @@ try: finally: connection.close() ---- - -Open a terminal and return to the safe place where you saved the Python script. -Run the following command to execute the Python program. - ++ +. Optional: Replace `test-queue` with another name for the queue and routing key. These names are also used as the corresponding topic names in your {pulsar-short} tenant. If the topic doesn't exist, it is created automatically when the producer sends the first message. ++ +. Save and run the `test-queue.py` script: ++ [source,shell] ---- python ./test-queue.py ---- - -The output should look like the following. - ++ +. Make sure the output shows that the queue was created and a message was sent: ++ [source,shell] ---- created test-queue queue @@ -254,48 +456,15 @@ published message test received message: test deleted test-queue queue ---- - --- - -Self Managed:: + --- -Already have your own {pulsar-short} Cluster? Or maybe you're using a standalone cluster? {starlight-rabbitmq} can easily be a part of that cluster! Follow the "xref:starlight-for-rabbitmq:installation:getting-started.adoc[]" guide. --- -====== - -== Message with {starlight-rabbitmq} - -{starlight-rabbitmq} supports quite a few different use cases. -With a {pulsar-short} cluster between publishers and consumers you can interchange the type of publisher and consumer to fit your needs. - -[TIP] -==== -The following examples use an Astra Streaming tenant as the AMQP listener. - -If you are using Luna Streaming or a self-managed tenant, use the listener URL for your tenant. -==== - -=== Retrieve RabbitMQ connection properties in Astra Streaming - -//Already covered on the Astra tab above. Image isn't needed. -//See if this can be made generic or already provided for both in the Starlight docs - -In the Astra Streaming portal "Connect" tab, the "RabbitMQ" area provides important connection information. -You will need this connection information to create a working RabbitMQ client or use the CLI. - -image:rabbitmq-client-settings.png[Astra Streaming RabbitMQ settings] - -TIP: Click the clipboard icon to copy the RabbitMQ connection values, as well as a working token to paste in code. - -=== Produce and consume a message +. Use the {pulsar} admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity. +Make sure the `test-queue` topic was created and a message was published and consumed. -This example uses Maven for the project structure for a Rabbit MQ Java client. -If you prefer Gradle or another tool, this code should still be a good fit. - -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. - -. Create a new Maven project. +Java:: ++ +The following example uses a Java program to create a connection between RabbitMQ and your Luna Streaming {pulsar-short} tenant, and then it establishes a message queue and sends a message. ++ +. Create a new Maven project: + [source,shell] ---- @@ -304,12 +473,18 @@ mvn archetype:generate \ -DartifactId=StarlightForRabbitMqClient \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false - +---- ++ +. Change to the new project directory: ++ +[source,shell] +---- cd StarlightForRabbitMqClient ---- - -. Open the new project in your IDE or text editor, and then add the RabbitMQ client dependency to `pom.xml`: + +. Open the new project in your IDE, and then add the RabbitMQ client dependency to `pom.xml`: ++ +.pom.xml [source,xml] ---- @@ -318,14 +493,17 @@ cd StarlightForRabbitMqClient 5.16.0 ---- - -. Open the file `src/main/java/org/example/App.java`, and then enter the following code. -If you cloned the example repo, replace the entire contents with the following code. -Your editor will report errors because this isn't a complete program yet. + -Replace placeholders with the values you previously retrieved from Astra Streaming. +. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preeixsting code in this file. +In the next steps, you will add code to this file to create a complete program that produces and consumes messages. + -[source,java,subs="+quotes"] +. Paste the following code in the file. +This code creates a connection, channel, and queue that is used by both the producer and consumer. +It uses the default connection values to connect on `localhost:5672`, which was port forwarded in <>. +Your editor will report errors because this isn't a complete program yet. ++ +.App.java +[source,java] ---- package org.example; @@ -339,52 +517,42 @@ import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeoutException; public class App { - private static final String username = ""; - private static final String password = "**PULSAR_TOKEN**"; - private static final String host = "**SERVICE_URL**"; - private static final int port = 5671; - private static final String virtual_host = "**TENANT_NAME**>/rabbitmq"; //The "rabbitmq" namespace should have been created when you enabled S4R - private static final String queueName = "**TOPIC_NAME**"; //This will get created automatically if it doesn't already exist - private static final String amqp_URI = String.format("amqps://%s:%s@%s:%d/%s", username, password, host, port, virtual_host.replace("/","%2f")); + private static final String queueName = "queuename"; public static void main(String[] args) throws IOException, TimeoutException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException, InterruptedException { ----- -. Add the code to create a connection, channel, and queue that will be used by both the producer and consumer: -+ -[source,java] ----- + // Use the default values to connect on localhost:5672 ConnectionFactory factory = new ConnectionFactory(); - factory.setUri(amqp_URI); - - /* - You could also set each value individually - factory.setHost(host); - factory.setPort(port); - factory.setUsername(username); - factory.setPassword(password); - factory.setVirtualHost(virtual_host); - factory.useSslProtocol(); - */ + factory.setUsername(userName); + factory.setPassword(password); + factory.setVirtualHost(virtualHost); + factory.setHost(hostName); + factory.setPort(portNumber); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(queueName, false, false, false, null); ---- - ++ +. Optional: Replace `queuename` with another name for the queue that publishes and consumes messages. +This name is also used as the corresponding topic name in Astra Streaming. +If the topic doesn't exist,it is created automatically when the producer sends the first message. ++ . Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: + +.App.java [source,java] ---- String publishMessage = "Hello World!"; channel.basicPublish("", queueName, null, publishMessage.getBytes()); System.out.println(" Sent '" + publishMessage + "'"); ---- - ++ . Add the consumer code, which creates a basic consumer with callback on message receipt. Because the consumer isn't a blocking thread, the `sleep` allows time for messages to be received and processed. + +.App.java [source,java] ---- DeliverCallback deliverCallback = (consumerTag, delivery) -> { @@ -401,8 +569,8 @@ Because the consumer isn't a blocking thread, the `sleep` allows time for messag } } ---- - -. Build and run the JAR file for the complete program: ++ +. Save `App.java`, and then build and run the JAR file for the complete program: + [source,shell] ---- @@ -410,50 +578,70 @@ mvn clean package assembly:single java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.jar ---- + -.Result -[%collapsible] -==== +. Make sure the result shows that a message was sent and received: ++ [source,shell] ---- Sent 'Hello World!' Received 'Hello World!' ---- ++ +. Use the {pulsar-short} Admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity. +Make sure the `queuename` topic was created and a message was published and consumed. ==== +-- + +Self-managed:: ++ +-- +To use a RabbitMQ client with {starlight-rabbitmq}, you use your {pulsar-short} tenant as the AMQP listener. +You can also connect on `localhost` if you have port forwarded the RabbitMQ port (5672) to your local machine. + +For `localhost` examples, see the Luna Streaming tab. +However, the specific connection details and valid connection methods depend on your cluster's configuration. + +For more information, see the documentation for your preferred RabbitMQ client library. +-- +====== + == RabbitMQ exchanges and {pulsar-short} topics //Move to Publishing messages section under Pulsar protocol handler in Starlight for RabbitMQ docs. {starlight-rabbitmq} maps RabbitMQ _exchanges_ to {pulsar-short} _topics_, as described in the following table: -[cols="1,1,1,1"] +[cols=4] |=== |Exchange |Routing key |{pulsar-short} topic name |Usage example |`amp.direct` -|used +|Used |`amq.direct.__{routing key}` -|`channel.basic_publish(exchange='amp.direct',` +|`channel.basic_publish(exchange='amp.direct'),` |`amp.default` or empty string -|used +|Used |`amq.default.__{routing key}` |`channel.basic_publish(exchange="),` |`amp.match` -|not used +|Not used |`amp.match` |`channel.basic_publish(exchange=amp.match),` |`amp.fanout` -|not used +|Not used |`amp.fanout` |`channel.basic_publish(exchange='amp.fanout'),` |`headers` -|not used -|Name of the header -|`channel.exchange_declare(exchange='header_logs', exchange_type='headers') -channel.basic_publish(exchange='header_logs'),` - +|Not used +|Header name +a| +[source,python] +---- +channel.exchange_declare(exchange='header_logs', exchange_type='headers') +channel.basic_publish(exchange='header_logs'), +---- |=== \ No newline at end of file From 55b1b4dd8008657775ef9baf7a1269130ebec7f1 Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Thu, 8 Jan 2026 17:06:19 -0800 Subject: [PATCH 6/9] revise and reorg starlight topics b4 move --- .../images/kafka-client-settings.png | Bin 23894 -> 0 bytes .../pages/starlight/kafka/index.adoc | 477 +++++++++--------- .../pages/starlight/rabbitmq/index.adoc | 36 +- 3 files changed, 260 insertions(+), 253 deletions(-) delete mode 100644 modules/use-cases-architectures/images/kafka-client-settings.png diff --git a/modules/use-cases-architectures/images/kafka-client-settings.png b/modules/use-cases-architectures/images/kafka-client-settings.png deleted file mode 100644 index 331392e005138c1cf0668b3c9e6f551b31966216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23894 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

f32q1#nT>{cOs4KYGe$g32&qCg*uCW{ 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 diff --git a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc index a1f7c35..ac557db 100644 --- a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc @@ -9,16 +9,17 @@ By adding the {starlight-kafka} protocol handler to your existing {pulsar-short} //Move this image to the Starlight for Kafka main index page image:s4k-architecture.png[{starlight-kafka} Architecture] +[#establish-the-kafka-protocol-handler] == Establish the Kafka protocol handler Before a Kafka client can interact with your {pulsar-short} cluster, you need the {starlight-kafka} protocol handler installed in the cluster. -//Compare all with Rabbit + [tabs] ====== Astra Streaming:: + -- -These steps explain how to enable the {starlight-kafka} protocol handler in an Astra Streaming {pulsar-short} cluster, and then connect it to your Kafka instance: +These steps explain how to enable the {starlight-kafka} protocol handler in an Astra Streaming {pulsar-short} cluster, and then get the connection details for your Kafka client: . In the {astra-ui-link} header, click icon:grip[name="Applications"], and then select *Streaming*. @@ -43,78 +44,32 @@ These are permanent namespaces that cannot be removed except by deleting the ent . Save the Kafka connection details to a file named `ssl.properties`. The actual values depend on your Astra Streaming tenant's configuration and cloud provider. + -[TIP] -==== -In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a token is included in the `password` field automatically. -You can also generate a token on your tenant's **Settings** tab. -==== -+ .ssl.properties -[source,plain,subs="+quotes"] +[source,plain,subs="+quotes,+attributes"] ---- username: **TENANT_NAME** -password: token:*** +password: token:{asterisk}{asterisk}{asterisk}{asterisk}{asterisk}{asterisk} bootstrap.servers: kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 schema.registry.url: https://kafka-**PROVIDER**-**REGION**.streaming.datastax.com:8081 security.protocol: SASL_SSL sasl.mechanism: PLAIN ---- - -=== Connect Kafka and {pulsar-short} -// Move to messaging section? -This example uses tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball]. - -. In Astra Streaming, create a new topic in the `kafka` namespace. + -No specific name is required. +[TIP] +==== +In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a {pulsar-short} token is included in the `password` field automatically. +You can also generate a token on your tenant's **Settings** tab. +==== -. In your Kafka instance, move your `ssl.properties` file to your `Kafka_2.13-3.1.0/config` folder. -These values are required for SSL encryption. -The exact values depend on your Astra Streaming tenant's configuration. +. Optional: Add a session timeout value to the `ssl.properties` file to avoid connection issues with some Kafka clients: + -[source,properties,subs="+quotes"] +[source,properties] ---- -bootstrap.servers=kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 -security.protocol=SASL_SSL -sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username='**TENANT_NAME**' password='token:{pulsar tenant token}' -sasl.mechanism=PLAIN session.timeout.ms=45000 ---- - -. In the `Kafka` directory, create a Kafka producer to produce messages on the topic you created in the `kafka` namespace: -+ -[source,shell,subs="+quotes"] ----- -bin/kafka-console-producer \ ---broker-list kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ ---topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ ---producer.config config/ssl.properties ----- + -Once the producer is ready, it accepts standard input from the user: -+ -[source,console] ----- ->hello pulsar ----- +Continue to the next section to learn how to use the connection details in a Kafka client script. -. In a new terminal window, create a Kafka consumer to consume messages from the beginning of your topic: -+ -[source,shell] ----- -bin/kafka-console-consumer \ ---bootstrap-server kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ ---topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ ---consumer.config config/ssl.properties \ ---from-beginning ----- - -. Send a few messages in the terminal to generate traffic on the tenant. - -. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. -+ -To verify that your Kafka messages are being produced and consumed in your Astra Streaming {pulsar-short} cluster, check the **Data In** metrics. -The number of messages should be, at least, equal to the number of messages you sent with your Kafka producer on the command line. -- Luna Streaming:: @@ -123,14 +78,14 @@ Luna Streaming:: The {starlight-kafka} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. The Luna Helm chart simplifies deployment of the Kafka extension. -The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the Starlight for Kafka protocol handler extension. +The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the {starlight-kafka} extension ready to use. . Make sure you meet the following prerequisites: + -* https://helm.sh/docs/intro/install/[Helm 3 CLI] (we used version 3.8.0) -* https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[Kafka CLI] (we used version 3.3.1) -* https://kubernetes.io/docs/tasks/tools/[Kubectl CLI] (we used version 1.23.4) -* Enough access to a K8s cluster to create a namespace, deployments, and pods +* Install https://helm.sh/docs/intro/install/[Helm 3 CLI] version 3.8.0 or later. +* Install https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[Kafka CLI] version 3.3.1 or later +* Install https://kubernetes.io/docs/tasks/tools/[kubectl CLI] version 1.23.4 or later. +* Have access to a Kubernetes cluster with permission to create a namespace, deployments, and pods. . Add the {company} Helm chart repo to your Helm store: + @@ -139,9 +94,9 @@ The following steps explain how to deploy a Luna Streaming Helm chart to create helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart ---- -. Install the Helm chart using a minimalist values file. -This command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart, within the K8s namespace `datastax-pulsar`. -The minimal cluster creates only the essential components and has no ingress or load balanced services. +. Install the Helm chart using a minimal values file. +The following command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart within a Kubernetes namespace named `datastax-pulsar`. +This minimal configuration creates only the essential components and has no ingress or load balanced services. + [source,shell] ---- @@ -156,33 +111,18 @@ helm install \ ---- . Wait for the broker pod to reach a running state. -It might restart a few times while your components start up. +It might restart a few times while the components start up. + [source,shell] ---- kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ---- -. Forward service ports so you can interact with certain services on the Kubernetes cluster: +. Use the {pulsar-short} Admin CLI to inspect the tenants, namespaces, and topics that were created in your {pulsar-short} cluster when you deployed the Helm chart with the {starlight-kafka} extension enabled. + -.. In a new terminal, port forward {pulsar-short}'s admin service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ----- - -.. In a separate terminal window, port forward the Starlight for Kafka service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-proxy 9092:9092 ----- - -. Inspect the created namespaces and topics. -+ -The Luna Streaming Helm Chart automatically creates a tenant named `public` and a namespace within that tenant named `default`. -The Starlight for Kafka extension creates a few namespaces and topics automatically because these are required for the extension to function correctly. +By default, the Helm chart create a tenant named `public` with a namespace named `default`. +In addition, the {starlight-kafka} extension creates several namespaces and topics that are required for its functionality. +These namespaces are prefixed with `+__kafka+`. + List the namespaces in the `public` tenant: + @@ -191,7 +131,7 @@ List the namespaces in the `public` tenant: ~/apache-pulsar-3.1.3$ ./bin/pulsar-admin namespaces list public ---- + -The output should be similar to the following: +Make sure the output includes the `default` and `+__kafka+` namespaces: + [source,shell] ---- @@ -199,165 +139,114 @@ public/__kafka public/__kafka_producerid public/default ---- -+ -The automatically generated namespaces prefixed with "+__kafka+". -These are used by the service for different functions. -For more information, see the xref:starlight-for-kafka:ROOT:index.adoc[Starlight for Kafka documentation]. - -=== Produce a message with the Kafka CLI - -//Move to messaging section - -If you hadn't noticed, we never opened the {pulsar-short} binary port to accept new messages. -Only the admin port and the Kafka port are open. -To further show how native Starlight for Kafka is to {pulsar-short}, we will use the Kafka CLI to produce and consume messages from {pulsar-short}. - -From within the Kafka directory, run the following command to start the shell: - -[source,shell] ----- -~/kafka_2.13-3.3.1$ ./bin/kafka-console-producer.sh --topic quickstart --bootstrap-server localhost:9092 ----- - -Type a message, press Enter to send it, then Ctrl-C to exit the producer shell. - -[source,shell] ----- -This my first message ----- - -A `quickstart` topic is created automatically because the default behavior of Starlight for Kafka is to create a new single partition, persistent topic when one is not present. -You can configure this behavior and many other S4K parameters in the https://github.com/datastaxdevs/luna-streaming-examples/blob/main/starlight-for-kafka/values.yaml[Helm chart]. -Learn more about the configuration values xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[here]. - -Let's have a look at the topic that was created. From your {pulsar-short} home folder, run the following command: - -[source,shell] ----- -~/apache-pulsar-3.1.3$ ./bin/pulsar-admin topics list public/default ----- - -The output will include the newly created topic: +. Enable port forwarding for the {pulsar-short} Admin and {starlight-kafka} services that are running on the Kubernetes cluster: ++ +.. In a new terminal, port forward the {pulsar-short} Admin service: ++ [source,shell] ---- -persistent://public/default/quickstart-partition-0 +kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ---- -== Consume the new message with the Kafka CLI -//Move to messaging section -Let's use the Kafka CLI to consume the message we just produced. - -Start the consumer shell from the Kafka home folder with the following command: - +.. In a separate terminal window, port forward the {starlight-kafka} service: ++ [source,shell] ---- -~/kafka_2.13-3.3.1$ ./bin/kafka-console-consumer.sh --topic quickstart --from-beginning --bootstrap-server localhost:9092 +kubectl port-forward -n datastax-pulsar service/pulsar-proxy 9092:9092 ---- -The data of our new message will be output: - -[source,shell] ----- -This my first message ----- ++ +[TIP] +==== +You don't need to open the {pulsar-short} binary port to accept new messages when using {starlight-kafka}. +This is because Kafka clients communicate using the Kafka protocol on port 9092, which is handled by the {starlight-kafka} extension. +==== +After deploying the Helm chart and enabling port forwarding, your applications can communicate with {pulsar-short} as if it were a real Kafka host, as explained in the next section. -Enter Ctrl-C to exit the shell. -- -Self Managed:: +Self-managed:: + -- -Already have your own {pulsar-short} cluster? Or maybe you're using a standalone cluster? {starlight-kafka} can easily be a part of that cluster! Follow the "xref:starlight-for-kafka:installation:starlight-kafka-quickstart.adoc[]" guide. +To use {starlight-kafka} with self-managed or standalone {pulsar-short} clusters, see xref:starlight-for-kafka:installation:starlight-kafka-quickstart.adoc[]. -- ====== -== Message with {starlight-kafka} - -{starlight-kafka} supports quite a few different use cases. With a {pulsar-short} cluster between producers and consumers you can interchange the type of producer and consumer to fit your needs. +== Produce and consume messages with {starlight-kafka} -//Use tabs instead of astra only. Compare with what is already in the target Starlight topics. -[TIP] -==== -The following examples use an Astra Streaming tenant as the Kafka bootstrap server. - -If you are using Luna Streaming or a self-managed tenant, use the bootstrap server URL for your tenant. -==== - -=== Retrieve Kafka connection properties in Astra Streaming - -//Already covered on the Astra tab above. Image isn't needed. -//See if this can be made generic or already provided for both in the Starlight docs - -In the Astra Streaming portal "Connect" tab, the "kafka" area provides important connection information. -You will need this connection information to create a working Kafka client or use the CLI. - -image:kafka-client-settings.png[Astra Streaming kafka settings] +This section explains how to use your Pulsar tenant's connection details with a Kafka client to produce and consume messages with {starlight-kafka}. -TIP: Click the clipboard icon to copy the Kafka connection values, as well as a working token to paste in code. +{starlight-kafka} supports many different use cases. +With a {pulsar-short} cluster between publishers and consumers, you can change the type of publisher and consumer to fit your needs. -=== Produce and consume a message +The following examples use the Kafka CLI and Java. +For complete source code examples and examples for other languages, see the https://github.com/datastax/astra-streaming-examples[{company} streaming examples repository]. +These examples are written for Astra Streaming but they can be adapted for Luna Streaming or self-managed {pulsar-short} clusters by replacing the connection details with those for your cluster. [tabs] ====== -Kafka CLI:: +Astra Streaming:: + -- -Download the latest Kafka distribution https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[here]. -With the tarball extracted, the producer and consumer CLIs are in the 'bin' folder. - -. To get started, let's set a few variables. If you've completed our "xref:astra-streaming:getting-started:index.adoc[Getting started with Astra Streaming]" guide, the below values will be a perfect fit for your existing tenant. +[tabs] +==== +Kafka CLI:: + -[source,shell] ----- -SERVICE_URL="" -TENANT="" -NAMESPACE="" -TOPIC="" ----- - -. Now let's enter those variables in Kafka's producer shell. +This example uses command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball]. + -[source,shell] ----- -# cd kafka_2.13-3.3.1 -./bin/kafka-console-producer.sh --topic "$TENANT/$NAMESPACE/$TOPIC" --bootstrap-server "$SERVICE_URL" ----- - -. Type in a super memorable message and hit 'enter' to send. Press 'Ctrl-C' to exit the shell. +. Enable {starlight-kafka} and get the `ssl.properties` connection details, as explained in <>. + -[source,shell] ----- -> This is my first S4K message. ----- -A new message has been produced in the provided tenant/namespace/topic and is ready for consumption. -. Start the Kafka consumer shell. +. In Astra Streaming, in the `kafka` namespace, create a topic to receive messages from the `kafka-console-producer`. +You can use any valid name for the topic. + -[source,shell] +. Move your Astra Streaming `ssl.properties` file into your Kafka installation's `config` subdirectory, such as `kafka_2.13-3.1.0/config`. ++ +. In a terminal window, use the `kafka-console-producer` tool to create a Kafka producer that produces messages on the topic you created in the `kafka` namespace: ++ +[source,shell,subs="+quotes"] ---- -# cd kafka_2.13-3.3.1 -./bin/kafka-console-consumer.sh --topic "$TENANT/$NAMESPACE/$TOPIC" --from-beginning --bootstrap-server "$SERVICE_URL" +bin/kafka-console-producer \ +--broker-list kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ +--topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ +--producer.config config/ssl.properties ---- - -. The consumer should immediately find the new message and output its value. + -[source,shell] +When the producer is ready, it accepts standard input from the user. +To send a message, type it in the terminal, and then press kbd:[Return]. +Optionally, you can send some messages before starting the consumer to see how it retrieves past messages. ++ +. In a new terminal window, use the `kafka-console-consumer` tool to create a Kafka consumer that consumes messages from the beginning of your topic: ++ +[source,shell,subs="+quotes"] ---- -This is my first S4K message. +bin/kafka-console-consumer \ +--bootstrap-server kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ +--topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ +--consumer.config config/ssl.properties \ +--from-beginning ---- - -. Press 'Ctrl-C' to exit the consumer shell. --- - -Kafka Client (Java):: + --- -This example uses Maven for the project structure. -If you prefer Gradle or another tool, this code should still be a good fit. - -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. +Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. ++ +. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. ++ +As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. ++ +. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. +To verify that your Kafka messages are being produced and consumed in your Astra Streaming {pulsar-short} cluster, check the **Data In** metrics. +The number of messages should be equal to the number of messages you sent with the `kafka-console-producer`. ++ +. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. -. Create a new Maven project. +Java client:: ++ +The following example uses a Java program to create a connection between Kafka and your Astra Streaming tenant, configures a producer and consumer, and then sends a message. +This example uses Maven, but you can also use Gradle. ++ +. Enable {starlight-kafka} and get the `ssl.properties` connection details, as explained in <>. ++ +. Create a new Maven project: + [source,shell] ---- @@ -366,12 +255,18 @@ mvn archetype:generate \ -DartifactId=StarlightForKafkaClient \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DinteractiveMode=false - +---- ++ +. Change to the new project directory: ++ +[source,shell] +---- cd StarlightForKafkaClient ---- - -. Open the new project in your IDE or text editor, and then add the Kafka client dependency to `pom.xml`: + +. Open the new project in your IDE, and then add the Kafka client dependency to `pom.xml`: ++ +.pom.xml [source,xml] ---- @@ -380,14 +275,14 @@ cd StarlightForKafkaClient 3.3.1 ---- - -. Open the file `src/main/java/org/example/App.java`, and then enter the following code. -If you cloned the example repo, replace the entire contents of `App.java` with the following code. -Your editor will report an error because this isn't a complete script yet. + -Replace placeholders with the values you previously retrieved from Astra Streaming. +. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preexisting code in this file. +In the next steps, you will add code to this file to create a complete program that produces and consumes messages. + -[source,java] +. Paste the following code in the file, and then replace the placeholder values with the values from your `ssl.properties` file. +Your editor will report errors because this isn't a complete program yet. ++ +[source,java,subs="+quotes"] ---- package org.example; @@ -405,17 +300,20 @@ import java.util.Collections; import java.util.Properties; public class App { - private static String bootstrapServers = ""; - private static String pulsarToken = ""; - private static String tenantName = ""; - private static final String namespace = ""; - private static final String topicName = ""; + private static String bootstrapServers = "**BOOTSTRAP_SERVER_URL**"; + private static String pulsarToken = "**PASSWORD**"; + private static String tenantName = "**USERNAME**"; + private static final String namespace = "kafka"; + private static final String topicName = "quickstart"; private static final String topic = String.format("persistent://%s/%s/%s", tenantName,namespace,topicName); public static void main(String[] args) { ---- - -. Add the following code that builds the configuration that will be used by both the producer and consumer: ++ +. Optional: Replace `quickstart` with another name for the topic that receives messages from the Kafka producer. +If the topic doesn't exist, it is created it automatically when the producer sends the first message. ++ +. Add the following code that builds the configuration for the producer and consumer: + [source,java] ---- @@ -431,7 +329,7 @@ public class App { config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); config.put("group.id", "my-consumer-group"); ---- - ++ . Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: + [source,java] @@ -451,7 +349,7 @@ public class App { producer.flush(); producer.close(); ---- - ++ . Add the consumer code, which creates a basic subscription and retrieves the latest messages on the topic: + [source,java] @@ -472,8 +370,8 @@ public class App { } } ---- - -. Build and run a JAR file for the complete program: ++ +. Save `App.java`, and then build and run the JAR file for the complete program: + [source,shell] ---- @@ -481,9 +379,8 @@ mvn clean package assembly:single java -jar target/StarlightForKafkaClient-1.0-SNAPSHOT-jar-with-dependencies.jar ---- + -.Result -[%collapsible] -==== +. Make sure the result shows that a message was produces and consumed: ++ [source,shell] ---- Successfully sent message @@ -491,7 +388,121 @@ Successfully sent message Found 1 total record(s) ConsumerRecord(topic = persistent://my-tenant-007/my-namespace/my-topic, partition = 0, leaderEpoch = null, offset = 22, CreateTime = 1673545962124, serialized key size = 8, serialized value size = 11, headers = RecordHeaders(headers = [], isReadOnly = false), key = xxxxx, value = Hello World) ---- ++ +. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. ++ +If you everything was configured correctly, then the `kafka` namespace should have a topic named `quickstart` that was created by the Java program. +Additionally, the namespace's metrics should reflect that at least one message was published and consumed by your Astra Streaming {pulsar-short} topic. +==== + +-- + +Luna Streaming:: ++ +-- +To use the Kafka CLI or a Kafka client with {starlight-kafka}, you use your Luna Streaming {pulsar-short} tenant as the Kafka bootstrap server. +The following example command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball], and it connects on `localhost:9092` because port forwarding was enabled in <>. + +. In your Kafka installation directory, start the `kafka-console-producer` shell: ++ +[source,shell] +---- +bin/kafka-console-producer.sh \ +--topic quickstart \ +--bootstrap-server localhost:9092 +---- ++ +You can replace `quickstart` with any other name for the topic that will receive messages from the producer. +If the specified topic doesn't exist in your Luna Streaming tenant, it is created automatically when the producer sends the first message. +You can configure this behavior and other xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[{starlight-kafka} parameters] in the https://github.com/datastaxdevs/luna-streaming-examples/blob/main/starlight-for-kafka/values.yaml[Helm chart]. ++ +.Connect to a remote cluster +[%collapsible] +==== +To connect to a remote Luna Streaming cluster, provide the full topic name and the bootstrap server URL for your Luna Streaming tenant: + +[source,shell,subs="+quotes"] +---- +bin/kafka-console-producer.sh --topic "**TENANT_NAME**/**NAMESPACE_NAME**/**TOPIC_NAME**" --bootstrap-server "**SERVICE_URL**" +---- +==== + +. When the producer is ready, type a message, and then press kbd:[Return] to send it. +Optionally, you can send several messages before starting the consumer to see how it retrieves past messages. + +. In a new terminal window, start the `kafka-console-consumer` shell: ++ +[source,shell] +---- +bin/kafka-console-consumer.sh \ +--topic quickstart \ +--bootstrap-server localhost:9092 \ +--from-beginning +---- ++ +Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. + +. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. ++ +As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. + +. Use the {pulsar-short} Admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity, and verify that messages were published and consumed on the specified topic. + +. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. +-- + +Self-managed:: ++ +-- +To use the Kafka CLI or a Kafka client with {starlight-kafka}, you use your {pulsar-short} tenant as the Kafka bootstrap server. +The following example command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball], and it assumes port forwarding is enabled to connect on `localhost:9092`. + +. In your Kafka installation directory, start the `kafka-console-producer` shell: ++ +[source,shell] +---- +bin/kafka-console-producer.sh \ +--topic quickstart \ +--bootstrap-server localhost:9092 +---- ++ +You can replace `quickstart` with any other name for the topic that will receive messages from the producer. +If the specified topic doesn't exist in your {pulsar-short} tenant, it is created automatically when the producer sends the first message. +You can configure this behavior and other xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[{starlight-kafka} parameters]. ++ +.Connect to a remote cluster +[%collapsible] ==== +To connect to a remote {pulsar-short} cluster, provide the full topic name and the bootstrap server URL for your tenant: + +[source,shell,subs="+quotes"] +---- +bin/kafka-console-producer.sh --topic "**TENANT_NAME**/**NAMESPACE_NAME**/**TOPIC_NAME**" --bootstrap-server "**SERVICE_URL**" +---- +==== + +. When the producer is ready, type a message, and then press kbd:[Return] to send it. +Optionally, you can send several messages before starting the consumer to see how it retrieves past messages. + +. In a new terminal window, start the `kafka-console-consumer` shell: ++ +[source,shell] +---- +bin/kafka-console-consumer.sh \ +--topic quickstart \ +--bootstrap-server localhost:9092 \ +--from-beginning +---- ++ +Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. + +. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. ++ +As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. + +. Use the {pulsar-short} Admin CLI to inspect your tenant's activity, and verify that messages were published and consumed on the specified topic. + +. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. -- ====== diff --git a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc index b51033e..ce1e719 100644 --- a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc +++ b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc @@ -15,7 +15,7 @@ image:s4r-architecture.png[{starlight-rabbitmq} Architecture] [#establish-the-rabbitmq-protocol-handler] == Establish the RabbitMQ protocol handler -Before you can use a RabbitMQ client to interact with your {pulsar-short} cluster, you need the {starlight-rabbitmq} protocol handler installed in the cluster. +Before a RabbitMQ client can interact with your {pulsar-short} cluster, you need the {starlight-rabbitmq} protocol handler installed in the cluster. [tabs] ====== @@ -56,7 +56,7 @@ ampq_URI: {asterisk}{asterisk}{asterisk}{asterisk}{asterisk}{asterisk}@rabbitmq- + [TIP] ==== -In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a token is included in the `password` field automatically. +In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a {pulsar-short} token is included in the `password` field automatically. You can also generate a token on your tenant's **Settings** tab. ==== + @@ -74,9 +74,8 @@ The following steps explain how to deploy a Luna Streaming Helm chart to create . Make sure you meet the following prerequisites: + -* Install https://helm.sh/docs/intro/install/[Helm 3 CLI] 3.8.0 or later. -* Install https://kubernetes.io/docs/tasks/tools/[kubectl CLI] 1.23.4 or later. -* Install Python 3.8.10 or later. +* Install https://helm.sh/docs/intro/install/[Helm 3 CLI] version 3.8.0 or later. +* Install https://kubernetes.io/docs/tasks/tools/[kubectl CLI] version 1.23.4 or later. * Have access to a Kubernetes cluster with permission to create a namespace, deployments, and pods. . Add the {company} Helm chart repo to your Helm store: @@ -110,28 +109,28 @@ It might restart a few times while the components start up. kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ---- -. Forward service ports so you can interact with certain services on the Kubernetes cluster. +. Enable port forwarding for the {pulsar-short} Admin and {starlight-rabbitmq} services that are running on the Kubernetes cluster: + -.. In a new terminal, port forward {pulsar-short}'s admin service: +.. In a new terminal, port forward the {pulsar-short} Admin service: + [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ---- -.. In a separate terminal window, port forward the Starlight for RabbitMQ service: +.. In a separate terminal window, port forward the {starlight-rabbitmq} service: + [source,shell] ---- kubectl port-forward -n datastax-pulsar service/pulsar-proxy 5672:5672 ---- + + [TIP] ==== You don't need to open the {pulsar-short} binary port to accept new messages when using {starlight-rabbitmq}. This is because RabbitMQ clients communicate using the AMQP protocol over the RabbitMQ port (5672). ==== -+ The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. The forwarded ports allow you to access {pulsar-short} and {starlight-rabbitmq} services when running RabbitMQ client scripts and using CLI tools locally. Your applications can now communicate with {pulsar-short} as if it were a real RabbitMQ host, as explained in the next section. @@ -164,7 +163,7 @@ Astra Streaming:: -- [tabs] ==== -Python:: +Python client:: + The following example uses a Python script to create a connection between RabbitMQ and your Astra Streaming tenant. It also establishes a message queue named `queuename`, prints ten messages, and then closes the connection. @@ -244,7 +243,7 @@ started a channel If you everything was configured correctly, then the `rabbitmq` namespace should have topics named `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script. Additionally, the namespace's metrics should reflect that at least 10 messages were published and consumed by your Astra Streaming {pulsar-short} topics. -Java:: +Java client:: + The following example uses a Java program to create a connection between RabbitMQ and your Astra Streaming tenant, and then it establishes a message queue and sends a message. + @@ -314,7 +313,7 @@ public class App { + . Optional: Replace `queuename` with another name for the queue that publishes and consumes messages. This name is also used as the corresponding topic name in Astra Streaming. -If the topic doesn't exist, Astra Streaming creates it automatically when the producer sends the first message. +If the topic doesn't exist, it is created automatically when the producer sends the first message. + . Add the following code to create a connection, channel, and queue that is used by both the producer and consumer: + @@ -404,7 +403,7 @@ For other connection methods, see the documentation for your preferred RabbitMQ [tabs] ==== -Python:: +Python client:: + The following example uses the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. + @@ -460,7 +459,7 @@ deleted test-queue queue . Use the {pulsar} admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity. Make sure the `test-queue` topic was created and a message was published and consumed. -Java:: +Java client:: + The following example uses a Java program to create a connection between RabbitMQ and your Luna Streaming {pulsar-short} tenant, and then it establishes a message queue and sends a message. + @@ -638,10 +637,7 @@ For more information, see the documentation for your preferred RabbitMQ client l |`headers` |Not used |Header name -a| -[source,python] ----- -channel.exchange_declare(exchange='header_logs', exchange_type='headers') -channel.basic_publish(exchange='header_logs'), ----- +|`channel.exchange_declare(exchange='header_logs', exchange_type='headers')` + +`channel.basic_publish(exchange='header_logs'),` |=== \ No newline at end of file From 5cff90b4ef8480e2619c8393260a4e64b09d11ad Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Fri, 9 Jan 2026 07:53:06 -0800 Subject: [PATCH 7/9] move JMS to starlight --- .../images/pulsar-client-settings.png | Bin 39043 -> 0 bytes .../pages/starlight/jms/index.adoc | 174 ------------------ 2 files changed, 174 deletions(-) delete mode 100644 modules/use-cases-architectures/images/pulsar-client-settings.png delete mode 100644 modules/use-cases-architectures/pages/starlight/jms/index.adoc diff --git a/modules/use-cases-architectures/images/pulsar-client-settings.png b/modules/use-cases-architectures/images/pulsar-client-settings.png deleted file mode 100644 index 7830ebaf1812b46ecafaf361642e09ff546049df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39043 zcmdSBXH=8h*FCBzqHq8egd+%e;7BhjJrNKzqDZe&0;u#Z5JE>OqTv9dfKo!}y$GRq zMd=V)2oM5-(h@>wp@niE@Vw*wjeFla#=YPEFP}0(o+o?nXYIY_nscta)zwyKX5?Z# zb?OxJqlfqPPn|l8ICbju$MffacP5`UaGpB#^3DBTRzRHqS1$-IDQLekAg@eepRV);I>P;sd*XBKdS~gr76y&*L3B zZ^iW^#g9?BIs&0G@NV#pVfo^hz_cdZ;jMtJWz}@+gSFrr;11IOausgspR~4xV!oq$ zz%YQnmvbTEOut{Q2J;Kk{eDwb_w4WY!qU(GesNCq((f04g!2D>@#k3xB`iV=aphzF zB43-?de7b!TKau(a&D;X>Elnd2Dsc))yu6h1}}R&6T1D++pg6lVFQi( zcWC|VZH2pbhSDvOB=^boJ%iS)r#uoOdgDtXCBC+2AtzsR-R7R^;E+wMHqwpt8uNsG zB(rT*Ax6XU)Sc@vfX?iE_f$TvV6*Uls9yr*b8L^$e@1Y?u zqia|39mxo{N-8(34t^BD5-gpQgPruBc}{*ge+8qGFcdku%bG%G(0qqg(0ks&q5(ms z#XI4Im_gDUpGs@e4)1)@hZ}4`uOt`~t?}Wvr=_&+jmSC*XK$)~#3b-3D zoAlA=-&u8SorCmb6-r4CMhXd52*5RW!!O&8!uYlqW6Xb@h1?Kz?k;Iqzo!o|_Sv$Nej^0abJeZHKarnEowh~{%Lko~$6P_9~EHk;&LMM>Z zxatJcUQn(sD^F9}(O!Nh=oYE*DEcg2lG;I%_IIP^qfhlAJrbx#<6nlV2HKT@p3tY=bjX)Ka&>RAxsn%Z{7!$Go?^BKnH{k1Mp=Nj z`zAI%@4ltJfuzqu{HB0&UM!TICRx@L=q zY&iWZ^>(q=$)0Zw_$hl9(&0VNU>}6sf35+a)Dz`qL^M`;BgBk0`mRKey?U)QJ2#k5 zY=cd|Nf)MBXw$9~9!c&?R;YVGvqKLq6nlBwS*v|$QSyFpV4*dSi}jDxvy}_DMRMn= z#6Yj(#Ver+EjtP)+uL`$@pZZ||NdLu&u;hAXEYtfqCYho`4Y#i*x2W!?3&8An6M$4 zJ*Ww?AWZho>;gtpiOF>LpgEU8|8VxFB8m6kVCkDi1Rq4ub$pBwW)RGt=UN*8ecU%$E4*w?~q*YZp$~|*=9=`H!C7dOxiZq zVGok@gC8#kk6Xq8Z_yEcI{N2?rtaTbH6eco+#-K_;*dQWk3I$Ock?{?{vSwmlWN>tKfI%I zxYWS&33YmtM7$e&8D*SIpWl-#So!NUKlcU1ro$82tv6igMb9X0q_(J?)S^WNzRu*c z3ils~MrhY^RmkN$JWTQ0{4WnwOR+K4m|(D?XEi7J8S1IIz(2ZWn&e_qM+gas&S6s` zHcXUBM@MQ+M-}eDgcLIK?uINc!TXhFjk!mIxSgwdoV@a=EbD3V$I&UFQ>QxYW+Y>F zz;)GVd+A(FSw`!>`@*YQNw`9SP@DN}hEeESIj8zmfTn~%-Iu=Cq5Sx;3st_Z9F)Q4 zET!cA1J0_kEEt_LovVWIke61-&u~c}>!J7kidScqL;7d#SOww2TXf;s5f_k(TyTm( zCUP#)Xqpzqmuh=uMaND&Cu~mprlBF1i54zCadJ=vQg*yyT}HvnOe@*O`Wc8UB-e!) zi{B}ZlC5&}_kn-v2lW4Ax;uFkr*57H^7!$e^}iY8RO|KspLz55_5bJGh?@mbiqcxV z3oClf@zq{@iG?ShI6(DKJmvC@$fmU|SXEYO2v!yz>|cNGbk*JLAZ`#*%Z>{LX?RphBokQ)w63=n(uR{ZXl+OIJdm`k8v*uFo zp+-U^tNfD*y~Lr)X|9v6sIE)T2W31lQghAH@zS}>e!2|T@F#o8KZR3w3@jFcy`q92 zf-(jUdHX)SS483|;rFR3ci^H2qgg@o_1UGRwXTp)ZnVx#TPxhbs>tyjeJQSz!cNP> z-?u)1bnzLR=+>_M^u?KQkWQ-1m!Vh04~5P=qfMNzHdbV_RH#e7NU+%wI{vjCN&_B= z-Kz6)U4Dq3IF#nA9awiUzE{$RFyVCI_C@XwJZ!=~EhJxcxS-XO`~ihJ zyEh@9sNb71Yr97@swh?-d5FK2kf1T?I_UZa5tx!_r@WN5o;g-Kr>WwddRw7LHR+ncbk^#llT`&CoT_bFbU_Iy z<6eQ|?zpCc@H#ONrnQ~Okx-{tTwNdj%qlvfw7gq;b7_wNk(kyZeSJaVt$M_>M>BWr{z84rZG-}MhdA^(X}R~Yd@H=(JgpKzc6!_Ac{vJS*o&@ z1%e!OvKZs9+z{0Cc&?Li8@6w4gB0*^Vrfq`XE!hbL|LAC9phOdWvb` z7~Cx&*s2MXFkwp<|NgE5RX4~;`=w!JjVe|BryKYRD8Wa4?QC1&tdb}upqW-52r77z zWU%$rNI$PWxAK<-Pai8P^woP#g`n(2?(Pfq6{J6Gr_DVOW&_Al-*ormwRritj{!1@ z;ycQN-Xd|fXwx|5&4q={c*z5C7=Q1B9CPcgP5djJ>zcQ5saOXOo1tjl?|mcHDiyY3 z&z;cS$%kkMWyvFt(Rz5pYh-MUBdwl}$@L7rk5x(()=mT88lOEU_sY@Gq{Tb*qI-1e zbfnQwOMBuD3U>=B?nE5#4kv0YZp2-F?w0<+4NiB1lBO4QP-QTeTdevq*7NbLQgFYG`tPfIpeDhCz*8 z%HahG0_8N~n2l8MQynzJaPs`nl#58~3YsD_B8(qQ!eT~~`x%ahLa77JV^cSl{C*aX zbDaEYs3Xyh=cwdK*z08xyZ$x%u*^IzSC;CJ0WyC~M149{W@+>sexJ}{}u6;_J=P|#;9>nIKyZ3Zq zI-wk2MJ}ZUGH%j20bm`40fZ4gU(Y31AA%47Du(RJDXpjxue?iV1Dx8AN>G znwdUX8DWRVq5LJ9VzyF$yHb=n&Ie@@C9S{>H&h3IQt%saC|X?V9H#`GWtPXldxL7@ zch8uLkDl{|G*oPbVt88)+K5{|VjDPxLfvQLH~r_g!XGq(oVTzd8+k8{wrB=bcKRWb z!i76NJmy0*XL0&b*xnbU++^tr-n`RimhG3ic*n4#!W}GY8;=oUqhNiAE_RDm_hVmE_*&e z_jzvg535l|{cDF@Ain!rNKtE;#s#?96FtYAZangoPy;EcDW}QEvKe2uFr{rD-=7== z>v79Av{U}*gtIJ)ZVK3!gUiH#8eT(`9^W6g`M@1I4$dNL&E0{=FKsc_L{CETp_K2I zJzYz&!z%9n7N!BhfB1Vt7_^#d`^U2iPR35}YN~5f#w|0&#rVonlIU;Jz=Bn9X24dl z5J#(6zAwA3Q0icE-0b6NeNOpRrZ3o(Z?GTPN4~a4*H{ipB{fcWOv?IPYS%s_XP8N6Qm4tSqVcFvX z5+r?u03VoAge8t=;TsF!B)ZQ^`%6YB7B+{Ii5*@(3u(1-)3D!ngz|~pS}LtO+2^g! z4|LD&&mDtZtGvHU_ofu>$$Y;rp!>JZ{@)5~p0}wEQqdQ9@)>z#g<$*3pWT#tMtdxr zs`_Dz{?!gWkgXdF4%h*;9Z~BBO_4R#w?5%9nM1Ws%}Kg;vKD-0m3z7Zt{sM!X2eF! zdqyLfEr)g0+7pJuTFgaKc<2YMi0GpvzK_k7riGoBuU(!8CDiL&Htd80y?1g0}csF!UTIXcmD)_|dVF3(oVw~$;IC;UZTg7#- zpuNql)*vI1duG(7B|oRvG3$^)o;}&+1!XYv5jfnmb~ZLqRJ5eG^oF5D(TZP9Qr}q! z(*YuBBN9z!-?aFUCpNj|Q{>XZX=aL<`lSp$UK?vDaIl*t;TBCE@#MSV^1+>g*VqYr zrAF%S+Z1s*crW~ISDabPp9~MKN*v`Wx!dSh(y7J;8{508sr%1+D%+nCU8t|tv+qv* zSy^-X5dne(_MA}>Av1J_tvdkH}@eXNrUDA00Bbv9LX*i))N3^ zK4AvKTg?Da=((~9ank(@W@Yz|7pO)>e#G?Zqk8AP+NYZJgx&o|KKF-g8qkUQ#m@Z_ zU9yD3IJQ=qnB>;)v}G+?vWw>#Nm8S<|3cjZ?ONDnHtmP#r1Zra-h{H<#?!(1?6@Q= zLdCAjcpYA`>V!gY9<$K3iEX{WQ{IBY4!HQ7)m9KjTxLOjMMZmeh~ZzbGa|ABl)9ET z(J5y@@6p`JUQp5a?O$gNnZletllJ4yJ1V(Xq^6z^Hl+D=OhlOm;QYTll+&zGzql*# zPw3O0qMg$S?)E$NnPKxAK%q<}5l4bb*q38_m|S|#^Sg)Z6>x{!s$aX&PKWdTOZP>C z*R%v9;&xM22ApU?YDwunY>jVhJzq@8RJT4E?>bPZbdOVeL1|~ze=4kpW`2ySrv^o~ zw8w@3jLJhe+0ng!6TR;t1QPaKNg1kD`ukb6P9*==TV96nvMhIBmHW&7b}`R2HnrzU zuh_WL4z)#d(N!_DrRx6~5`gc~h&Vx~j%tPHHhc6HOA_571#IHUc@D~3>b zzU+B?8+XBGoLMv3`zv>V>vaPa|FcGxcdL@pJKfuO^lZES2);V;sK0KM^_|*Z6E+`) zYt#&=#{qU~7dY}F+EUNYq%T^!qgh6BWCAx{wb(WlY=A=fNgoMODEu&{H0kKhVN*@S zdkK)R|D8V;cjQ1FyGbv&Ws2SnGpvlrx|8pw5BdAfFD2gKE0Ey15+z6 z^kH6bF|Ll0MObR5z@oYK?iCT0%}0K6)25}x{1?|biuZS9^%+~ged>qhp8{293*8)|GiS3)>&-7r?T)5A zFcucBI3rr)zV&tN73_85>*n63(GZ`}6WZaW3Q3k8vZDPQTT*{hxu}8!317GC$U?U`2XBT$Q1iY4nC(x4R2J&sALxU|DZ0Gy43E1(9%sPGu?eenu@1pvM( z4bJHhPUUBR)yxy!$P2U0GaIj9(*Kxm_jxs+Z=A%C#M3uP=qQ$h*JVZc1il+F0+;*A z6muEOulW0X<<>LIFmQyMpdXG8YSftzIR`bQm1yQqk)jS76^F@;3=p%XvXw#?U1LMD zOTL1njVW!ox`L0=F-mz^vOW>Y-}GtN!x=q`-Ktj>!g>U&;b=&ZBV5$X25)|ay>1xe znTH%tB{lOV>n^D1fM$%e&=bulChP~^ShzjzNd-{`rnUIOI#RBY0?frUabbk;C!8+& zeJwGdY|+pGcRMdlekdPEEf@}U|CH(d>_yQtbZQy4n$*)ij`^3=2@l=P(c4UBHO?~bE83e}kk*t|%Yli1g!jB_ zS1ZxvYS2QA@ZLiS`L9AJ8=UeUt|IKeW|)-1R_}2qW6b3FrQvVq5vzj9LrG2ji`T*F zk2FhVWnE}v;OO1qS+xel$z@YYlwjRWgPJ654tK7B68o7Ca-sZkN>sp1|RgSS3`);wAUGX}nx;$7&Ipva*X-v zZUU@D2OCHiZp_(XpI~Y>P_lMf7I%XkteoHbxMs?S9+FF7fwF!)LwP6LcDiv~&^#4I zU;s1_6h6F@@-<5ldXTG1)0p()8v$r3;I3nr0g{b3WV-YWwuGym6ZGG3ZzC!F{8(kD z$0_$nS5^dXA$W!U{%=rTJ$f!Ilb%^t&^sNb`Nh<3s&2+cA2xls9QX%4BT|1>quo5qTz9sTCFRCp z)ql0paqL}@ZmA3@0Adwh+2KZZUdHuSn269G2Y=PMRAE~_6`A|D%C&dK!A+U>vAkE3 z0+x-(XW}1(PXEM4ayf!?Z^PrePUt|d3F*dD0#jvi6t2o5g@Be&V@grkEjQwd@Kn|l zgS^WLGl%AGv7#?()xhMf68|k}ouiesjTQ6p(v|877jsv(?&5P3!mRXIZ&F*>e&KHS%YMK*0jz zn!4V&s|h0m8|d4Qqv}7d=-q>WJrGm* zo6!1=jb1+jdwbJs#;*7!+nX7a%n&2i9(mS)V?d(dqrGkf^__6JWoWah9B_xN@~ zP>cvt6pcUVWd2a0lDF3~DOn-D)WjmDo z^_%ZA+CnpwqWcmnB_-^s&Xl9}*FfKCo;AErURp`sbgLcYa46V{ zuwp17^bo+D*#+^+l`5Pjh4U$5$@}CCW6N8vJtzQ~ut$vcUx?YcusO}*)w^(@l)NUU zBQi7UwWpHj<)-`o&kZrhCESJRe>5FD5B)ZSOoS$VCNH*!z{dr+?<=C17$8I5c=dU- zQZli(HQtW5_DiDkaS?XFW;q~;zFtY_h}#S**}=@cHZPqFSU5`M@5xM)FBE@|WBo1g zheXSZ0R#_*h2-pBl0p37q!6IB9m>Q%M-M^Q>vEbk2zz7)SCB5U&&a;n&r!Pex65te z3fzyS1O2&`5n(TO6QTnpReBGyWhTG12TJJYx@(EF=8pJ^@XouM6tC1gGRN>LU1W-) z6V}a&_=*y^KPB%?2z$!Yw{$P3zxGw1e<;5Mrl4U88MD9(31~6gF4MM-H&I#slF*ng z>Z>3SydI(*XRC+dHnKzG683UcuN)dGP<}s+Ros}h?ys1s3zGa~eDe3=AgQB)pDArl zMd%e=plfu2y*6r@CW$9;M8t3k+VBg1b-uX!IKbz=-T|wRL-}}mXVsnsJof>X;5`PF zS`?@nGujt-3;|6X~Ho*eEJ2YSUX{HC_e|eyZ>%f>$qlPRMLMw;Dpg@#+22 z>JoE-s>a#xHs_XYiLI#+e&qC;3W<2$kE2Rz@rBfcNKSc?Z#myZf_Ol$m%kTo{MS@C zKCKvUK5E!o9@G**f*gpKPIAYNv&&84_0hw(=izRk;r5B({kGj}j0nqrKvBA}3^;)# zGLt4Nt!$_uJ7&M^Z7L6Tola0*Sc4%qr!Q5d;7oK__b*MOfWnTbm1nrK5MQ2stBI^p zVNVV)%Q+@mBg`>TDE_AN3_A-V^XvP#`_;XC2W;nI055o3cpW8FD&10VOESw^43_%? z-6n9Z zXxp|dZY6{Xas-#f)Ge+I>*hElFUJ4?wK_Ek>riM~-m>lR`Vzz!3M>RUYoOGA2r21q zQmjv&NC6ua>*{867qqTCA%n1sF~XvyMyP|TEezQ89Gn9`LoXip^t)M_`9c1hKwdUC z-{^23rVTh9J`;*De$W_EcCVpuJdzfiizfspjy0rJ6;1Kz{i5*NMLzxl#q2BJr}*0u zcQED!(ist*xIYkd(`Oo5WY4fNH3ooF88;n6R>vy@O4gg1RR2W)W9?!5_$c}uObtml z8qJ~$=u64mC27j)($zFR=wkw{K;T+^=fLR80G|5IfX%l^YqxmHqHob?6 zpT?tKQrj-T{GGW?)u9zSz*o?#Ua~xM^l__Aqf)2}vp>{gPUE7<{=^{TFGxtr*W+=V z6uspX5vXz;x7_`RGmqu>jE>%NdK?1)4r-nA>e%h)BJcnzpj~M!IpIEPb5A`R0aiuq zNl?>-At~JS2A~Q0)C*X8at4i(^=_~(E^hXJT_& z!}(Q^WEOkJxH5EY#=ZKyWp@rru8Om>cbS@Z(Ih`@2SD;B3j+HMzb{fkV^3^AtsHm@ z-Lu!H8+IPk)>Cu);uSl(ZKA-Q1z%7PwlpHtE+3=xR_;gui-}S!bbo0@d*-3(bJG%# zY3p$FfE&LLMPFw?^EIDCG9koIoI8_N>W=oiw{D!9ALY9|{#zLSQS!fCPL{jI4pm7R zcvU!{=cV5PWPnk$2f4~tvdRnxU-aMkM*4g+|6CEJzZB5^!`}C05*G2{|9~1KPEA?$}^rPVMc`{AOUa}{*QT%_9rRqDHz*cERv0q~E z+bKSKo|I%cK_7lUSwv8XylPiCX)u%sn%qhI=RQqecn#)v*J@Xd>E~{Q3o;hMih) zMsqp28uudgaUIv=$^vOB zYT1zz1m&Y_p;Qk2BHOj_rakDky*-p0cq_hTgUvrx8bK;>gK8A?y9;ave-7Fon175s z<}a^yq4Aou1 zzW9pFA+xGLd?_L|eKBLNaQ)t2DtACib01HN#EaGc&3~dG8@DQ^#6mMqG%k%o@RF66j_4!R7k z3nQ>HBoYOvmXdMQQsW{OA*>=9Dw7w5GKa;mItV@|9J!fs#^4W@274bD9qANTIE#=D zjgOWc{VKujd1ryWsfbEqwX3V{yG{0UsHzP^L#YaPc@0b_wNUS3IpZ9t@8Ls^wkp zCy#UW<%C5=C1Ioq)i|EjT2$0_ejo)XZoG03)G4_8Dv-38M=n(I{ejrO-kq%z14yU_ z7|IE$exi4otBxn-Th$oC0yv}{5j=$ zUNV>DJJwxBz)RJ#ttNuU5R3a_-gh^&$44)zIo-uIO*aeVrb)#5EOy!})${(j`(eqw zKV-{H$YWg`;8k0+Zz@!nZbzA7z)sU4OUcPa_b{uTpzW(bT%_mg+q>1;won~V<~}R( z4cEDUEeq=uQfea2{5LHC`ZqM=m^+HnF8ily@m`I~Hx{*$>TWIb7c~-(>j?!v86XB4 zwKIA)y6hATtKUgPcmQ-Fqjs5R?ASEM$zjXUt%>;@Wa>@kPbkh??1QVb*37CPfBswc zX370=5t-qxioc@3nTt^@%sC4{ZTXDRY~i2{b4c8l&1=S7-cvsc{QN-DpvCB(V)XvZ zKVL;<=vmE$o;6)xYOWVU{>ZgkeH*H(S1b=Maj8EL5b9LCHS^K-9!eis5ghn9j9DAm z9ZXm&{6+Zi+rjzSFNF!=>7#^>5!z*X(gND)WPR)s+d&)ItgAVvgHHC(tGZ?pCM2D~ z)MfX*$SbT6$Hs07NOwCf*3sD^J`OU^qO&JyMgZy}%;pan4*rKWi<-%Uw*8Db>?Q+q0IF99+u^Cc&1lkEF`kU@*frEPhE zoI-QhUrJ@1Q_s{g{L6x^NIZJ+LyK*9-_$(#6e*F&IWbo8B^q7p4RGTy0mP_fFG&8) z2|IHgS4|Ju_J0pr9e=q(-582>y(je~SD7G|9ECf%D6k5A&EGH*h8R%|4 zt1wqrCK-bi=EMV$0Y~1}?1m#?rk1FD(2V_Ci>$>5sKYhW$ab=+mYwR_hduv0GOidF zV2K~JRX_2H&IC%rYNpJvOjwDYH{Q9(nBZo)h`SJO0I#3TJ;-d=ODZE0Q~QIKCx?>` zkL}E-?pC@oA!G*6DKRK|Z}>RmIQ)ZVcYU zw#a(noV)_>_J!2ods&^TfyIPNIrDn^C`C=c$gdA3g{aiU(A!bk)*Cwk0eZyj3CV-v zfKl0{DKzM^KW7|8c3*r3ikUYTORFzO~M=>5Pj#_zF)Va;ICfO8IPL6{12q_h`&GSl9c>+pX-a1cg`q&F#T`J1Q>$>}yLsaUb_um;m0lj*;7! z3(AoMP-WmpWm! zU)C_GUixhGuanJPF_hoB=wCP6l;{6;Mc7Mqu!lhdjx-{~g|ir%s`owOQBle0jk=5U zj)avO-D7%H;p%-*jEzMvdAvwmip5X2zF53}tnR;db`PVEhQpj4{K)}L>x##red<(o zS9@6I#|Qx9^G$n!xc5u@p_^B?l zv7e}r(2JFE50Qa)N>p-S(Xcl4k!&hzz=I}6mzaN8tEn)okpB;Lp*P2vgbCszyULU8 zDKtYM;qNc`l-K*fVpLY~wNzJq24y~7?O?mKg=|nBnH2z1a@*HpI~rh(k^$39DiY`V zLF8a1ncOlJG|79>|A)9G8cQQO|Kn`(;;j!mMX$KP;H?G;!xt}nE2*S9enqcOD8SGr zfg%jBeAO3hjR_w_^e`g| z*%0zR&c1XT_nN;59fM(^zxcxpG4C)>$xTN?NW8pj?Kt@$hAu)_D&M=AB#DS&OPdn3FWLakNC1EM&`Swd!~%Y_Y0^23QN7W_$E&YT0>Y&L$HA^> zFsjeBt@anb#}PIv$WHN4|Eoj@@RS>WQ2OpFQ!Bh_5H07vZ=yt^4WX8 z<6H4{mKX=B;yaYIq2ApOudX`)p+i62m-*nsD|@Dv2AEPLx>Rq!@#_0uo}ne5tU4UG zcecj|wRWP!H^uDekc>A3QDEB*%Op;AB}4e+?lsz0v%$i)9yaB3zH!i2>>w)wAZw

qG!np0LJqk0O^4%t-DT2aHg@3QJ3#lDVf=i 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⋙5QS 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 RjD5G@aYcDLKScg3`*;2{-wFT# diff --git a/modules/use-cases-architectures/pages/starlight/jms/index.adoc b/modules/use-cases-architectures/pages/starlight/jms/index.adoc deleted file mode 100644 index c6c8221..0000000 --- a/modules/use-cases-architectures/pages/starlight/jms/index.adoc +++ /dev/null @@ -1,174 +0,0 @@ -= Getting started with Starlight for JMS -:navtitle: Starlight for JMS -:description: Learn how to get started using the Starlight for JMS API and get hands on with a producer and consumer interacting with a topic. - -Starlight for JMS is a highly compliant JMS implementation designed to run on a modern streaming platform. -This guide will get you up and running with a simple Java JMS client that can talk to an {pulsar-reg} streaming instance. - -== Prerequisites - -To get started, you need the following: - -* A working {pulsar-short} cluster. -* Access to the cluster's admin port 8080 and the binary port 6650. - -This guide uses Astra Streaming to get started with Starlight for JMS. -For more information, see the xref:starlight-for-jms:ROOT:index.adoc[Starlight for JMS documentation]. - -[tabs] -==== -Astra Streaming:: -+ --- - -If you don't have a tenant in Astra Streaming, follow our "xref:astra-streaming:getting-started:index.adoc[]" guide. - --- -Luna Streaming:: -+ --- -Follow the "xref:luna-streaming:install-upgrade:quickstart-helm-installs.adoc[]" guide to get a cluster going. --- -Self Managed:: -+ --- -Using a standalone cluster? The Starlight for JMS docs provide the "xref:starlight-for-jms:jms-migration:pulsar-jms-quickstart-sa.adoc[]" guide. --- -==== - -== Messaging with Starlight for JMS - -=== Retrieve connection properties in Astra Streaming - -. In the Astra Streaming portal "Connect" tab, the "{pulsar-short}" area provides important connection information. - -. Scroll down to the "Tenant Details" area to find your {pulsar-short} connection information. -+ -image:pulsar-client-settings.png[] - -=== Produce and consume a message - -This example uses Maven for the project structure. -If you prefer Gradle or another tool, this code should still be a good fit. - -For complete source code examples, see the https://github.com/datastax/astra-streaming-examples[Astra Streaming examples repository]. - -. Create a new Maven project. -+ -[source,shell] ----- -mvn archetype:generate \ - -DgroupId=org.example \ - -DartifactId=StarlightForJMSClient \ - -DarchetypeArtifactId=maven-archetype-quickstart \ - -DinteractiveMode=false - -cd StarlightForJMSClient ----- - -. Open the new project in your favorite IDE or text editor and add the jms dependency to "pom.xml". -+ -[source,xml] ----- - - com.datastax.oss - pulsar-jms-all - 1.0.0 - ----- - -. Open the file `src/main/java/org/example/App.java`, and then enter the following contents. -If you cloned the example repository, replace the entire contents of the file with the following code. -Your editor will report an error because this isn't a complete script yet. -+ -Replace placeholders with the values you previously retrieved from Astra Streaming. -+ -[source,java] ----- -package org.example; - -import com.datastax.oss.pulsar.jms.PulsarConnectionFactory; - -import javax.jms.JMSContext; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.Queue; -import java.util.HashMap; -import java.util.Map; - -public class App -{ - private static String webServiceUrl = ""; - private static String brokerServiceUrl = ""; - private static String pulsarToken = ""; - private static String tenantName = ""; - private static final String namespace = ""; - private static final String topicName = ""; - private static final String topic = String.format("persistent://%s/%s/%s", tenantName,namespace,topicName); - public static void main( String[] args ) throws Exception - { ----- - -. Add the following code to build the configuration that will be used by both the producer and consumer: -+ -[source,java] ----- - Map properties = new HashMap<>(); - properties.put("webServiceUrl",webServiceUrl); - properties.put("brokerServiceUrl",brokerServiceUrl); - properties.put("authPlugin","org.apache.pulsar.client.impl.auth.AuthenticationToken"); - properties.put("authParams",pulsarToken); ----- - -. Add the following code that defines a simple 'PulsarConnectionFactory' that creates a JMS queue using the full {pulsar-short} topic address, then creates a message listener callback function that watches the queue, and then produces a single message on the queue. -+ -[source,java] ----- - try (PulsarConnectionFactory factory = new PulsarConnectionFactory(properties); ){ - JMSContext context = factory.createContext(); - Queue queue = context.createQueue(topic); - - context.createConsumer(queue).setMessageListener(new MessageListener() { - @Override - public void onMessage(Message message) { - try { - System.out.println("Received: " + message.getBody(String.class)); - } catch (Exception err) { - err.printStackTrace(); - } - } - }); - - String message = "Hello there!"; - System.out.println("Sending: "+message); - context.createProducer().send(queue, message); - - Thread.sleep(4000); //wait for the message to be consumed - } - } -} ----- - -. Build and run a JAR file for this program: -+ -[source,shell] ----- -mvn clean package assembly:single -java -jar target/StarlightForJMSClient-1.0-SNAPSHOT-jar-with-dependencies.jar ----- -+ -.Result -[%collapsible] -==== -[source,console] ----- -Sending: Hello there! -Received: Hello there! ----- -==== - -== Next steps - -* xref:starlight-for-jms:examples:pulsar-jms-implementation.adoc[] -* xref:starlight-for-jms:reference:pulsar-jms-mappings.adoc[] -* xref:starlight-for-jms:reference:pulsar-jms-reference.adoc[] \ No newline at end of file From adfddb6a24560f789a074fef46b261df45b9fd45 Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Fri, 9 Jan 2026 14:20:45 -0800 Subject: [PATCH 8/9] move s4r to s4r docs repo --- .../images/s4r-architecture.png | Bin 95286 -> 0 bytes .../pages/starlight/rabbitmq/index.adoc | 643 ------------------ 2 files changed, 643 deletions(-) delete mode 100644 modules/use-cases-architectures/images/s4r-architecture.png delete mode 100644 modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc diff --git a/modules/use-cases-architectures/images/s4r-architecture.png b/modules/use-cases-architectures/images/s4r-architecture.png deleted file mode 100644 index da4692ba40a8406c970ccf4790ad072818042536..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95286 zcmdqI_dk{K|37{mdyfzqS!E=9WIHm;C?k8%gG6TbL1d2zksKqGBpf4q&*Ip7kL;B# ze4oAE@7w3~`TPstAD!Ffa6QN4abJ(frcRn&$c>?R1pVkE!!!)9WRl& ztYyoc)^a-|#kO!>W3PFOwWpm;O%|;LEywM*Nr;Ud>1N+)WQa*g{SGt>%wFIg5_3$B zuC0wf6}LdfX3dfKT?~W^cAp=WPyTRnaWGUmj7!5{l<>)!1Y@jQlw;^J-h2AZ!;M>Y zS`w60yF!?Q&|=af#+6>%`M)x%7{X5y&(3lmb<%|g5qChp{_WGv-us@kDEaqr5vku-!PT!A`3=5TqrVOc1nP4@=Sib9@Ui;m zdnZ|+330STA3Hx+q3^iP>xKdj*B+7Fc>Y|4PMNCGb5k=pHtvD|bfOm&$TkE*njXI~(keSylUWJDA zyooO<$RDr~xLVvw;gzCTTM#sa&{@|pe`w!wi}Jf%fB4`R;d;Ckc8R}8%V&~P2*on; zn>K{+{rowl+Bq^p^{Aq)-D15;B^G-2U<#x>7Hwc$7(u@y(IL@Kv1 z!vu9{{u8r-=*$_eHV4G>hfG@hisFHP55F4zF)`uDpH-#(#!VM$358?R(vrVkI*7?I zTz#YUoy60PS zgvYHk$z}@*4Ou<>cxzV_Z3?c^~((g zdin9TXd9Mc?!e$KTp!lymX?j#%Q|8EK6as&qAx|w{!v6dyv5FNv#dwVmWeTt?^%>6 z|0VHFNg`bE-M5%H(0(}RQQP>s19j}1NvleEF^Xb1ty z04-2Wp`X}aC4hxU*h~|Ap<1_NtAJQzd(By3A}@8H$UM#nr9pvDqjDNODM=wmgza~L zrk7x&7;xM)%W0a;LJX_*153A&<3ALj!oFg^Edr`O~k3D1RAIQ+L*|P->XF0Q?I9 zzQ!Qq_na1y!Ga$)6O9ZmfbzeQ}VHA~c+DQj-s^pB4_T zBSatjXrXDxx>Iw3h4+#JPncSDhX>(4 zkm%=^z+=X|A`b}t>C@?m88N15}~e}z%cP7jK?uTJNxJbCv{p9qcnb9?*;e%Nc7VqcDM7(G&1XP){S4PhLk1lcW_ zKKqPdM8`BBVSER0#gEo6-_`}&g+0sxq zbHQtW_>2q>AMeU7TOF);Zi=xk?=39R?M0{?8%=e+`5k@hzpKKF#Jf^f=>*4E@AcM% zAJRX_7KwK{TbuPn?)*uHSf@JDjHxvEFMgLSGfL}@>vwTczhh~EPgXZj-T3s_P%^WH z%ECglzOJrpna*#$6(0{$IQxE6(|qa?DJv^6x4@F!X!dFD&6}Yw8EdZ-9FTD_)5^RP zyvV-p0Ql@I*aW@dyL)x@mvPK;mw$a?J77ymP`zz$9H_E)xPD^7S}9QEZS4i0><5$O zA|^!OJR4Dr&CP!V(R5-zA8Gxb2hE`SJ(1ilzcmTwe<0FN?J9^K?_Q4WgDxm6m2Z=Y zeD&8wS94U44GJ!a7ZuD+BMeRc`c+hXN%LKMeXm)R6eG&N(WNFYb_*43+tdu|kH|N`1H&qtn`hYgj_BZ+sH+SYqiXRrwiF0$m&aCd)O?GzKQ>sH+#CK8EPWH zMK9sT7|g8zWO4QBv2IMvg1^~?-)O?+7eaf6uU zKD)i#f2!-|?BJ~S!{gV)#LSTU;{b)F?Wu_$C%0KN!Cef-c9tW=L=m}*idOvYGY6G4 z=(w&!1aAIBLw{`4fRpwK9wLhTgOb+n>@TH92x4+~i2f$E2s6d{%67bn))&8%KU%ph zIXCj2_&=vcS$4){_VoQAKgA9TRnfWvSGoPJZMx?UgxM}J%Z-HpgsY?P6{nB!A}h-o zo@t#C*tYILO^>12uZi5UAu)pU@~js}7i)%^VxAk%bxG@p?~4&(zMIyb!0ahGg*U~b z3JeGOx!~5)p}mxHjVQX}*pveQcxJiS)8R-VxRiKIN5Uhsg`Ks5B!uGzKl-@;6`m0b z(^hvx@<9HY`ZN+|IpW}-ci5VVC9bC>N){?F)W({9*aE0(h4JDFMZxDw2JQ|jd(K8utgeWL4OW%DBq21UpreaX zOpt}0cO@=OPs`?qnzS{<=;B3%_QE1Sd4_78ZeGGOPBq`h9m787vROrqjf^Bgrdk>F zj}moojFd@8ki)9w>`YQ7vi6!>kBQj|aN(G~F0z2vMa$}8mKGE@$|%;^xzmsIb);{dKj8wL&d>uqtaHWH!Xf$<2K@A5trn)3T>i zzt6F4+srfn=?g;*4GLkX!l%@7S)NoUvfb2>||BvF5X@+JdALF}Y`RLr!M0c1(XzIZ)0S&;~K zHJ$jEe(t$d$@jgzl}Wk|wDXka*_Xw|8(>q3cIzxI8Ui|u2PteGxXf~xzgi!Brh&ss z!m(07cBO)_Uh`{Y%)0rq%9>Iecrw<#Z7pgUjiC@ayG z1A-ZZt*WbV6KOhnFVG;X)4v}z$r7W2ap_M594%yDK2lTL94Y#Y;)$^s{W`&Qca-zI z16EU6DJCfBGf_6uln=JX;R(Y~6pfQeJI93=WJK4+FMCyZZ1v|b782Rno1VU?_1^vS zhnP{q?Sn_68E7a1&A(gUkf)31{rN4&cdn2RTRYjEbD6lI!5^0jtDwOlx#vFiqZ`|OM_BlA*nfcJtV&yz6 zoAe$kE^K@_U7h%?ewHNQ5puR#@Nom_a$G`{j+-kTyJ=o39?FuA(Q$F@(EqRe-+3kQ zU)wUdsQC|KmL?{C98`c3e{}aq117>SrH}rIeVFmUrTxnr8@h?pb4}xF*Y3ejMSucE zG3VmK^`AZK-EZWBpXB)BVH}ut(Qn^lV}3Eso(C9ZK6#9d`Lh}ZgLUT@-ZnZgeDJ_! z`^auh4GT?3$Sm3}jXXX)9BB)FE7ka@*aL5kNB@vN&xxe<&K*&&ueGm&mB+#D@s%F5 zE;abtPmL|Yz+l)9tI5mL)$Ho*oWrP;S5_Vme=gV1&^RnLhD?o(y{`jr*FQd58?fGX zNWz*1?Xt3}Do7R{{eYdAIC^t)v!dYHE!;J7W?5Zb>9#PiH^|UQCtn;4zxilyss$=1 zmX(lHbvK8GntF7ke)!{6@@*O4kS%of7ZJ$R@a(DV#pynkPda0G-ZDXPadEXz+YPog zjO|JgX6N~xo#IG#Y!SGj?8?Rl z_k{zhr?m7X{capU-jM|VS?_k}SBLVbJF>&tOp}Xku>hBk1UE+Dr|~!@JC4mxTe~Ob zR&)B@YMP_Vp)lf9#47cZkJ9X&KIiC-jgjH`d0ccdp+FH2a@0hXL+X1-Bh1;V{oor( zTfQ)~R&L*4V)7$p_BqY!64l@U(J>$@G;N|XV35iaIDc~6CF3!a{Fs=qT24J zSKPCFL$-cd+1_)kOj?}xZ|UArM=I#Y@&?|4=)J!(zHr_~3KsZFILtM~Podu~5a+}; z1FCPXD1(RKFX6Ug3O5sU$wDqC7lkk6|7x~GZ)Mn9TCV(-Yu(#+o)|5eGXZTGaO9xt z_g1ubk|sP{Ym6u9o*1hS0!1rb8_)#dlLeosRQb5*SR=SF5}7q;PNB zloSPi^9GKC5y(RyujA7@OM3dl-Xo`6U4OYYT6rA$=BKY-x&t^^#ev7u0@G-~JSwa6)cvL1mT_bq zZ}O)6>YZx*@rktGHsR#&*}{QdSb(!wC3|kJHA(90&G)cO^ZGz*-@?5x(qc)cQR&t_ zpzcI$Yc<$zO28Gu%Ofi**;`su&8uBYv$M709OwZ8+M^WIz((f?CAks`NG9I@i38_1 zt7{REl_$hJK88aO3_looaom3EYKdiBhze!tzWRDY7WW^`m8(>;e-9z34GQ|wGs>f? z-;D?a*U=+K4dP+Gp!G{&)vKI7LWZ}ux9bqu0qS)nqGfs+^X=c4^rot?$aV;a7yN{+ zaX$IDQGK@UXY*fS#f-m!g97w;EeXzwpVXyHEAh^;X&f8^i;WhW5i7= zD!;99?(Ze8V$f~Y5dVd~Ouw~cEhJtX_I%$53Hug&`iMrqlZI03nU!)JjDCq3Ei2v2 z9{%Ugo;{0xrf8!=ObXA{5QwUN$&URhYNJa-#1*v-FsPHG8ESN>pg*xBUBuyDMYwc3 zpVLf@>h}u&Za}v^2vx}_SAT7yBgl#3U0K%iHH^2nj~F_MjlWw6esZ8jWoFKRUhn<) zlsmaxhfvan9tHZ^is2qmJreju>2aI`H%FO7*o*1Lr>Ebhq_C!vR^i;ufg%3($3{(l zeD6byE9-Y$w`va8)fF-Q1Veax@4ElK@sg0wWW?u$dpfJ4q5^R#!6Go&J%RGx2N?ma%v<#ug( z{m5bcJwaW7REC%~E7Gh{mI!WQq*v;AHbi;eb5IwJWq_~78m)3-@&q>VuQC_|6CAbg^^G$pC(-~5Fbx}0d&8-ip)ckL`+%M<1 zoM#vtUbQcAKKuAlC!Cxa`}nc$<#afyyRVk9im^s<+&Hv{ONND#e~nUx6MUx|Rzj0T z;l7KzwS>p=t+*&l@@UCx)CLFhitmA#XmsW`8k*tsbmN=%4Pxq$dAb%DS8!{_X$_I0 zxbV=AFOg~D%AW+JA$B%R&AxiDX)9adK)Gh6x^V+s)8=Hrob`%K2u7bHo-11-+p+N{ zLyDU}7tR1gP~pjM|113sv6h?3=AzI`Aazn4_nwEpD;j0(8?-HApwB?qH>b&zHW_+* zy9f-{Uz~B#VS!Q)9ljEhl&Z~c<~RTG%>#zHAaBF&qy(LTSzPVn13Q!89=yP2`lq(8 z%HC?qC;%L&ba)VTxb);ejDE?doCFJBk7+VbPiqfm$2ZM4%CH4P;amqmEgMKxP8~4OzD5rsOXn*}%U8*LmJB$pHoUvz8Xse35yKE#dQy<}&scEBb@J+} z-AhYQ23+6kNl@pXF(FeV1xYap($D|(aV!mNk0_C!&+_I3eTh-My*xH!EDQ6mgJ7p8 zmei0Gj>2u-y|-?hhht+z!jyg=R8bXO%a2sLx_2HrV`WI&+wzq z43fiIbxx{OO&-TPGbV{F5Sa%75^q&owJ}hy$$XA`=q0bJ5%mpmzePn(O{hHN%O(Ro zkdK;d*ckgMVX4r|?;J9=DZKI3*C=EQA?ktiH98t!nd$Ku#QP=OpNCo2?8}Y?gv_7trTf;R3gH(# z$&w2Ei|)D$oQm@!U%+NXFq*G}2E(wI7-PQT80QG2|2`V4FoO`;`S~2*-JU)z49^o3 z$RWtWK`5pPWDoTnC_8Tq8&Ws&Lq>Lwr|+u7F>>O72K~;|Z~rc>i+Ugt>Or?X@G-y| zvSz)lw^H>R3H~f_ptd80?2th&68b6|5A+LWiKLHR-+>eF5(pU?w2Hu;Mq?+wvqrV} zQKFhF4)o-0JhB*Y5x?{lS1;fv7N!sX2?PE>ufZoR!~OnZy1KpJ1@C?%>ec3G{B@x% z@}s1uSk8jQp2bBHXFnEKFrq(eEIDP}-hYYgwgjm09JaCKhk&f*?Fw^4-HS$Lv=yFX z-@JXrzqpT-{8JfvW&O;A{ZF5i^kE+~bygF7z#q*^2byeJTyKeLFAogWZ?2k;g>COL z*OyX01bL`-J-qX+5F+i#YjU3QGJT>!mC8c)R$CJLFsv=Pe$Y*QU_g)yTU-&@AYe?B zyy7sEo=zJa+^h_vADjJI7q-wg;`AA){#x@uGYvoG3LU(KlHdEqTP)th!V2iaI;#g) zEb6JZ57Ai?#B}QiuZ)6R3QLBJpV>1{&X~V7qZtsduC8v5A#upZlYAI`j4hcAPXGyq zBBy&nS>vbqMgu9bVfHKthnJj9ZAnG5m*#{CZmp>1RG(-gM>=H30q^C{u=?<4XGUtK z05Z~<(8#FNe#MU^f&~mAHhcj6hos_^VMgUdoq$g(E|v+1ysIk6_E!GKhI@-@p?WTV ziSI%{V7g^No$&Z$pb$K?C?fWlIpT?0Kco25#wNsgjx7$R*4m1neoNJs8YLsm!ET7+ z#3aNp^1dcyMi3JhF*w{pwgAM!^`-xXh6ZmlmtY|PR#PzLqAyv5aCKExoSC=8|D^tW zm@nw&$+aXHB+l8r<+RiiZ=GbAkpR~%Wop9TZ}CXJ!+rrhH_}x}&Z<-awddQugolZL z8K#BgP@u}TK&ZR%|L~S`Y454<_`-wi5M0w+C&38Yy&fK|Z-dc$_1>&kATxC9p*i4P z=Yy9R)ys081QT@DD>kb7vyXB@#lo+$i_yB*eMt_;lmO+I_E}P?o|U zomtD&@4{DPG~#Ywu4jc<-G;Nv`v|HzIpGsMAjJ?8(k_<+%&qlm7t6!Y@W(U(kN&q$ zU0_H4#5T#vmgYo!U0a)RL!($Ojrjf%&=o*e|M{Ky_qxA+4JVYwTJOs^c{wU9$Q?!@ zA-Mh)`6cvCTtfdo+M!&20q_NyBWBr;EJ*Vbzqy1A<{u$F|iTQrGih~+}nDS!196ljAdyY+Ecxx|!d#g%P(Ottib*yqTp z3705{NX+Z7NJH!di7;!K?Mx*DSrYCad%_iu+XFvrE2AI;i5=ozXLonSk5BK+Y;fQ@ zkGO<>os^g}KYMDRUQ{9}DLM8)B*%#w8>y_~#Q41H^>0Zdh<9n{Tb7a180rrG9nPte z7g@NN>Z7E$+9Euo@{qZk3$1d~>qfWv5L~t8qBy1t2bRUfMb@mrqZ@EQdQdo5!_gZrmz-}qBN80#PsdZ(xOtz=hs>+RdYtU)1il)^*FSbrg5mu~yZOZ%tQcqqZbgc2f> zE%X*4o&fa=EL446ppk(!hQ&Dj_e~)pOv2v&##~U>P{A{51U1SNuYs$tZ-*;hd}?s8 z#%atf)>u`)m$(eTZ1W;xNX9W)&G^EJw1wl&owss$5dBXgj}AGRJ;9F`QIb^C!_#ly zdrCE;stc>pl{6mE@`qif6xQ0?!2{qk z1MwRdXXs892_|Yo+Ehn}_$n|#KOr+yt=~y{2w0T^)CejOtPQdk9nZKpwR3;Bye3R) z>TDV<8q?OAh@?77l3nW1P&5t>P15;>f(hP!TJtKB!o=*P45p9@Ea%3;;@pb7Jw})R z==8iNv)JfLXbsd@uG>+;jQyF7s@xEY=N@zRXG+p}weQhytqYMx>_U(4BFwNcYAN3y z?zl-MeEKw}xI1*eT6T`s6Y(DC@)ief1ph(J?W<(goi*6X4q^O^2)+9qhEe2*q30a< zjz7D)B!QRJ`X+vjM_vq(kU8H76vNQcHIXOlpca0nyHg-BK3 zj#b6Q%jG{BdJ4|XjdiK7YeA{Zx0r*d+kCdhKPy`s2W_hVJ1n1sji)G`#*}wv>&d4} z)+zmE*4~=oui=v)EbElpg{>X-j)?XKcgA0fjD1W^EjjZB_5n@B&j&B^a+~N74wXc5 zuJcP91N6wsD(|RhsTegOAt6zl_@F1~)Tq8YaD04k-v!!ht`f8QIOB-YH3tL$1L19r{Xw8h<^n6nTE6)Tuf`Y1Z8;7>b$^Yukp1uKFi1y zCsY@G-7iwBj@Q+?^wVCuX}T3S-rD5)Qn zBL!jTq9RT@rY985LBI=dGLhi8A;0Zkpq{Er65u@*#ZC|mzu;?lUUC&L>zkO}fXcs~| z)OxH(RV$i_DvNzDvGb#Ja(dI$Bw=Bzk;*j#Lu8iDm?g&@wZveFxIU%2Wo~ze?dMz& z9-V%8+DDkkyjfsCGlDTz9os{xUBO+?r1P49ME~E0BM^gmSy#CW%&^B{a32~Qe|&#` zEG+EMWw@m&3@A*GZ!VGkd7zy*Fp2~3ZH($tj{e|*i%}k-fp6A~(+(9bWR=)m{b%p; zz~1F+90y;0O7Flw|LsK2jIb;tKfD&%G)C^s1rf|^H!NRWO1C}|{S+E7<~6JTP|S$% z!&hUVr_@qP3c@fbLHEkXEeP#u|3eZ~HV_C%bw=9~ZRt^-8)ef6zCq#P*^a*F8kGOA zV7ZYA;Ln*vpG_;iOqV~Vg@9s8a-FfPPh*R`Ez(t4G;r^HXL~B%FI;D0xm*ZdRaNE0 zLD=O>3%-n3k^fhk01%k-?LjN^Y=>ret&vx_Q}!?qBO^SzzO}LLfdQYRjiY~#gc?f9 zyNpwFxOTQT@y`K~$41`$J*B1Gr6nqeL&|NrIt|+ljktC9U2-y8KdHU#%uaIB7vN8z z?g-VBGKfXxTcq+D^P2M^#RUZ?_Pm)D*zwKR4%cxcGJ!w9=ABui``%ygPYT_E+lI7? ztk)J!h^m69h)B<)NY6VqGC^k8--WlR(HkAHS_e~pk|UuHHTT*ghYlvbQBzUzm@8cv z5!d^j^bNU3iEnOf5R#01=6MF3+Nkp->hK45@7lUKE^E(CPqX2tynC0cUG|6SRQ&$) z&*Q_H9`o?JYMgnpN-}~p?rTOdyO^m`Yt9u~xTj>7MUY@7YL&@xi z=SQ2M4Dp%P_+I(H{jO8c*W*eaIA}JilTEoZnLpFj9lRVG7xxBJj*qZsw-`nVO>}05R9O24 z4Ggowto~2bto2#~GHzYK13(rw{x|kF`bE zv}nEm)uQ8f{$DLxWIM8Or)E(Kf#EchouKs-0J~)Qiu}H>O3e5|zq-4ZSHVdBMGJ7{ z`Ai$^=w3{MnzZY98EPgttUs%qc;35K>uv*Z7FCk=J!V;D^!Vi)5uO)Ep9SGgwq$T} zIt%w5lbqwnH;Ym|PF}<<~NIgSmx{^S5r}ZIiIb`KOL0sFd8g2r1#Be3Nx-g z#g>ws0-(+}lZrlp^zQ&ZYiY?je>ssz@z{4$|IHgL=YYSssKfW(YI=VD3`Bhx!ZWM^ z=@1p=Cu!9%*4zmtWym3E_3KRtv{}}ZtgK?j78095bjD{j1V~MdjJS7ET%Zqs{tM`J ztb@el=*H3Jn4n-O2+0gEhvIurCQOfdy)M~BXG)!P`6Yih2*_?}Sp?1?=#|C>2Bh>h z;K;M`XSMuWSS8Txy1JZk!`gvQ9;ndR-FI!)0mQyfzse?Zy$v3K*Wr?!A|22f+3hTi9cFKkwZNVNBZGBu<&PPVUO|Q z065~Z@bMNIRQSrYqtT4?wbxITR{mM?3aNyo@YaM?AiV(PM!5V%bd&pUemtC?+INu3 zW%!F^sru6Qd5flN`QyaA8N@L+eOPfOU^Wh~C@K+#e;2HQ2GxEu+y+{E?fwYpENm*n zVMYgk!)!_=nCVq!waCIBJI^&3Yst&)%v0_?AcDt6HYKZ#efg3Faxd@Fl0)LTo`D=C zNaq11OM5uLzOWschE~bV;me8gpm?<#DEmbL+Fo4^bBt04un2P;i;Xw_R1F*omzkO* zIFKo+lBI|$UoNE(NBW*b)_S|Qv)FXRSm-hazgdjWxr2`V@qFHN!(4=5TaTRqCSoKd z{73BZ-4733{a8A47KKb+ogYd}igF09YXeCYEq9hffb{b4X!w{OM;Vf{(;9-P?peFs zllX696S%m|wIU}Zvsj}MdmvCH{~nmIdw;TE6n8X90jO78TbHms-4p!$V33eB*pT0G zlZ{ObG++wcUEK+Fz0EE;nGk+tte*d zOgC+7js`-2dWP84#02T|hg9>zwM-E*kkrT}5FfAb%kn2YeJA#-Lp8VfQWQhw!>Z{# zqedYuK>3|G{Z4@;npc^cn3hl8l95q4cPAqLrZIIxU3Mv9a*Vi?*ADE3uaAa2BMBV= zN~Q2UxtJR*_#wdwZL|IbBwlkWv{uoF83_Edud%QLbrCxh&cy#L5``jZgS~2C`yQ@(+Cp*#D?ICZPR;aP|aI4Nh z$iYc|FehREO?;O4fJ3V&BvL3SDT#-7ibp$J<4G%U{s@W36UyPx$s=%gyA;=kmI09) z2X63FU1VSN`@8m!@sP@K9?z|%u;5!88RrzqhLBCRN-(; z88JSE7|_R=a(}Y;C2Br=xHyn|9_tA!2|?KZJY8!68lDzEb!KZp9w~ zWVfiBeSLkgPkVCxcfZr)-g}gE-g^WIs!3%4a@hu851zcIM%ujO zorsRIqm6h&}xN{S)<2cQ?(tj>D#z*qsk*+PX+( zMhP9ESaK0ZmECI^npD_bz@f8WillZyyx|n^N7V0bj*LKP#1wFmn4;wF4NjmP7}l6= zm6u-m20nLRz;>oanVLu^M1NX&N~y_#jiw{V!S7dLpNHP}$b{_-K_bF~oVGq4^^uG`u6hdV|3?+ds3^5t|2r=b-~is%#cnn#?rKdRDlY>ex`RJsjYD{YnP5{}K({AI z1mVTRau^AMV6p?2Moz6McWG=aB@K|{Dj?Y@DWm-#$Djw?nATSBpL7o>Ro3ZI!ISe! z_Vxib6poE?+olyH7!_ydZXQ+8$TsYIMiv@!sRlqpzh^O<5}VR->1<(_ZqTrrDuTlS}WkZaT< zB;Wme-M#z|Z&p8kDoer(QHa!mRf^p}=`R1~#TMCG8_;=D^f9~rDHCNJpQfjva3TWc#(XdD|e!y#@MP#7l z8qNQ+LV#Rrq)R`eTKh+@r_8nf1s$QfTGxde`&PG}w?&lx`TgcXod^=^uEl745a;&a zCn}8!iH*(uAP%3H^gZp=sbqhs(5mq8W(0+0*9?fZQ>ofHILLtHS@o^<m>GZ&_XIDFYLvEwRBfa$tE@)4BZ(jrQ)XvuM#O140gzJ>vBa_26{aSK zE<9uay6Q5L=JZtr9cuoI-=1l+Yvedu?(E3AMJHx|9+s-9V&l1wsW{+{unn=BNmMFXcAw0Yk1kizoqs7#vJ-HIeE3))t@r$^V5wJc&^n z8C%$wauZMkfEN*CK|6LJcG3)q-yWx@EG^A0T~F2G&;4(;5`>?8%ajfH_T!W1!~sF8 zj-1X^^~+vx$psvAJVsxKhDlm?`eNiI;6;k*U&PhCP|I5zAzmBjdi#^^+Qurc4dWJsq5@ds&f2Cz>@Ag z%*nCx4+wqfx;Oubr%3SN^UlU@P!*8e-iaOlK?epLUSG{!gTEtP5p+GU+i)@4_rf2s z_IO*O+;iIq?_760?@_tDE_jczj?J%QCFbm#X=w_RRFbCd?!=n6Y|pD)<|f9gx5i7& z{T`0Iy}PLeC9C*7EQpSm3)7ME?ubmt&%YVN__et6a*5fCUHR2*S%0Ib7bz+H@qdG^ zU09gjyeY{Lu=M@?r#{!X%8j}``}=oYzZR0acTJUwFFd&1{;V>2jQ%FkX>DO!zOX-7 zMhzAGqEGpobv@*=J?Z>EOYxtPt1Wj}O@98de&hL{VC+sMf>*@k^UKRlY&e)0IHO68 z2lf-4gcR`+Q$ctr2P`7~w#>-Kr=kc9!u!Nw67ynXycFkf{_j~)Q||Zmq2Jf54}y*k z(m%(J{Znc|U`#!eK0P5pomt^w%Gv3f3(a8lOC8tj3}Yk#>%y17%kZUSI!+N$QF6w$ z!%jJ}@$Z)Su0eet+PU0a_saUl0v-y%bJ;A``hM4DcXV)gBo(H9U0ifSoedR?Oj6kq zDCi8+uMB@&lL?T8OG)@#@3jil_*eu6vNm2FncMY~jdci906ccI9sO@E4ZJBmkaQI- z<{wH1UL4ObUs>$$Ue7Y0DzUO;Tpu-FmHAase%lD9LnXca7UHtZ9b|ZYWFD$lJo%M$ zJD&ihrpBY#)exXU;dbG*^CXdESQt4~y zq?l9%uPt$;h`ZatGF;)`_|aTLU;|XoFQ!?Zm)@TTO`7FZZCM@I8qwL9Z#4t_5>9#E z0+5|Us!CdFm0U5ea|;`L)jL7}w~Y z%$Z+q^z-N`9&bMQ@bH_NMrXM&e~D^=B;DUXS;y3}?yETtL#zGiG*`8AmzQe;IIpGs z^n`ufC{8cPgVx@F1R*cAP6`PIoO1k&t8EuC=xZW-J-C9Dua>)R+00B%D!-hq^AWaa zDjXlrl^l8WK*)_&8}6^762G-|L0!Ou#G~XhLLbXr58YU)s=S?=_A0F9!Ha22mtDS` zyPW11opM`db%jHp-=#}=pXDeyAp@=t_=E7th|INhZ-x?4-=_IH7IgWh#KkorAXIhv z{3rubF*&$A(OX#91oDQ~>0B~Br zKdF6|tmw&j(24SPjeIwfmc+>)af(QZh~TwgIvh*l%(PP=h1HZDl*WY8kuA8r{(IK1 zfT3rW^~ZQZhl8IOrl<3-j;n&OBeBBQs9_>IQTt1mL4Pu?uZFU|y1rBOpNDfodVzt0 zQL%ANmq=_!XGmm{;!&|#y;9p7jBo3kCyE6W@Z5C7&Db%bGG$3{e%)9I4H?Mp3>~+B>Th?Y_ z`?szVH{=PGVp&AKW*CFqd=*8F^6jX+g1HV_*aBVDyk0?V9CVJ!P6D;Ei{QbXfB@D0 ztj08@W$xNc zJ`V6g?N>HT@ksRe?t~K@>kcGnW zF*GYUBkIGwnN@Ox1rM!)Zi>$j(x zUo<^aaCtr!1Y=#;H!(0E>NsC`WBKZXdBca4goJ~+Yv<56^~v2T-4GLF9W@fm3a^<( zbUCEp{_VZ4ho>fHpkCVMzD1hDi1zmjv~`4KWbC1#X11DdF#21p8VNeS=e$AJKU7oZ z@e21-8x5inuU_Ytb?F!A5l#GhUrwj)4%&?gpDLDU`{((2Th;BR;H9pak&!ITY-v@- zk!EgzTLw>240O1~uk9wvId8M$Jbh@htZ4({Xc9=uc2=0Jt3(%`cu45vWGVrUPKX?s zvI(c~ASH4=Tr-S{zsEi_QQjK-n3OcuO*_uvc2UPGOI^^S!_(ICNn&Yp<#YG*HX!qbxfixCp?s%=V7{s-+W~ok~Hz<<|6eX z$t|IjZ#~`J3L?{x$Jj!VB8wUnn?dnF;7gR1=UcpyI$Y4@12~lyV@#=hevwLE8$ zGJyI96st2&x1aai!2$OzTR>(MZ4$??Y}dVJ&{aGgS@*xvoC2$ytmcys<{L!sNx6=k zwfjX>;2<{y@fNBTgwSeI_Mn(-e&fJ7H3!mZyu4l@Z@-Ls#U=dbnZ}idE*hmK$@si(RAvpt6fkU1!4C32vBlCSJGD~Ufufv`Yx?1h?667VB#K%aF z>_||UK3?`>vop3etxXBmX>VVVtO#vt5b3~pF7xDn3;t1vdlp1X^RC#q%9JEwEj+K3 z?+daa*Og$2%l|<}x>1DU`sP=i3^iSxCFW@`zBc4ZQbaOl3WMiTfspg#a2znT(ZQ?O z$PLo@-aBhj$;#Z4M<=&DC@#NJ-}*tEt3woYam*X8eONq3ozZS}ln91UYrS@{EAv0i z{mWVUI!bQ4FDwdCvVv3!fyc}J@89X_KxTFj4A>v^REMhIk)c0jotlq6U~%1*z4Y=9 z#h(I=g>gSRs#nZqmanoTL(#~kn8KUC`R}m*1%WQ|`0mGV{P5Ciz@VwE&hUB8U2gfQIMW7P_?z%>^9Hw>4lkUz z%fI$4Ol^u%Q&XE&D({6k58EPzhnY^-fEu^rcrR{Ojw?-0&Lnxc$bcV0YpzW0?Rmc1 z!`4`nm-XIp<1cxSBzG-7Z3i*Q0}&c=Lg`q1X+sZ>EpH|ry)qm)m1A2QezvPPCVWMIrI%^a5~^dO@Fhbs_4jf?G#}@hL@8g; zqgEbMDzWls_JmmV7#3)fE)GXh{npYHnFI*2jay`LH>gBWd1v@DB!j@vy?i{zgyb-~ zk@iXF_fq3#nvwE5+njew5HG_XF2#Me;gJ#cm%d6Q)M_QX^yhFL*v2LUNdTCKfEPQ+ z+#G_omzNdrmpV6%$tmLF6lmw^LSa~l^!Yk}!(CZcr`bB1c`*%^qp@;(Q8t_r)_f5n zjK$M7a^h$TZ!%>mxxWJHV=zq1T)6nh{13nI5hTlP+$1*|Hc!`;*?p85Pe^tWwx_Ju z* zWM*FDPg*TJK|ALmBQg{|Vm5muhjVU6cXj4;} zL>J8+Y>Nk2tv7iUv<3aFv?x7dyNJPz;lNcyOxm-N5#Te7kH;z6kfdPrpcNXPF3d?p2YNMoz5Yb+U_)P^RYD1d zfkMo$&-v3&+u~l+&gY@gU+1olU6#Y@tUCiKGB{+5?J&Un)*Z*HTDX71q?GM#ikmPq zDwuuFQ{WRGDwtsIv-+c*?3Q;)uMbmsrwT8mksJ+_?tdjcf5{Ipfn4L_b61*46SG^` znOGRuoosn^?86`K+yp)cd6QsnAoH;(o%xJ&=S%}ODiC;m;3*|&-2@d`|N+PPyOHw-1l17x~^|6;802+mdl!+Y3hGU zT7CDh8`4x*NKqo~j;2x*d$bVh#$Dlnk5N>-w;|X{1p48S>q{GAqy!}KZO@NE(Pc^w zDu`UrsY+0Xgf(YEzsv(S5v=NiRG_T&*(!6Gs2D6ed|HvJ1sXWQUd;K^wm+XAY z0^ugD%>fV$pd|_)+9{%_+iL-%vAYCLWs)bbyN1jqWHv?9>PwwVJ3CRQc489Jepf*A zwJ3tHR8r!^u`naXWeiWJz@MYW(HQPaNSgeE4b+zyAr>wPw1|rf35v>De0`1XjYW%< zJ~UwcO$&9S_w-}Eo1`gX9;{h~M0nDa`|6I+<@R6*FGS|{T1BI#nd%zXL3VL{J(k%t zI3*aho86+HNA*0C3rpY8>u)F@tAgt3-kI70^?EL&$T$bZG`)xzn zMqhsE)DLup zaFxq-@-)#8=O9MT5O{^4XBR}-y9msy*~3>BV9}BAo`GRa9nmgZ%d8G&>3pw_j(cJG zoq-eBz!I+QO9+w@Lw*Ar#U(>b zW{t;5;iwIP-~NzN5Q~deY+opElWq$*IS0+9n?J`R_IO55#BYCyb_&06=FRAr1em6z z*hhzyljUw~MgFRf#)0E&9yHL2QFl7X(fZbN1gqJ0q=*&T^P_@j^y5?>yxZkoqcQ|& zg`iUu6V``<#*|wfDPP@B>bklF78oLo9?(Iw#W7K1vrWSIn7$40wUubcmmhvt?aBC! zkfRS=7$y4ey}s2GEnMo}ggz!fU!PAE!k@o=PJsHgk58TGrW7TQd3SZ%3q2J3i?EWb z{VjUEyEEhCFxp;I<<{P-eLNx%cCvkM3)q-(Ljc$!L@3bh;vu4jNp*{6%bp0K+EK~trMCR$Kxr5Bov_ur7m%jf@-v`=rrU3Ek{_5&;;#Jb-Fla(?JyTD7C?`RPX_pUh zOOS_+piJUvt2+)r9gya}&^+k7)`4wYU8=`GKSz<=(X%E;>DYHDMySQ_YM8v84_E2) z0)%HMfCb&=n+pvWb?&RiJi*7P+>2^+PJM*xK|=R$OuqHIzLE>*nh9VIhO?nPI5b_| z_H^Vi*9UAFM?b33h9@T^p?_w3r{oCG-EoACggeg8+ZEgUVfhlq~Sz%*%0KiUx1VD>kO#1!HA#| zD9)pvC1!@qzb}#%l0>jKHa5(HEOCAp_qG}0CDPC&w{Gvpj+PT8pk+6ZEPuhcSI4&@ zE>5?p=ZJp-4id?GG>KMhkXC(P2m|_aA7Q4*1#treGlWeqS+>OfUX$N#hvAR|iV`0) z9~}{@zbf=V^96ForWn}X_hE4;2Jq|ocS7|`Z16Fl1I>|iQQnOlA+F;<6#GInvtc}y z<^E7e(;NUY^_CElWilem3h2g6QzqJq z0uPzAQ}(1x!{S_9lp$13Lg;E=^kcOiF$p3yk>w8b!Swi?n8)&s!E#}z7Ay>=;Ofyc z$9!4tW}j^<+0j*;0WAo8pGXDgWxF^l-OP02^}50?3Eh_$rb`g4%PrGT+*+5}2C~r5 z-=Es7+d@)xpd*Ok&{Jgvs8mzZAtZr3^!yknMz>8KoCbOG#t#SEE(R9Dki3%gbQ`|w zNmmENe#WLc?v}4zDWN;3Ixyr7qDd7iaJuQ4>s#o-bf9=1kALmB=UO!TvE;!L!!)0> z>pY7TOjTSUM{g#|=ngZeIZD~1Cd<1b`ZTcl?%dJ6y4<6w&3JzXsowT`kf6rZ(ZRc9 z?KpHl^6(nqT@X3AqZZ_{;M$2GUu^*GrLSHj14HI!ON)}fR!cloB3z~sWk7q-?l#-0 z-q6n`#w;q`z>lKkB4I#NY;09nbCKaE(W2MRMEHx}Gwyz?Wy3+>6*_(q3IqNC7~K2J zlTmYRbv5FSBS5;4YK-Q<+nBc%9kCQ=%k`8F9TvObbCJa1JpC@Q@pD)+Hm0omFJ>-c zbMSk?k|OxWj~~U_0MzMVdA3BA%_v&#GLjz?Wr)O1VAE3!Fzvub6hBu_IzIm$x|f_l z?*C2X=_>cz9t|-P%!cz^YWvfK7!lVl)34-c>*lgQ+t$&rdM>V~wl`3-#J|7c8S{z| zqV{e!kv*kuHQb=cQ>--?G+`^pgOEhNdWfNs_5)#C3}~8(T4O);DvK7@1bbUi`d;7% zKPF`>Yx<%30J+hd*@FsTH(Fbnb+QKy9dAXbhS$AWK->X`N?BQu%G<8#>BNfia_%w- zDl`kTTEs32>3s&;1S8yHh}=_GdO`;mIp*FzfFaz)!tnCKLRxwf9XSon1~60r*^#9v z0R~8Z#;;geTLFlcmwO-dLMmPK56_R;scC#D+>>d0${qqQo>3Gi!xp`N-ML6h)srw< zNMa@b#0MRkdcTde{cZtwS?{u9`uo9mwNz5up55anKzxhze7y$L891C`4PSkwhJ<>3j5S`fQn zHB+@==-A%lfhK^-`uPv41W{XdO_dAm!E7l==kV~0vf-X+eW;mZXXGZtWL#hCHqe%S zqxR@YI{Du6CuJv(7=?w$uDD;&+~szEj$n|oPw&Z&{;Cp{8)Mj%gqsy?s;uAEmO_lG zxZlp+InnidzhWZXSrJ{zB)QS6RF-PpuLlAg3G>epTE z%b30m^IX`chhHOJ1O^Vjcpc~Q(aaW0`6gUqCQgL9oiLJ8)WbjMg71JL{S{5uUF73B zSw`}7A1@+^j*vxNLnVp2`?^*(JSRY}S&xqNYm*>)T*DF%ME9MjBU2uBdf>z`fMj%h?)V zFfRKFg&ysvcPS8BJX1D&0!)JHz$Azj14LX{3_01BNHt(W1GFW;9f15t_oMf&s!QH} zbkZHa)sdCgU0%S%I5{~1l7ezQ#EHU&h63m;QG7LxjU|E{926xWZtYY@=Oe5M)`&F( zVtBO6vj{NK8af~2+!6a=s?zhzRs>dWT3VB-Hwy@65l$t@7$XW-a6VKIa!WS&oVlob zC)OBPoFVr9-O3QDA-fXA_lrP!sG1iXdew|u&M^)A%Or@v0G;x3|1bx}?pJ=5W`^U*Ci8Y76TVE)p)kT*lX2VvPldBzoX*Lb`-+l(N%#9%eZ90;~dkvFJvw zFhf!eUV<+mb1}`?3>(3=Bb|~A5)Bc)NV~UVMM(5#vR*w2bafGwN7?K z@ccam#ySPto-myMjhp-b$_oUCGg{bcX>03l7(j)bGhWoZW0ZXAYUaKlv_w%^HkJam zd`mEFW2MGchlo}XS2#}UqObH6hts1riiP2g1$Aq#gTR-$?=8=iMHtG`Oun%n<%#9} zctMlC1xfSuE$&Io+4zf0xw=|)vcR|x4$n7GM14fW#A+Q7FN6W-gWJN8%Q`17ND{oV zy3D!u3r;GDF;@6+4&BXpMrM(ATr*wa`~2sz^Iu3w&tEA;a#(vZNWs%wK>c`>*qOk# zr&{?OO%K1&Gm=8q-G0pf;VbZ0w{H+o-7LH{uI(9Y|9KGAhor4*8!k!y9;r`4s5LhF z2&gpZD{W*Edr@)HMQlK9{1#iO7no%@Bvy6U^vx|;bm{Fl!-JS?WN$7=T7Lx?sv(dm zroDU5meRH-Z27;noblyA%Sk`f^UF&LcVmA1YgYWl<@#e~W00z7{r*fcenOzAx_LS< ztlKUa3i!3!=l@5>pJan|#lQbRjCu0p(Ldo$lz-DS{>`WA`Wrp*KMC&tb8@q;(V6q^wW&7DakQ4l_T1S;^Pab9ZXEe}8{B=)|wUFD4O|_R#Ot zQ~MNXtI6d;eC=~o`2JLzI@5l=NHfVHaN(nO#)H9NJ|r-;?a>zI7+ni@;U;^ znZ%z-TqdhhfMJFyDzx?FLI1zYc=Q7S24a%t0x)7A=$@%}cJn!TpO7F(RW~DqN{Wp= zImwH{QfO-jaYKY9%plOj)mGFjDYw8nX1^UFcL!*KxjLGg!((Djm?Tv|+yZco4T%IR zgW#Qq?C8qMXj|qn6a51WNShI9*4+j1Un3Piu)GoNUx9NjYDwgkqy3|4H;PD6mv<0~xo~4tba9?uH%>+o}P$I|}A4RtlPz9;1E`9E0 zcL&+2-1khvi9q)vBoxhA59|gYf+km-$EfT0_}InS*%^tv@i*4(97ND835Wrg!mnSZ zS6AXHLAG3K396;Q)ODiAo%z z4D?rO5{?)V-<{rL33D>W#!HFCk!`Qm-}<qISRGYyYym~1LG?_fHT#R-mN}d*xbDN# znGeFGc`==4W@fQzYm!}1`B72NEHV404w^Sy=8moh%INxyfd zuMh2m9exO1$c4(sazfBVgoO7r`!zK+bF#DX>!BFHyc(IvHwQ|+e)Z}EtSRb`MMabw z&Au)-INO5%&^m^p`Y6o1dU{@!md4uU%KHC0-i(}?k%4Uhg9h;7Js~P^l+0)82kfRh9eIt2N#m07Bvk2HI#t{R5DU(F~kg!+D>` z?UmV+D5&h!a=(B29kxjklg)a^S2OiaMMC9^SmU)_ps3-#mQtn1l6$RA_;d3#~cm7Ac zIs9Ut_W;pSG%r4!FQ*=0-y3Fer4B&EP7&>33&liM)PQYCr4L1i)z~P;T>w7^2oDlqfh0z> zx1#}Rep{W6E*UIamz8UCisB+7S)G;sb?gA@^8n=p!v|0@C z=>||<{n~c)xjat<$&S4I2*BW{FcAznJbI-6&aQ-ByIyZ9O{%## zv70FoSj%*RW`dNFEYjqmD{4{9;m&L1e{)M!l~E0K%yCL;Dph3oFA3t~0AJAhb={kT3zRNR@XP~g2gL-M&w`(M@gF;GbkB2w2yZ;veR<=vU~ z_df&CX|wgtZ-J%yCe}kI$ob)#Gd%h+4E_9}`#wyBSDMDV(XN{@HvkZkQ182U8R&Ix z;A52$43mqA2z+Gg1E4p%LL}M`t^BT}gj$sdv#pOSlaW`=!rTK1x_55?)P|y>A_;#$ zmY8YubprNXO6tSvk9l<}zQ=d-p;MzGn(ecOAZ%yzOg@t+{@Ee6D&pSSMyg=85|YQ-M&AuKIO zamrlg=wFq^_XCd?{!rlc6%PuR-C(iGoC9QpU7njm(cNU1H6WTzvkQ*k@(|$#Q`g;) zIv5(r%1HaD2w*YL7;t(~a?}6^Jy>&8Y+)-pI&Y#NiO<`&r`}@09QvpD9e{^n7vEDw zfBY#kH2dA2SXD(uKu0(?c=I!#ABqjiMHnh>!PS#|&E7i{2UYg~X*fOP$!vq6m+>$p z;Kx_;<7Z}7UWD6pBeo8bUQ=;VnZSzj>2y`sTiXkWl7Srk>12 zzLVT0`nsUy_mgvW|)kG|TGT6f!0tBNK)+kREzVOq6AwlUB&d3BzgK=OW^R0m-M2i5KFJ|A+ za;er1hr<1&1h(tzPl~>zRs$orZK7;_@;w}4zFU%{tg>ohBbvqjt*vzWC~boE}f(%swW+#GnM4_%#XSEXgzD= z(?tx;HU{GyO?sQjRId5Ivhl1N1K3C#?nSrBs*cwUK*me+=x&VvfnAE#Tf7p0IA;F& zeUB>T>cr$^>|JYj@kKJTxrvFyq)&~xv@W#3onh+a#4u@MWc2e}ttr<-PQn|M zLPA2XN88`ocvDYIO=afiD~fj|vvPlG%75jFSlZkiMo#zgpg(*_cKxorA|OzyAM)^F zYMp5Y z5g-YFue{7{=KNksYZ}h%g%b{*z`Xi>jqor;>Y=U zs{m~5KRhD;^}VEaLF6cBr>oyLSRr$Vt|$io8!~?bw0hHz{(F|*1me@do8tcsSHBB} zCCRM+){DE01c*K2w{fA>5m<)VKou8?g}DATTcsMGQAtU6tF91FJXxxEC6y<+H!0Nd z-w)w}BB?G(AT9n!N#OTNyr4}VAMYK=s2&eGPik@dRbjl%Ca0M%Vq0;*A76hc7ysnw z->-b9-U0=-7vH}^E`z`R^LLm_Bb-;Cx?pCn@X?{y z!4i{kQ;&er>FIp)_1F9svu4`BB_$@o_$jnrzgyd&#V6mfmgY# zE~fF+i5HA?H;Sz6Ic44EM`L0(Oy9msuhbJ1D`u$p%6Rrn(6H3Z&}q3kPQ$#$W;%i4 z=(&d5n}&DUADvQHntUv8YM-yZiUPG-U4{`HVoW+&VmXsVk+;2Y2gdvMT#Y7`N^8&O zB7W&*KSoE^5~#gYo9OA$;j;enWUdk9{k``~Zqn$&=cRHIfLocf?@~`lKa_o57C>`* zm%=D6tP>LFop5_}#KHc@h{QiH_R$iAL`<10wg-ZF_DmJDdEDHu9z1xkD4BTN>P%L$ z?Y#?hWsGOL-ew_JvQ(knMjnPsEnVc4~*ggWv*v<}fNmtigQCCb1 zeUM5~hYdc#$BHL3hiKZCRxIZc5$A1Hup=iXBmlpndYjigi{aL-TZ01wuW^4LA3w>U zU`q!9mBoX+gyhW*gE#j@`xP6qvn^`xu*z!e?4-?@n43S#0E)_60e2hKLRi>aUXy>z z%RXWnBY{gInH_tO=tg{& zeq%!NH$#i+3@f2G&#iUlL0RyqEGz4JX%jX&VqV=q!j0ai;+Zq5W)b>#;VRG~B3${D zwX_7k>43CLo9ytC^{?i{Jw<+GOiXv4GVqG%6wUW&2AX;NW$irLRK{HHQz^O;)>_c z^Y5RY9?w5X;YEX@gF2jR^dQ>pg}F1l8o3bg)w8x<5CIS`to=7wzMY3ZzyImLn92K( zwp3JPqiF}ceK?4Z)m7oiNrhAoXmJq_{hY$*X74~4n3*M=SHsTtm)K@lR8_k}Lc$o& z5;q_qTrl2D?ditu@>uDhY9-_+eE}E;?#TR{>^s6B3Hkzi68z20-)0J1zk1Hod40Cd zcIT6i*)4%ee6nP;lkeA1_<9;S4eV_0mpWL<)#(Kv`ZcM6ok%3_F3 zKDl?e9X@gfFXmCR?Pn8vv+x>9GzgV_`t#zc16}ve>G#%I4E7-9C@RC{$qgNxk1#aO z(A7aN<9=DYB7|Fy(w$&NM@x%hErvXa1A2aTqy;lils!mjH8UR!`nBV))QPo~ojPV~ z^z8Wo{|VtcRBUB?yJT5wL3Zu^=g)Oj2eF=#(o&u2J8KW29!t;DPZ*i((qLH1QFzEjv0F4<{DNHegW1~1ig!Ux z5>#_L+kq6siQk`snj5#Jwh$4n6d$KajEnVnyf1ZoRxa(roT(SBLd;|(TahqyuH^DZx$d{dF+|?gU;D<7P{k`-VZ~qk~x}(2L zX^ua7@Xz_VI|HQZ>({T8YaoDZl4{MF8j|Q}MH6#$lgIH=|Y{-wY*FuWoV(4k)S5U>TF1+s8*VI2qBz2ux)i5PpF1<_4 z0%3gkZDFC!^*gO5HH3x6hfCrl_8q7Azh~2VE#w@Sa5+Z&deKImOZUMz5#rnxk-n(~%#^ZRNtwCA#E-lC(UvWSdsg`bLpCtjtU9Be` z9HnTjnm@B2&T4BZ8)jx^u(-hlMA(HLj`fZJT_EdECe%kKn|o$?Fz7l@JwGJ=<_b@cU4;5RoOfBM5r9Ln+X;`#aNK$F3dW_8V8} z0!xkTP?;52&#*8#b21TGwMpRqqG*DUFX7g-Dzet|Q!R)bYDKC;1-v!LHlFMn?1V0vP*xySeoo zp8h^+Y=XRK4M^91`ol?n{!YwSWY4eN(DE5ta(9MrBz?FDEMw?)e|=%$l8BJo%&M6I zXP6+vfW}ClP+RCV#d(qvI2Usz?#-~EK&ZMbF<%rn{Fsqsb13hR=Dh(7C46*jEVKXM z*DpMm6)}RAo;7k3iCdEGYmGMTYl@zpjKA3JdrlAl+0iU3FPE6-E4KfqiTff3JzuX8 zi;QrIQ(WRKyD4@U6_ar$|8I$=M-MvUZoKtTQSnw&`w>g!3d;QE?yf|>v{dE4y(BL3 z=r%8}_fhX}u6No8Ak-s?RgQu#lbj`ZOe-0LpZ~Mb0sfw&{Xai_`ia;-{Rx1X9a8`2 zhf3!B+qC^(G@l^8;{BKZ_m%&54>se~c7g6mSob-@tMmNIP+Y+b`@E&cFy7h@rEuPoYc?w_AGl2%>1kCVRvlE*hUH-G;8 z3AWeH&Q8iJ$J!9ikq?Xu?m@#OxLB=6r$1KyC@3Yky11xj87aBCzA>qMycx6WXRSnkN6|KMNz8HqUea!^e+jAO#qHfEgd}8d#`F5EZ<2>&i0!qp1C1l*7RJ zpFd#~)w>Vwx@9XFK9=1x$xRmi9V5V1@X4^>;Tqm!dah}p`dCNX&`X@0M1$l-&u{Cm zYL%fkO3Pop!huxl*auf`U?OquuiCJM6?qsLI-XC1eDc4`G8*&e_nvi2z{wzwP=+S` zU1B~R+2D6ECD9C4RjOANKZZW*)3nL7U9R!w$XPuJmKhcN72+&ik|U~ddvCiNp}Dj6gq5$s&$xnO>n=T&H($Z@C2j_`cOJ|bu!3_ ziyOY(^ZWf%jyIr>N|sWQxcqE}kLM`iz%KG?;`Sa{!3%B0wfA#`iBs>?M|7SWU)?2n zG8Qb`;E-i1nmGS>;X>*eO(MAFZFe`ka6%#7*4WVSs6MBrRrCAz?=CJ)^Yilul0%;% z$HGY;63B2Cmg`%4o`K)O0T(&>l;(|=`{dc&*Fgo(xuYD-%aWC1-Qihf0Rcm zi+XzN!{dab8ubCP`3+>*wDnq@()aN9qZ4_9XCK^%2HG(!EG%fa$Z-l?Zh@h(@r3D` zV{mmq;Gb;ZARLi?R6cb%{-53Yc&ST#-hsOH{qZ?z-kX-UZ--B@bvu|UFEqz{$0!1) zCJ2@H?$A^O>;?M9c$d5fArFmGqkhzL%Hzb znu}^exMK_dU0CgkDv(7)?5*+$^!qxZ6C$>LZRw#zYra ziYCn0zP)$vo~1>JUKnV_b3(kuEP_HpY$*lLfz|N>v@Pk* zU>v!xuMbMME}Nktn-m=W;{AIsQWj6iTOu;&rF~d$&ELn4Iu2TpGX{|OJZPfU;sfJb zfA0Rl${UUAqv74|?pH_yQ&Uroz6k=VQpPDU3mx5IL}kL5`UV(a(03XdDplj^PdH2F zS^}-p$0kk$M}P0!Mz9^o-PH}9oE4CJMqAwCUP$r^jD*U!^_-kGou^1icgP%Zk@em( zc`~sQ6)>3<$FY%-a#(oi>MWk{&B+zW<8_6{`ph;5`SP*pZY@uYO9Q{Vu^UWNm^d}l z1V%cbSPL&%CG6<)-a3H03*d0Lx3_nYF?DaFQj_R&V$8|m=bhH&&L2D}_OQCVJS-iy z_DMd&s*%pGUriYpgwq%(sSK~K{*{HXUO2Lve(gZNH<**rxi5 z$7d?QHvQa+sMN#PIR`;e9TgxfXymjV#8E7J;k=G@-#4CjYSzw!hn`m}- zM_sT=vEaRk97_Oe!LbG*Lb6ei;9pgyz=wH?bo@Z-$e?7ED0};XzW&*Te<>yU^5RzP z#ofDnWUM#rY=`r)EE{%8R8U~{aeW?5yrZKVTB>PuzTAyYOM@qB#eth?IOQZxzJSKI zKUY%H7my-|qrN_-vDf!>e_{m{U$nQAa}$Ck#|MYYf?mem@WygDln+37ZP)VBQeeg> zip!STQ^>r9bA7(;tvUD6>uu^7g&+`@o-8V^1GEJ^MF82HrXdoNU%ws(z4iCGA#?LV z>Ssitd;9chc5&I$qSA%Ro)Q7bix>hw`b;Y6_u$SBDg++({abwCmZqP8*6BVizLh8| z*wPZ*Z_(e+57Oe&_!K~GnGn0A?mm}vs-NlU0Sx1X%8G2Y;eSER8qW`}+GU{*q5rU}8-cCL0CD83nH& z;SqSrww9sSfM)~D+=F)K)sCBu8b>EB`1f%KDCZ&$PXgpLQ&yhh(zxJ+N@Zn&%*IcyU{?XeZ z|9T5P)kvzY zj>e=O#KSC$G2JXk(VV9Mg!!MleQ|tNo0iQS?%v^!^k7dxG2n%~sj7P7>|Fc@pQf#3 z3H~OyR>cWy)grofLk!?=)%hqSiijGO z+6jzmPV??OwH;JP^}w2x`Mw#RX6O{iPl16vq5}ct0hr6|j5qre%h`!fd^J+LgZ=#;*sU9=nKTVZV&{lt0;>Vyx(pv@5?p(U$jmfd6jL@&`|uQ!m>?F3 z^)N{;{HRr|=N#|vk;{zb;tE`FfGGNs9BP0CPf}kX#=ys9OIF_3^_+c?C&S|^Ol;|# zGD^cn6eO?^mso9?pT29n{p%z37r7F3I&=$V#gTv|ZC>gvGKZ!g3IfPDjm-SP-!2dm z+T?+YCj)K$#279(^f+vBeR_JDhK2@$%yni!3#n6M4RSDR3P8^Tq9iNd{ZVtU+^KAs z{~a-AK*vgY#eF+i_fP^1MFz{kuRx_&FQ-M*uvA z(;7h@ST8^jpxx{q?jLf^^Ke30SU_X|YzjHP?L}Kmmm_)GKt?kV(7K%0M()2lB8DnF zQQho+)&@+=N1+&$gGG-;+Qo*x7=rc|KYz%X7}5PZ?4m!F)=Y@#X4ol$OL74a^YNoU zBMt&2jj~Q$g3{;ab`40s5Nn8 zx8KSL8_G_GxIBDMnMn&TPblosu!CmOVq*Zz>o^?1cMsfi5d@^`YPiS?t1j)x%}oY7 z*-&Y5L}j-q=Evl^9aZ{^I^xZkL_Ky)pJ3c0kzzbVmpUF+EEN@Np_SH&?f4?`>21dRm#T&9T7+Mbmz8mZ@9&Aw6__*v{FNmi%bJW=)pKfdUyk|l zH+Xh}dmh~Urekwxpk$TB`5{XbGhkuV5u)oYc1@vmVz}qs@pNRYvU*i%$E#mbOG<7S zFTX4+EaZ@vzv@Y3LXMIh6PhK3Nj6ZTH)9l&zC0;*`8;YF@_gFDeDTv&=tXKtwD9Hj zTRf!R_pezIAC8??`|x(?+{I&PMbsDZn*pQ86Gh7b_N=(OJm(B+&v1bwE^d@ofjk`v zt!*zJDRXxNCs{D{H*H*&R&)H!zxXMX45~uQNhXs^Hk;BH(H$o z*QlsLF^p#+^6I^Epr%qkUD{(aGd31F{7elTi|P&AQ^l4R7J!m79>ii>kx@yxrGuG2 z6xYH>1CAnMPqYtm4hlV&`u!ThXg=6RUEOh68B_l#&;{}K&q+tF^h$u;so;!{hpw)6 z+2_5fvWL{;u817V>9EmzorIvqlG_3ulbjQ4vqX+mbG$-*x26U~PAVb9;sZww$PFdU(UN~IwRt*w(VtN>ZgFGTO|@lG zGlY+8GGpR#%bqcxvS1mnUSow^8?OU;Hz@wOx_33Y!hTPJpwUgX607l=!D!k4L&Zm9 z#}(toOU=#8swg^D?PyMJwd>EX%bGw~rU}j)ym^y4zlGHN3fwE#k%q$hTT=W90>;_k z$Ytd~2s{Lr<8mc4-!`ze7B<+geCq4_>*R!n@8PS_(NS^7Az*H| zK2H1ah)7OO!Rd@Gv}$B?CM=;}#g-ePno6sBf@}6qmmx0w=~Od`N&cfyrB18Za&TSub;P z;=7WPNbQ$@n>si+?5l%|pNvdRE4_k@?Ch37f{$_R)SCyO+?}9;;=1oz)Mt2aj=ox6 zw)5G-hiefZ^TO)(dcP$I&$Bn)X@249N+@>5nyE`dN_zJVbjFpG-{aE*KpV8Uzun3d zhQj;IW=p*qc?YkqwsP^5@>cQ{c8%mueTv>=52hxq*Kd0JwvI-MLS{Cbn*1v-({T=;6Du-{)elv$;rtOO z0=Fml?^HO4%Dta3&{qU;zy%c)3NmViY_dsJ%)k{Z8rs^`6%|GG-)ING-9H+Fe0&t# zi>C=Mx0 zkMtc$Ut$N8%{iTp1Du#o9-?}l?=D$7X%t>G<=;K@hNJ|5v+CfR#pzX!uf=v|*~`eQ z02J;pG@Oc(6&0n}L_?F_Gu(eVryYsv9v$@zFtD_-!B@Qm2Rt1%15;q{mreKk_m!M0 zGaMR|nLRpAcq-hVDv&kN=nv#b?X{~1yu@V~kD=5nr(90|Ee*O7+^glB*cZ@ja3)bJ z1E$%`dcl1o<$dM0IXj;yuNkd1xIbA|KhW2A=owK+wk}9HQOY4>yHZ@)il2uNA@v99<^H#z639xWIr8bzta4tYG|)H%5S-jhD*fry?f^;L@{M{`Sr6 zBE!Pc(gP+9+^2_;ugCWxiK&z8`GFE!5SLQWk4;(e7jHV+B2R-L z9LUT;T!5CzDUf=stwd=8_FikgWi;3H=TyMLRFRiuXJB?P+c@ zNbvU2(s#|jGkh@-#>vU)wN4)FXr$t3eHaUm;Kqb(2LytG+*MIDLLZ19A02%@An~93 z{ykRyb7yB!ak03V*igP)Jk}zLI`0hMbW?)>AHQA90P&4?{p@HR+;n|-cv#e6`*|Q! zIKtzAPF=(POhe_&#&x9T=TFyFMcn5~!b0jq;5Ix;R@S5~$T{*GiuwNfk00QcuGHMz zpz~v=PS+|zVqz7^i^Sw)bwd8mHE4R&3R6;?8Mw#WPeTKr5p@eKdKz!fJncH)e49P` z6Z-P^&+qp%HDMhq?r~8pcYJr2yW>4PJo->B`g`E&JrPFO@7uUD-}q4to?ik@X6{<9 zP15u7l7`?fD~a-z4AA^p4zCh~8wG_qg540py_Q&vEAlCdsU<%1}y>~`vw*$=we_j&Me zp7FcI=gRnyn#qFE6^xYK@%J)>t!Zd{J~u`%g6l-U2;WbgNcd9lr+bQVLVAxk;@jX5arxYP0+i$!|eJ!&M^HVA{%NUv_g-}Rd6q(dCgYV z&_L@*%B)3z_W030jnAHwpReOcQDfuaaMQqDh4z392M0%bY*9q0=2LC$!O!oX0LZXw zso4=Ft;L1&np+SPsSc`#rW)sC{XE5vE&>9OU)3Lax^Jtlj`z4QEhB?A&bv#O7-j?6{*AwiR<>+)lsygf}C_o z7zOdci5GyhTg49J&PZr0c~6upu}fuAaa*R@?w}(QHE#52KL0q>yUFgzJ6{u zQ!}UWF`1OQ#7wxJCJMLpk9^rYxfy4I0158K-VX{`-C+PdB=NJpiVF7C@H$;86EzpKg$mJK;IwF(1bU)s|S%IA%Z<-hV$ zeBU3X_5jOs1vC!f%H$a!p4pw4Eya?%blpR`yD*`TRsAFMY(L&UJL^q(x#BD@PcMQA z5N+VBYN?`6Ap81eD?i9?AG390vmg3#N!L;;+9*=qsW6!f582QS6m0gO*IzzEDJ1?y z8%UQR2mme9yeCkA0}i?B2Q%oM{?0Bb{3KTwhz2sz z$(Q6evlYY@e-f(iA7=Q|6f_xDmSns=0dHSZQ~Ul8n=m}C0b_{E_Jg#vvD1UlY_}Xs zA12|<9b$pXvMI{F@akwhBt19p9!2wM*|~qAH!CGXdt!w7{qfJ20YZ>~clWFwyRN)A ziZG@7*0tL(9zyPQF`y{ldRcU(*0Y!wjwG{pKwY_l2C&i&eek?7OMY1|>N6=6{%z#* z=ZMaB_k_+cXGGHb&Jlt|K}ANF!Iwz{|&D<(F=NlS~kkye!>&%wnbh>RqimFYIS?n4_Wx8D8w4jTx# zH5;!aI`tFKz!|h4%ph>-KgXM6XtTJys%$ zC=RlK;Ef$qno#sA^ELnxIRlcH{WwYIvj#<2tn@&U9FnIgcF3S8CCd(-o?PoZ^7|(# zTXsJ5`QpxEU8y7Y?r|D2{pfMii=$a_&0|BY{KP9}gd4#vr;!F6?kOvs3MjM^!YJf# zJePY|dT{ZbAM@Bldm9v$$=65EcYh9?qoOC=1S~A-U3gbBhp_-Er-btCti;_5oIuQG ztL^fiaWKKqVLzy?!igDhKy&5-#|joN{;BOxR6(j;UG3&-8KO8tm}YIh5U^x55&6&` z$&;}nwk@}3QuzGoYL?S~$`5}e)_6QMhC`aZSKtDJjabQMGi}~wrK=1H`fbG0oT750nzs-S{w{=$~}k`L8aFPpohiqu*`Yr z^_Y{4$Ka4XbC<>0v}y}sX^d4Ce`d>0!9!WHIH%0fEv?Yq(-ZC*5fR~W-r>RUnu>W& zwGWRU=OgF)iXi(w_92(W!>MVOhH4jdB=jjz#%=>igaU-crTwFczweDKK3qmf_1;f`s%^sHQTWj@xh~o=uv}2y za(143P&a3J^QJU!p%Xd1u2=~Ay_)<~qj)3$t) zsTCkA`FCj8g2=I3_pB@z+TS9LyxzP~>Wd9tK;I6tw|xcp&x$?YuUJ zD0?79Ql}`U#{_oVvBB7+t+%P&G1?qet^1{W^+ybGwPnyH<*=QF{cG7DK&BRo4PYLL zN5tMXHjAjB^N&8;w50XkeIS?$ERomPxgkd2E*B3?2q%`V$IbTe#@o1QvDD0;JjPo+ z*9h0zp6;<~KUrjE?<530OH=2jdRo;B{>X?MI>cB7P-Jc@Z?+x|2FW95ioGte#e#M-!_>G8)-}o#K$31h`UX*iV(0HJfpaxGBfEyy1l!B(wFK!glnzy z8IiZO7>ZsYv}BP^y8|OlY$rf=TNbOASM%$aFCB`+vF)xM=r3Qs6a~ep(iZt+^W!n_ z%gYntx8RmWphh6)y5CbEiN&-t5hNp$Msn50TNH?wWQ<_7sfj3HB8;*=#+ln zU}}=;ykv8D@sN+r?XhjnX8@QT<3lYNuw3Hy@0IYGz0$g?|DBsyt(S};R{DxJ^pA3e zaHMuxmoWV6O-%;J&!U>?hpPJTC&~%SA1~1(AA;qkJ`(tw)uPG!nMczacsSrn8eFFu`uS*((2$FbHbSH^E5D0aur=gT=2cpHI!WK_EHKqUos|1t~xMV_767H!1(2J6hk*VA1>80?O(C2Dis~Qs+qwMryj6vIzLYj&~ z$oJ9A`HJ7WECMQ=gMwr)S7_)-?9}qh%6PNickt`;Q98j0vOv*u%8xa0U1$|zeK9jS zN=Zu_RnNh}u^@zNv1Xlj)ckX5n;OdWR^ZOlXj462*zDY2x)DI651)BUtATr&mx>q_ zt~toG6%wVvkOSb8I1siV64-E@|1a&F>3tQBzwn{^5&*bxg*yLcg(Bo}0_8t2+!vV(^^S zuna?Qg0GqRt*?x*duSHm72=YKPSN>%2Njb}G%OS9Hdfp?y|6<8J5HgXsM4nfjcgz> zG+?d2{>>Xl7G}xlXmzV5>SmjccOYH){0v7;rRxdca35JVVtN)7{ugua{YZ8H{{bJ4 zO?LK{LZpmrjxEZLY>^zw}i;V1%JyUdS*?aH3-7nYmxjy5*zkk5pFI{zs zbKd9mdalQK0$yX@vt&BCxsHhOXvf1hfuv+W$HqwQ!OG4)2q?>UY^Sd%yRm&TL}CE0 z_&`hyJ)XtF#3aN$ZMwlHn1v-nT-;~%_B$ERxi(9M$ZBLvx3$UeUoaFHeS7R*$%NLq z3U5x-P|6oPFxbf)aYz$i4;|xx*1GPR64&Qp_Q#|Yytp$v52qb_xIp*Vb9Q!?o{VgL%lE2k z`t_IL&qA}6fRijJNOUj<$c0J<4c_qyBaL2k^~kDPEp~`!XJkE9Heeg;>wCpG0dqd8 z(~^?)x%fv^*sRdDUJB|3^!<(I8g zlb6%z&t|Et%RG(SX2$#ee*PmJu(AeiI;eQyvfb69BXIpXJb z4WVLMamCy1V0m)HMTTs>5s{EQZEf8xS64zsu$MqS0k98%%0e5h900oWBuunWXH!!p z2L}!us)#lz%f5`o?yX;dWIyk^JtgxB76IVD=S4x^tV-|^EmXgXifrFNqN^&N-{1T0 zH+{XFHZFjN$Qg-({^>I=k7j4QWebOk`AyLhL>QU?1}tmThh~$m-d?HG{QRDmfN9V{ zhxGGIB!|-P3;}6;^`*y`tE2my@tx1GSqgGe=e#gFJFIx(1*(o|$e7Oy#H0}nI*NjK z=cwReybzjjx&2~*)F4xVoULI52mu8VDqIkaV#BZu*%?c9^-%eoArQab%kE@5l2Jt~ z@LXaQknmf*BF++4Vfq3a1)tWfE=axiDW@7(p7@i0kIu=*rxn0NaSE0T*qc3{9;vea z76Dydn$Rp33wG)6L_VP!d@4D70bUvjzX!YDUK4v9(%?>Cwhi?ePJ;``eAhSWEr9B5$XI z*1FN=@8;AK(L2f?7k+*14Q5!o;8^ReFT4Htv05Vk*#}fN_H)8~d|{rsblKY`H;?Zz zmZw-(9M#I?2xsKv*O%8XT%!uYeh(iV`0N!!j;a#T###WFL}3nb2D}$;FsGIkm5aly z7QVBM6S5jm!9U7Ro&nL~c zhb5TaUa8E;(1@Sz?VSbFC9Q~;o$s7ImMj_AVPpl=-JS=PrjuGfVrFVM8I=JO31CQoM!+Q z6`ubCY}LNPyOMYEyq{;JO=klZ%iMf(K&M*J(muoogu{NRYykSs&G%>DM_~~W*{KWc zXz_8utjJkWLqlxxh_4tcO-<1U2L#``|D0->n^*AimAbgNWU_Ms#hlj-t$d3WinSRA zxy562QJ0&m`ua76uLJqfB@k5^VESL}27x7xuMm|u4miOz=1K(oP=2ozum5?2E8o9+ zFFt)Z8B9sx>NDSA6Guwxb&rDs6CY7B?Z^22atrY57ZL$s+gwBJQA%vAGUV1uct}XP ztlB(+00qX-E1R1DlF0hnH45g5L+gigIWowHk10u-E?f} zd=mTG*^TySla|2vTWOM%Dv}oKuMZW%-!O%NVw$XcoEp*%^9mUYf}%fY^iGuf2{xtE zP~jo#>n|;-10$vhu_z2XDsFN1cbyX|2;YWfJ~y??$<9`goBSl?uog^oEhJ=}BWvIY z?EV4)7nWPo6iJQzGe5zKvEmTqY{nAlU&)?~jsn*na|C3`ixFe&?MW}i9qb)o2h_d< ze9fUjJ9nQPAKexbrWf|;H!R+6LMH{PO|W6o-x(K|Xh)fVC~B~a9OvWVKEAVqu%Q80 zy%rk4wK4hukAhyzePi$oUqr++pp`YQb;eZjCeMEMS;&E==@>{0fDAjp)TQ>Q#wo#M z{Oi||Q92kw7MAY&@p(`%Mm)_vVYmVq@)?eFduN%2cxnovg~hVF7dAW`a`uZ_mA~W9 zDfw7HempA^M5nr@hK+X*i;Cu!ydgl9z(_TC9Xq-f2k)L4zrEh^E-q}7oh%a=rfHaC zSr-jezI^(S*Tv=V(W9#9ko&isv7gh4x{|UI@M@#+V|~xd!$>xXexwA?m2aR!|H=w| zhglc!-W0)L=0H&X?~{}KuV}Fd2xNipj55uU3*Zgi$it$Rdkse$ui3c)!-DPc5n=S$ z$T171U;vY9ioMqXyD$gG^9f083?L?YrlJCU6;R3HaCMPQLh?v4OLS9A3`>TjX%VEY zna6PfyNSGVoJSzF`?ssB1CxDm-rvnH`FvZ-Lm$FvVNup3Bz?*sM>SZKVEY=Hj8MGm z6SG@v=&n-x<<@3qZtL19>=+lDOGi9(R#|lfL|}gf`=dvg&oUAx0flLC{^EwHVIo)D z+}2G(d>TL1aLGe1cPyonD$+SENo*4q*}!pkRkH95hd0y1YS{XHRAUtg|BHGM{s*t^ z`#ya9xV7vSYU?-HRdp`|ZPXs5JoZEe`j8ZUfk^AoP&mULs+}M_ECRs1-$YATVN-3F z-RftAuYuj2890oQ{;$g#S4hzRB686|dxpETxY2Q8zl18Nmze{$8YEuLWW974VLEp*s`sqNDLlmm(GNtqWPP*S&{W-gKM9%# zR=iY{y|1H+01?CB=G#O${X;f*(GI&_OF0hfv)XTHE^?^2p`2!}|LdLn#o4evs=mRd z=~`aeMu095j5x6OaL|(ee%qDona>a2SyY~W2RZ`J3>?4{FQkB$*T{haTQV>J^kh(v zK#2Ga9jEOk9W6Q`<9mC0_IG0#0)H{ou(D)4w^N~B{?~IX{Px}-aMG_~uMw5@;DE}V zIzj4zOfN(3XT-ptX^{Bh!H^ad0Z!nl|JmU2{I7_I3+%og8`n`RZZitmP5H53EshBd`<@AX@#RYImO{kx)^Y0<9BBAJ%Ud zPxrBnbHT1gTTj8yCCTG80#=V}>e8aZzf0M5jh9(Se)RF-=}oDDy*ghn4nV5%@J#EL zVUej*z5&#s$8RXN&pO6H0*MZJ9hMM|q~oXJmgSxk7z6O}B?utkYUB;}IS6uQAN(n! z^zu5-ECS@h_hS*4os3ow4DmXa>fDHIZ-{@GV}FFfWyHs=sdeAoj+1bh)3R9B>ui;TYWl1L*8mNqn2*R`6OpD1$`a!bk^i7fQd4N_97@kT% zXM|BX+!b4Qg7!eaQbU&qa@K+=sfT4XJUB?|R%BR*o9!PT)7aRU_WI>FJZh8{c@XEy z^U<=`+z?r?OP$dgor>*y<+pD#EFz{>b$W3(N~u>c#&7s))rE!P+0Y7HBmj=CS2|-q-$mizo_%CMPQ^-OXu<>n?)A9q*{U#_|X0IFNwi z;l0;7LsKN^0s&EoQ?<3W#>1_7PXM|YO!If|-i0me zA;Q&tEiF&8m79V3m-0D+qu4mAqZ06;*~vn-7o4jrTuLqhOphL8Zf-sV#9CS;c{GWZ zG*hGJ$BgZFyR=`t0N^JrP?L_P4D0FkG*yDmO22BW<)wnPIUV#8@Ilp_U0uQ27TT=H zetzD|d5gD~(mmjKD=H}sDGuz%h!}cl4Mu?LuaYA4Ot)ITfuaSH5ipvSpRZ@Y@FL`Y zp3r}Xy5|sjMn9s1oKsR*07+eKZEtE_$?J#%M5TW^ga+&c+&v<6zYv-n7|?mXO^F8P zQcgWR+(_8VK{*fLgik`@N>7!Vn24z{*!3MJ5;TfmhAPwX6~9$Yj}8rOZuv6cM@H6R zW1*deIJ$ztxysiUYQu7xdz|N|n1BMgJ?_>u>?(lcONEe+K>B@4Uj;Oy;-?Rp0E|}M znKay$x8u<+q$wgn@Dm1M6K}T-?V5ojhqF(A{=2+{_;%db+`6iWjC|D-_r| zQJP1!Qe%O4kDigmhYF0X8Uy~F8q4LVf!lJw(kvNp^~HQoA_!!XQ&U&M!ZmRqO4`ow zfz5GQUVwG!iy*HoIG{xH1jR1kcFY|K)f(Fa4ky19AvB~J$)paLTQiDE7(S-^Ao3c2 zr^5K2Ba0o}0~(s~(a~9Fj;&Tu(Ii4d#4rDV29aHT(A*lfdAi^KsR_`bTOs^Sls05C zB($`-=x`eTe4K#k;T$L|GYIf@DGfUsn%KI(dt6H;J5a+ysa`Fl3EFWu`c8P$6yZhE zivqX`Qv(q!Pk0V8oAXUF|40n=x$>1s-Ac_ndlvE11(x{eK9MCB{0MAbMDsLYp8OPY z6N&+QQcXjnA7HJ0t$4QCpPn-NRO}J2ZCew0b(mygx+MgZN0B#<;12``bUOlV@anCsK z<=)8(D?$J7X!cDC#OdzN^wbC8q+0QB7N`vz%;?zFCUyiZdQHiB<$ND7unz#`pY0)8 zqSV?*kz97JBq%s7&CC=+fo32gG*r&i-8~TA1g1gFIis#Xy1To3%)Sq7Bh&=CWw8Nk zki$rh6+0U!`K3JpQ>dDe)$Mi#_(npqti6!7M(&7$e~trib+Uo(zpOprK?xvT0{|NHhHoa};I zvAVWa2}~@$zxn#zDuHY=MbM+v1q@ukA?xtq=j~c^-UI<&z^I*}<|gJ56FU9OFh%;Q z|B_Fu(T|E+ZBNa3LcDW!;e%^Vh4eFslKH1p=?n$UZOR zkx{4)N>)GZgE|^~vtf0U89PRy&M9M8&#dZv8%{KuJ$YKNbs;}rk$U{VD)lu@F8+FN z(Q5A#YDfL-igAHW9YW=!>AqUGe1~_g+uUbARj!vLO(tXPS7QkzA`A7emAwa3OZq%6 zPwlWejn%4MNA6gT(~}+edmT!hSNJ_s|A-VdQ?)^Pe6^Z9n(ltidMxzs&X(ccRK?FH z-`^_A*kiGJ@`3?rpZbn&P(-K=`XZ3dgT?`kjAx}dtwqfQCW~um`6!j> zZQr}zV4YfHKaGdldkw zx06@M!pIRBxy>}vn^lmC>tDzVw7zx5xhut~Fx+=lt4-6c#+}V;MRZ#>Bd(J5nUgj{ zt{0M%s&;PXQzJE3%p<;}i`UBIUb*NNmNoky1&1p|uKGPXi$(7Rtzp94%-h^7*j(8Z zAYow5j_XM53-VD{=k)UD(#W_M(Uy5#1F6#?+J|x9<$3a+%1mj>tkOct2aD?{u@#u$ ze#`Yg18zm5=`9NjY1*>?l64c=!h%%v;qw>s?Q-VPAf`A6gdfnBj|-#{$v88tuj0wN zISSKoC~11o{k!A*S4+oCw{#N`_3LhHS)J!iRa>VnnRy=IbF+P}(Qg#aLN8dE-+|B{ z%hMi~vT3+BoD-TMSe5sSJ$~1wwO4rA*-UcEaX7c731^w2GO(o+ zrKaBbthg7O88Ga9f?TJaQ#(Z#6mZ2WvQG*cH)PcaJ2pccv9YWAon5pw+*CLrwR{{Y zOfQtM2kyU4!h~f8Xv~V<%P6Z}Ky4+4H<-1dtRW&WUAGPfcA|#P86WO`tpd23(eHw!Iwr_ivRTRmono(THvl*B@7^>LU&YK)D{3kLM>Fv;{Ov) zR&v>{r#MCjcN@|#={NTCR$Ygg9zl_AK|1k|Z>gw*QU$p@llyGJph^mMk<#pkkSj4M zn7_tD3^OE+C%RYM7syu~$)7w0w6M{!vqyme5E_J4mzPq|!C)LQOcO`pxIlJiWf@Z2 zW6lv0t8qu=@C6Y9EA%SaXJl+@oR6TX@Gd&ri1w1Vm^}47`oY`nZ#ZER5etfzg zQxEXS4TmpCQSzE5y06aLNdEr9sNQ_0!3X9EWOL#;=hv;%tBT10t2A){uUSm7Ms9 zhD(j}{H(GkBW4$eCH#Ca{c3g9`)Gk{ML*L5cB|tuJiMAu%7XCO6P6|AE&+Ype(zMzAeVSyO2)VI2 z2(<{tfO}(ncWpcMXZ5P9ivV$_wngnk!)?t?ecl8IoA(u)f2e52Z|bQWv)120gR?MX zJQ3iTeOE4Z)$;2{2_s?aJWlZMmnDX=uY!&aDl1HEboMHGvv!7~N(%PR$f!}I=x~nu zTAadoJr-y=xsApFUi75H{P%R0>uIVFFVScWJM_re4Gk{@?SK44zLuQC;N>s-k`_N4-J5wzo!6)8fq zM{CbrZEWcAFcLIlfiod!9H;8NLY4!oYd^Q&ZcpU<41dVVQV4?_{=cJ=q=8a z2=gE4+1r0Aec+4&=%^B)0fj-}i|H8V=5Gv1n0L+1n5Bk3*ZKdyS+b^Gn z%MPIBYo??U#Y`9RP09DGH<|z(O_3Hv~2zw6wG`D1ng^X8YP9 zsHMD5@oK}zVz90C3=LyJcaHiE(9!}NB$yZ22f>2OkZ?#}1u)tQ48)#sd{yluYQ#F= z1op;uwEg@^X`@*$MN9_(Y5h2`?V=_;oU%*U^231!)hy`utSW2(N1^&e%1@mz+st}@ zZ%_Sh2arKfmP8uv0}))IoE&Hu$_@1NA`OvT19bnD-eTPEK*XipvSnQ*@YX$jt5~O| z-8ZAmJ(GeR&UC0LsSH(Z`|lh-WC;GR5wAH;=lk1MfK0Gs_NVe$?K69K1XeuhY6}>R zWKiZH;-lzApM(O+J=(0gsh?lthrS=M-w8Zra1Q_+FiKoN;g7N4Y8<{TEcpun41@;& zl^pP!iu(kHV?BIqfvkM{@rWg${Yz!f%PV)5(@D`^2ZzWK)f1~Khly$DDs!EtjR_tI4 z7Q4?=e}UQh_Sp*NObZ0w_v~ISE6khg0`T6QUxFvQr#(z1m}NZ*w(mT{{?HMRRb&(W z5|~~ApS4lVj!eP7S`9E7FWjbpUiw{5YhN#4Uo^Hf()B*dnYG)wF8d{;`?Wh%pOO|j z!49&z<#>8c$Ljn5X;5A9V-+1?*W|+8&u5=Ibox%tg@N_r&A8r1{Vu}x&6}KL9OL@# zoF7^}36LAwGRT;J{s;qaLL~^M_jI+xI5e-u}TZQ!&m_T7v+PK&|j~@{Xlbhc+eamOKxRWrjdwNfyC&B zASgsb2oO0ADE4=g0DSrSG`R`+20*MJUO|<=8q`q8s+=DbHxh15`|$(lc<7GP4J>lg z#5Cv=@Hfew?%w<4|JpCP(;G|g@Hu}wpr76R&znSQP1nLKCI)Mby{8Wqm$C+z7|enc zg*^{stqLfJ33x@lhMn9IH?Dcsxk~(4aN<*NEkSI=vjcn+K6HeVKrfwRA<>HE^M?gr$e z>OBHNLj6Wx{0Dl#w1j zS7WcM_R7vq7ci45zZkbG1Mvur82H3yh{`_Q2e5dk0m$~`X!CP=;&Ng&;^g3{myEhzW^aC&-+}*@%@9zZl?W*%8_>@|; zP0Zg+wS{WNC_-*2wl89s1H%L)8pg&{0Aq0l|j+B%O;a;T90Pg3U}XIw&C?z!VKgFyb(ifEm!6o9P#zb|sSuar;n=Bpew*Y0<9U)v)J)m)Wyml!OWk2WRwc{OXci zcFbshzvo=wc)Cn4K!Cx7$8sSV2NTS=EDe$OcxR;14Rffi5Tb-a)uc^Gw!1kqB{C4e zWzyHw410WXYA8L#j{xQi;Ix7=g{leA`uic>p@v;im4@{+XnPd<6FUIn+TEA(0(fOC z(A})#4UzEyc14xUH*nMkaMM1vmiyVKQqr)SnS+L!0V_fz)|`klX{nfT`JbR#q0h*a|^cWz{q?<{QHZF4Ygl({ zSmSV8a_+`BSl-Dw0uDh7OH1ioJ>LImv_&1(B-clIu|N4eP`WMD0p#2Dyn0>aKIa_)+ zAfE*vdnGd22&w<+^X*9zhuYk4Nv01mV8?H0>-z1Q#c#!fuKW)9M@Cs2_FovTRoELX z(qI&{iDtzC{QYI5?)LDntNd}TufA8$EGC@s+*gGUF<#APw({RUz6WAsd(+B+-vDY{ zeri1nDI}PU)-amji(Bl+$H#;zPk1}O1nIBDwN4%rB~lfyIG8%kUQcg7eoYKh-j))( zD_*9$T=T>;iV1qKe0j^b9S|dL{A5TvVP)JC!0u)F_w{iQ&xX3-KONG)eh{}U%V4S# z%6MYnaN+g%tOw}P3L_g=S`BN{ra;NMRlWM>@WR$>$A3#Fv>(4p5_6?!Ft69k{|v?2 zPuo~^MTzEIx9!?GesB~WaFQol{}#=Y%CA)?=5LV7`bg-1f8YghuJq&+Av-jpP1qF84t8<}kdv({mIg`$=OsIPtTbkIqlX!r-? z2W{r%1o)%!(FxjLIT!eC0DQ&~IQ8l2jFbUsU27{Va78r&PP!MT*OFcq=-Ta$xtFJ} zd376p-ATL?`-C_42iFhqpRevt|9Uo8Vozpgi_I*Yk6DMaz1`~TJ4tfSV zUdVeU92}N&mOSJ}SH@ee()Zm%S5s>(rJGCcQbM1d#1H+Zf^$_}T%Nle3QsmZm@4|b z2s%3oif^8Wo*!+-`1y>d5uky4GEH9(tp2i6L~d8Q@8W%gTP)ijS-%3*R!~MO8&uhn zbra#@%DHg$wV3L{;Z&S*y$FQK(cKts{Ys!d^YZk(Ki$=H=nw)e7po4E89*bSf%IhG zUL}G#5tZizcp+VsR8+uMdG-(RU0y^^*Sh2u6*XjJtbs)sF)@@o1-hlLvX#7F8Ub}} z36+P4sOV~PIXztpFn07G15zN5qYY|e>d;^!FJSic)+aOL!Qp{eW;Ma5qGG?9Enkcm z;VJvev9e5}4G@qSutb14PNv_AGImTZpq4IXWt%hk4Cdi>KX&pNYDd#!phF7KXJDUY zR@mFGmL6au5AjyZNhhF%n&>b|-wE)xvq*yz`+9+FvhO)2W)co$_ck_ zb!MjiGDou|B$Nokr2Bet@%GavA$C?)`~=$gmF|_bHDL9MCBj$S{#m>TY#jz0!n_XP zWJw{If`Y2G9%l3NfYx&dJ<@H%K8N~O4<$Yetgf1_X^H<{kN3q1?yy!-lsp}Bu~{6I zM7ZU@)c+AYi5l>7z+Z@D`$L@F+>TcVmH~COQjQm=@86Dv12bmXp;m41?tQ_g7& zs{~{Vh;E}FX_S^ZX=)BwTW^%$tr8&7{y39ifl9{nF+ac3{SUPTH4-!qh>zG+_HdDE z>?CFVen!L+1N<5GF>E~!3mw?uwD-rDux36v@!DHR1W&C$E-z2{$&(*1LLwu9!wbo? zU)|kOpZhYOspSL(u|4DB`u+@!W|W?SLW)f4$6Fi}0H3#4S06n}d{7v&K2L@X_pnC{ zJKGZ-V1LY>pEdg-(CsW9cLgaoVoue5dvh3}XmI`Uo*6yAYb4-%10gXDV_Ha?W^T(H ztMw9Lut1}gRlz$N^h*W?-Xl}K!C^nq4Dw45ZF_s~fBm{y7y_h5^9fWmo)n>ggSWBj zu{2LMv+=#Lyxf2o?QB3b!qE{}72kJo2F%UvW`!skiU;Kym5J*G4+v3vGk?EzBE#SZ zlV`K4zVe4<#upu{rCpyIyUS0j=MWhXN>J*$TpuuA3$(uZxjX1-{&MRTBWVQCxFX+!r3~4cOAbCy=OElfTmFANT+||k%l_}Hjo${XWkj+IwJ9p+_08^z zi4kvBAU4Ymge&2-Ou0ymhX-vQ1@V8JjnAMc@VZx#3~&kb!e#X5`g%n0N;4kNB! zg|BYQQ*n=ZN5}Jdj8a~eCC=KZ1juhcc>InPYEK)leKBBv?xoMEcJRTL zd+%vdjMrTs9{bLC)O4M{IX(6}7~odmd0}&W_J_xp-oD9^q~Z# zXk*RGq!h4a#!{u`+>fTO_ZzQ!qI~DbKOv&Lq&54ruH!_MJ6juR zU*0KLgoZ%*qh|3yw3_R8x;Zh&Fe?yJJXbOx^@GjOJGHOvQ0ZYo{Fh**4W?B>lkwG7 z)b#mmRHttP`9yf!>c?c?i>PZn)2q$2j*ErmMjY@;O#10`UD%gJr?2$~F$+cQ*Wlh9 z&#+;d${oEkZQEBf3S5n$r}?{1+Ni~}>v6m6tBthlbGs2nf=kBMQ0?*hR~6on|0KGa z>H~wDr^Zcp6I2;$Ur`X|Twlzun2$%I%&B3}(l2Z@Ct=o_3D&aRBaOSyrrVV6*dB>o z+af;d34Nl1WnMI%j3tw-NQNg$Dm*t;vg{m74=pkvCri7^!DuA77tk13M{qOAf6K&=GT{BzFE0Hen=yG9}^zE zb?m$22KiI}a<%blp-i`+(xWrM=Q4R(ujYL82vL1=6{fEamZi4wQK)Mw6}m@PPUN-~ zlk3He#{n`4w)CO(=aY;VI08j~XfZ@`oz%SyYA=`lb}LjnK5;6aLux;0b4j{y-#%Gl zZ&cYvCHUTsr(uDu-|n|$1Mxph`S(o{zKI1WdLn*B#l#bavmI8Hk&Y6<-6YH@cXnk- zQZFL%bH+v;>SXRT>z4qoRZ#h?-1$yt^XM9UbS9hp%A(hCwM>1P7s;vwe#g0wv_&I* zUyBf7vY3CXulxEUj?bZ?g6olDN|4!g4Oi_(vX;QhEhX}+#>{)$A~CWBne!;rU_0%G zSnKK@kMDVCg)*|VoCrBf;LEL z!43xz=T4~j3j&RMged4>bC=laK|iAr_<%iwob_=3-{&2q&^bttSvAOI|D3n~BZ(Ur zc>a}cCd`r=u$N){+RGvZ2&B*+5 zmj>4cH;(F;{;H?F`xV=T-@A`2pvaGZf1X$QivQl}4(QjP4>|+VCq-}h=ZA;*2HB_K8KR36wzJ5-B%MuQ+cHN}mWxB`o zDcjB28F0Jr+_?img7sNp@84@^YVLl^%EB-y+)(}BOOnL^Cqx-AYJf9;>5iPHMIK)i z+e_y1Eb8V)`zVbb90!Ib=TCKieejMD)im&thWYrb+J_5m&l9X>w|6`3_?9#!LTqf9 zGhx2#oAE@k0nR{#6VRFfSa`9qtq>aeR-2R z#SQhg^C8wh_YS;soN=k_RvLTZw6vFI%(MKC}C3%$+7ag4he#5`+Y5hMT|DQWINz{Lf66Pj= zuXBW_f2CgS@RbMCrGDe~XGymC0de}4u+LR={RBvLd~N36`&(6c$G2dOEJXw#(v?r< zPW7h!ifOsR-g3n;kE%(Kk_*rofzhju31d*JW#@o*XOP6^vYr7CAza!p?!zm z=#gDZq4EMNuNyxe?pDjzHRy5B>yDRzq?it{Xnd) zU|31L<}eUv&%(x4xEl(&v{*oE{u#;HKgw92_FIE` zu3?{-*C{$_aKg69hpz;r7Boc{0W3D&H&qG`&4%HRJ3_jPRu_$1_2#~wGzza|)M=1>}1K6Q)aNq_b zJTfiqiJT>A>>inZ7(!*!Sls1F3{yUC14-EtzjM*B#leXgo{n-%3-1wIC++=%*SUnV zJRBoM;^M&LPtcF?fC;aZSXu{f7dvoFdXK2vUqOW`adP$LH?dT?C#Cky>g=kqxn=M# zw@JmjFmqT88`d`AK+p|-adHBd{mVv5s57v9R(5cBR648oKp&WPfG$(qAR6e1fb*06 zH(;~=aVe&QSR9qM#ien#yA3U=z!=n61&1&qS%wa2FV;VS=;f`F_zA8!f)_u25CbSy zW)AwLaZ-m%MeY3R&c-Dxv!ztvSh@zyu^yl;I~|L0H&0MpfS)_V4T%hC3UyyG05f4CFD*41=F(kF?MB zZCRcmlIn?5BWTp9#J@dHhD**0v!40(WDbeIkBZ zsDUuL^27OFbVAcNwjCYUQ7ZU2D#1AV<*G%ho$u_6^|LQC;uYJhm~f`U08t-~-?f2p znOS)S*gq8TP$w_k(|MrXTy-k>ndDbSkO)PJH2hbroj`7YhNr3Y5uJbQsl8q+Ziz9X zV-mkxU4;fz6H1mONHF-`SX=vuc7wM_od5dd!~c+qmW)i$Cg~`+N=8~5zz~^FEu>jN z$E(Ex>+I+N{)im=u>B=&-O68{6V*SupJ&QH`y@PYF`)W{**P(P`WNRnrxy%eg9lE! zSY)xQJcnpl_}M}MlEt84z~1<^t5R+apu5X`B*svHxwoz5Hy zI}UIL4ZzSyP=q9D<;Bw%$MsieW2=%szW#pkpixRisZx?@9^D!v2`k_0@WaVx|1zQR zY8qlezFUxkqU*a7#7B87dvQ591&wSeb=U%4z^l>3}-acI8g7)Z=7uyWmUR?p!R5UhIGZ&>y^fD|xSjMR*b{tOSl z%dlUzpOekwf|k&VioOmHRm!sWCx{h)yJOh?uE|!{myZvBRlUKZEIJ386h)6O>t*kd zD|ipk3bN$X#Ytq?NRLuQ+Y1X-!M2eYkMT;wQqFf7h5D&rn_ayqEjxp_CGQbN-y_QM80tWwoh?$nD#^{AFSL64UeJSCw|7;L zg9SF99}tFjHK)N`$MD_zw6v&*5SbDmAJhmUF)PSH%|W2-lJ>O3mI0Olv?F({+evi^ zhM_%ZNmkW2RroNpaIo)-v<|+%R?6Jt%W_7<)PAG%;d(Gm4Bu3IlkGx|ARDNaww7Z? zZi!sJyC@^PU3j&m52;^{6=Wn~TE&)Y$+yGtE$dQ9x#MGjcXWMl7m9AdJt)0g>1B)n zit;9L$wOzE-A_S&nMX2zg1=UGtrz}Me9-GGUD;79B&>8FXV z;#Pr)QF^(25Ra&cygs@cz=VEKyG_DEImL+l5*E!^5TMr z(98_%wulY?00y!glW1@x*rOd55n%{sOcOO>a26<>ho{l&SZOEueP}4HcoNf6hMYEV zFm3cG+i43$sb}70YVYku`_t0WVmG0v6Z#1h(H((-R$XM|&L5Jfnd~1H`74U~USNzm zFFkdN3su%vQJDhl2dxYN^pZ#durTu1V;Gv}AKvx-Wgd-$p!dYry8Kkm_|ffx6g^ND z)g=B*aGKt{nQEL)^}%oz72VGLDK8(Z_BMI^Wx6CnJM@b98zYz0+Gt%UnFSNch2aZ# zeeIthZ12#|_$*p1$L)nm2xjD2 z^xjShxuf_51sS%5;hwWZ$KuBgsen-qR zB_(;&R|`QuVlDb*2~kOSr?}2kXtg^TGbhS>bRzXa%y0I7zAHrljreHaM|vkTn~0;LL)Q%}g+UW|{P7CnEUB1Fh$KpmzL#Zu5WOn!_+m2wdeCY*i+W-D z!`(ni!t}N~%{|7mm{-;Jt*_%TklSSU-i@y`M7BXr)vzftk=P^25s?9hh6C{i;egS_TzJeI)>xWqb-xuCAED4r-mCp%P08pb* z3q`rQ>aVXe=E>e`{i6AjKL(AT{I<)N@^ZQ+>?Q$0<8Zr>f^}xZ(&o6FiTSIe!&?vn zh((p%bVQU;_u^taU`mbG4t)WJ`Xfd4iWq_7o`WS0nb5~y3k#uAK*K|A&H|ko|7DG~ zCo3lh@&-0BNas@n`@beqP-2*HkbrrN4)kIY+tARl0~Ch6osEZ!Tkk3G0mwmL>f{b6@2n?Y}`&^t|dr&#g$I> zRfiFz`FVyqcJ4D()orj?-mt+NtS|rQiUZ~!L3%_7r`*!I`SzRkX_~~LBR*XwPoKM{ zt!;l#d?ka6GVFP^;n5n^weL-CzrFlHd8Fu?MUj4+6XO?I<+bRyXMEqWVDtShCU+j; z7>#nK7|36xuL|hq^=|!yq0wAK5G-4Vrd%^pZ!qtdy}x&`JoyTbkVjML$AX5NCAP;F zaSx;z+PSO#onHfiMJ?%lqP8^Ggub|xltlB@9P(^{jFi-VXw@p}&e-_416ykaHh$^z zfJ0am!0`mY(0?+@o>Tv78AEk7bW0hnwn7C*U*>akgHPhbujv};cWJ7{Yx-fav?>l7 z_}HVAK@itOm%{T<`{8#_XP;gZ9er1>UQz5Vur6hKxa(qU+8a3q+zp{f@s37XBqI%^D%Qs~PE1JGW2|w}J$mHOWKjDZ0GZy@uxto?HH3>a@jl4D!dzU^ zY>{OeO4^~V1-}G;anUhpp_peru z=H?&mixAI^jX#RFXXgh_gpnC+%G&6e>Zu2-Fs{s_Y-OG9_bs<@`$3s`Ul|+b<;jr! z6He-z1!sWJBs$Q_;LA$#`8~eGMz5DKp@;-oah|f1;Wj26m_g)ENrY6hHGPBKgCxbM zkb!d7USGO%RT$*OK~JQOpQ4d>#ct<?+)?bc zyU5jtU(lce9Px4a?K|0Q3@qFD?q`AF12Z3-X82m>_#voQ@MWR}siw%zSFJk{3z#Om z*k@Bx5QKbo9t|a}fr$ukZ`nS%ohU_=jSI>i4L3NQ$C(0gu}v4*rfkXi7>Q#iE4S#2YO8>6v(ejFlCulSY8DIs~{0B`vPC~mz`jaPsoHUy>*x#RFAiz#^ zfRl>7k`wv)1GeEv*m%*DC#i9lfVJc3eC|`a_aAI4ZfiO7S01qw%^~>>rc>PDArNsK z5WlvuRzAD#8S|th*|SJ%nUj?9K3;vp#){Lv+cIn%U6uV1fyJ0he~(Nqt@3VeC(q~D z>kozJw0p0ZQ|so#j2xE?4sSI(ec$;iFo9Ekjs@o37AOfeaFP-DbW_HE*o~XKdMQ9L*e72pmMULCh6s1f&iBea%&5i=LTvfIC?2A{eEtb@|Yop~5U)`f;3^S*= ztYel|@7rZ85bjW5j3rAy6*@(e;g*+G@r4mxr^TsVxe(}884V(~si!^-#cDq+e_RkN zx_J%Z4vuaxqvxoPp09e+^};VT^}(>W)>x(Pb{XD}uA zB}`kTxwf`{bNwD$KS*3H-ps1sCRzV2`D5r8bz^_kd_qIXGyWePllrmtZjuVWD4$*L z^fpb#t?XzJ2)!dkCz|U%eOXnG+x>lvHUV#_Yl;vG6b=P)yl__%Er2wjiDN2b8ucuICHIc(-6M-x%z751{uy3W!fSOxRkb$+%C|wO z0fFn2*;jWevVyAekfTA#5e8C6hjq_}x^yh3mY( z0$*#^CSl19Ba1+DTVJ1P>UaAZa=6h{=6#*Ub9yYJpkDCyZE6|cP=>|?W~hch}%JA8X#AOHW`wzQI)5Zz#-+2{huB|`F zWwLnCR~OB5Inn4W`nybHGP@_QJOPuLW?_M)XZ}g%WZdFoffY;RJpuB|H$r@?!{|wrfHO^KUbfAp!krJJoQV}RuG3`hsOFZ z&iMycmfx!aG#shg}0879m7_k&p9 z!$Efy$r9ed#yBxCi|pCFFaOK9_=_5^JGK_=Cl;z zGSikI=YjMp(~u!ob#k&+Qc5cpj*CKQyojbENjspWWvu&PZEG%$q6v7?91XVAf4J3aT;|;vy@qt3wQH%B)&Ji5Loxv)mFEbj+Q>8BQK{`2 zHJ^$XlLU{})q3e7hXw2>Icr6&lC@L9TmPvcaho42Wp*C!IF zXS@%!ybu(VEWw{clScQ_HRAG|y)bs2tH7e)r-U2oy$Q8=FYcQp3*`fI#DP|~Mf6L# z9;)c7AyYC0jN)x&6mi#3e|v2pCOR4h7XzAy60$!pz9|^!0z#edLf?(SY0dSTU8etr{DsniY_ABeqT>F;_;8PxNS6R+W@0k>0V*~FwO<%hT^qVv6rMHVjUMkhmE{69x}S=^h%Xv>8YYM>!$VoJ7u!F z>Vj>mnc?-UrhM{q&pgPnJD!S%hOLwO{1>bje{Qj2zU|7c%PU$YGA8vXflXi%>*$cb zD~XRbJdS(*lk=CaXNo{Srl;I6s{b}lR}R4nWak6T|P!hq!PjPs@IW|rlxpUu;} zy=kQwEEwX^cD01s8kB?x4X&)(XEaYjL*Emi=Fq$hPh7jxyUMc28PDuMZVszW*gf0Vz?vS8v zQSZ5{QECz%n>On-DU!?QZn7*STK2Rv<=jqTzI*p+0F~Rd@x{J2uWo( z-7`&1#gA3`IL&Rmkg7o+3ys)BPqHfJ_9@YWI)b91;npik)0W zueAPM+Rb)_A+F(A`t@<0!LF;1lZ#LBDU#qA*;>dplLjSui+gFvn-6J!$dv|eq6m5h zyv9RNX+Ln$&p%y`Y+3OI6x4`>B*32Ol_Ve}*Cr z{y%VsZWLA^4AfG?NXTk^=HT7DcKWRa3C??fb)v`5D^^T1T(wPP ziK|S#fRz{FH}}v_bKdXMi7!e4AT`>B(z(ENdwwPL+z;<$#72#-BjerEMFm%+H|5rR z-qmW5?bm$~aSNpJGfnc0T$g~Wkjp_q0m&qzOR=3y5A{DLyJ?mTA~Vi;p)#|x0gE%t z%E}Um;VpbZO}%;VBBX@NpFL47U!|^b`Pol=gsAbtpZo8RFf)n*%lI>@)MZPq&T)~Y zewsEofUJ4hON@NpqVmOF3Hv3KW`g+@Rk`sCQQ20a63N|zKOqCoPeU=Y7jUt`GjoO{ zwG}|cuQhXB!l_lWVxhsNHLD#mJ$xBk4Qyw_Of5fQyGa#|Oad9{$U&6)P(7mJl*Zr= z|AT~@H>#gsk8r$lTMM5Zj;NV?6MvR?#qtLONvTMrVsc5OZULhHlO);FBpVA5o9nkk zca3wz^!H^<5gNv9FwY_=C)KsBDW;F;KkxHe-#h5DawxPaWE%(}Yv9Pev z)C`Nt_1jrTQR}c_FH=pV>KX2!{;UEi)WVaa1)zmVUNQc*UA(d|&#YS0u1$fR!-yAl zg~^HdixV8&iSqW2@bk-PCtIU!gUy!F_v4%p2oA$NuuH!!X%NQr13RL*PmvXwNg`;`D}hcT7{?`J@FRS)M5jQefXWA6wgRdHCGp_to{XmwZpW+!@>`B9cEK zJBCtBQ}M>NCp<0a!Y&#ti1`fW%)N7|MHs(2UH0;n1ocXm?{HH~I{fN#OamWGG&MBL z4k;CoxaU&$!VIbMMFV$%jMRIPiy2#6Tf+dq5dxf~b<;Ze%Ct8JK<>}j;-!14_MYbc zYYqG(NmaXmk#G`zZ#Cy=TjjYmKM^^r&8oN}hJmbG(Uf<&Yg-$B%x3I%kavm18JRc( z6&*0zaLe91UFX+}piV<(YG&5Gp5)Z?+FuK9V~tlb_T(IWBbTt(7t7_k>SK zgJuw%L~C_6tR=HtLdi-m!5MMqZEY!t#_`%#O--)RD}jgM1~s0PHTO`4)9<<8r>BQh zhen(gT_>Qr;ITp8SLP7e#kzR#EKN1RsQfX*&P&K(ZTP??BNJ0COXH;?6c1>P2_zuL z#8^JsD=&T*rVc_q?j6(y(=yJBTD;UAA9zy8;OYL2g8yUnfgCJc+&ksu$u`iWJEVql z+=N&s(KBbVx)VvMo^VAVH~q-Fxa?$%xma`z3^+KRCg&-d6zGb@zg9oOYX+BAOFVSo9-Zng84OZKa)Q4g4+47uYzJwpfAUc|mH zCrQnS$tEYaJJ<73c#QNPsadg>0VzI7))b9fX03(Tinx& z5R$4+(mEjLy1EKJf4+_0YmJup5)&B-!BSWgOi4+J#`U%@Uqx2e*VF76h9JwfKQ$cE z>aLGWt#JC@;ktD^3O*{3sA)3Vt)E{317|m(LIr!EE)Z;gt5|nhnrM#VxdPkX)rK%lQnPr3FXvX)wkR zZ$0!StW)&^LDVfi4P|F3bwHl#Hp`e%&*I}E%1hVA>L%*EXuYOnJnsBJ{Lz%c?vh3= zgvIRX3REu075~sHFI=S-1Qp{^=ek57jtUR0WntD(l%4%*a=epJx*#Yf;{N{j*jZXE z1l*!iV`EM3PuK|h`udt%%yuhV2Tq+MM2DZOi!w*7BBzdY1xSc?jZ&bF48 z%r=NsYbqti`lr7B&D3XRY6`{?qMt8Hx|GE$OG_C6CRBYHkB9+1SK~0NWcQhKFn+@W z5M~XaxwG;53EKA^q9Q`G8$Y6mVIHIk_Eb^gjk0S%*R1lwU#pepuoW4 zk5(eYXd3BdInxYhS682@I}c0%b?lKGCL$ste6*$;e?mQ^-TF0KEj#^H-IQOd#OXT(20zZnB!|7YeouOCzpuchHL7O9(X@`E>u3%#PIZ!j($?+qP~m*KX^{VDK*z#98-~0#z37znd25%ML^z9- z<+Y!Suz|999>NPU2PcCGy;bL)oaTyF$V^D!XQC%>X&KN=I{uLOtPq=xjSU0C9Z9>B zir{z!nwWr$0Bbfwc^0whO~~QItUNgQ^R+D*Oe`TS|C-FpGp@y5kd+lT?YWlf`iaDY z1b3F!!sq#oQ1l0+1EA=*Jh+7H4}Ym#Z@bev<2~Tr9SbC=BbesbBW7#UIB#9Z+}6?doNj^XwCb@6fFx*-!kN+#8> zMwraK7LPe|Jo`)TmyGMN5ArcnPkuk89OGeQS*#3dDTc#QO|2F85-n6Tsi!CSNgmSa zRh5nODx7#Vh-jt)u|#YRi6jn~M*p#gE>ux`frx6rxi-%)*o5KJtfvU^k!_ zBmoA`8j?exb8%(+!+)PaU~R;wi4+tUEJMv3w}W)N7~$X z18h<4vzxB2l4DkU;gX%FH{TL8Of!w&pKm8YrG3;Rqmqw)^?2&Lf~L%=Q2BJ2G7|Rr zYAzM%WY!Kc#YKwj1uoKHNcR2xlcQY-iWCT^3yQ#Azi5J-w9TU;Bl~RI{Y-@ZSuZ#J{oDVe8#l=86+!uw z=A+)wic3f|sRYRT4v3&CD>)U8^`1WOFd4!q@-5^&2R(8RNSwjJCl%3fd>z-N1i_=O zjg4Hwg3a0_!`Zb6DQ(r3Z(q<_&RbrN8!F$mzYA_8;u3)s69K!Dj<&WmaM^CCZi>cR z#P&M822z7~k$%xPgwbJPm&Jl_rl0@?KYI-I_4NftM)c@o9LGaMF5Ug8Eg!Y2wR_^1 z1rhA*>@OuYq9{xOFE_qBHhwi+ENn*GRma|VboSg}TT@9M)Skzj(~ z$Xry**^3CuC-3v}>fcB5e~pUO6_CRrM*I8ufiwWS^cPe>HYouP>LToM)O^s16zuA& zS6XmKpjJmpUvL!^t366ZO?D*sp|4#1GWX-h!XQ!ZD}rLR%|`&9evY8k>021WcXx~4 zx^d^uMV2sSU0v5vp+xBuPr)Jxm=CcUpOYWZ!j{2sbXr=L0~|~vP?DSb@-g6g79H`w zS0{L!u7gEstdjTWP(#k$N8(|l*heCi<$=39o^Ec75p_9zYLdW(X20@Ttt_2`QGUWb ztBQn@62tJoPu_eJfm1Za#l_uY$a9dT4-C6^`kEZ=-OI{>{VuL)gYO(?Pet4ZK5nX6 zv&mp4^=T;-!++_Qp`?B@iI5WjEcK7Ijkmb<+f!NNL#S84$aPDT0MXktjVax^0LmfO zgqOWE6y2#jA8{bFkg(3rY{P1uXT}~^E_2R4ku+yLb%pdt3iC}qT+e`H-SBYCTRnaK z9oYlsl2?03%sLP+Ao_#cV`4S)ppnv*E2miM?jDlvm6ncsH?qqno~cUJniFTaC)

PEun;R$^tP1pY=Om~sC$_6 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

iIz#c+wGD*DDi8N0Q<#&LU#SLX^G z<_j-V8M$i}ESH%e86K^ms1z4G0Z{M({$s8NxR(4e;%k6&|AAy!(GQTBE`ET*TjGIN zpqA$Gll1(HSDjJ+@ne5Ki+}0DI`yFT)qMTBApY7(NkIXu;f>D`t!~)RA#4BgOu-BI%QGz|H$gVxbs{GE zy_%6)r{9?fnnJdf+@D}{F?LWOH3_aO0Lp-1S6*(evSNRe{LS9L;NMIR_LBbW7_@gn z!RL5RPvO6Q_3Gv$Iy#uiqUw82bHsRf?n_*D|7@Q{O4u_jDk@Upe0X(sQ-}WPO#b

Y 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 diff --git a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc b/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc deleted file mode 100644 index ce1e719..0000000 --- a/modules/use-cases-architectures/pages/starlight/rabbitmq/index.adoc +++ /dev/null @@ -1,643 +0,0 @@ -= Get started with the {starlight-rabbitmq} extension -:navtitle: {starlight-rabbitmq} -:description: Use the {starlight-rabbitmq} extension with {pulsar-reg}. - -The https://github.com/datastax/starlight-for-rabbitmq[{starlight-rabbitmq} extension] enables https://www.rabbitmq.com/[RabbitMQ] protocol support for https://pulsar.apache.org/[{pulsar-reg}] by introducing a RabbitMQ protocol handler on {pulsar-short} brokers or {pulsar-short} proxies. - -The extension acts as a proxy between your https://www.rabbitmq.com/[RabbitMQ] application and https://pulsar.apache.org/[{pulsar-reg}] cluster. -It implements the AMQP 0.9.1 protocol used by RabbitMQ clients and translates AMQP frames and concepts to {pulsar-short} concepts. - -By adding the Starlight for RabbitMQ protocol handler to your {pulsar-short} cluster, you can migrate your existing RabbitMQ applications and services to {pulsar-short} without modifying the code. - -//Move image to the Starlight for RabbitMQ main index page -image:s4r-architecture.png[{starlight-rabbitmq} Architecture] - -[#establish-the-rabbitmq-protocol-handler] -== Establish the RabbitMQ protocol handler - -Before a RabbitMQ client can interact with your {pulsar-short} cluster, you need the {starlight-rabbitmq} protocol handler installed in the cluster. - -[tabs] -====== -Astra Streaming:: -+ --- -These steps explain how to enable the {starlight-rabbitmq} protocol handler in an Astra Streaming {pulsar-short} cluster, and then get the connection details for your RabbitMQ client: - -. In the {astra-ui-link} header, click icon:grip[name="Applications"], and then select *Streaming*. - -. xref:astra-streaming:getting-started:index.adoc[Create a tenant] or click the name of an existing tenant. - -. Go to your tenant's **Connect** tab, select **RabbitMQ**, and then click **Enable RabbitMQ**. - -. Review the information about the {starlight-rabbitmq} extension, and then click **Enable RabbitMQ** to confirm that you want to enable this extension on your tenant. -+ -[IMPORTANT] -==== -This action creates a configuration file and a `rabbitmq` namespace in your Astra Streaming tenant automatically. - -The `rabbitmq` namespace is required for the {starlight-rabbitmq} extension to function properly. -It is a permanent namespace that cannot be removed except by deleting the entire tenant and all of its data. -==== - -. Save the RabbitMQ connection details to a file named `rabbitmq.conf`. -The actual values depend on your Astra Streaming tenant's configuration and cloud provider. -+ -.rabbitmq.conf -[source,conf,subs="+quotes,+attributes"] ----- -username: **TENANT_NAME** -password: {asterisk}{asterisk}{asterisk}{asterisk}{asterisk}{asterisk} -host: rabbitmq-**PROVIDER**-**REGION**.streaming.datastax.com -port: 5671 -virtual_host: **TENANT_NAME**/rabbitmq -ampq_URI: {asterisk}{asterisk}{asterisk}{asterisk}{asterisk}{asterisk}@rabbitmq-**PROVIDER**-**REGION**.streaming.datastax.com:5671/**TENANT_NAME**/rabbitmq ----- -+ -[TIP] -==== -In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a {pulsar-short} token is included in the `password` field automatically. -You can also generate a token on your tenant's **Settings** tab. -==== -+ -Continue to the next section to learn how to use these connection details in a RabbitMQ client script. - --- - -Luna Streaming:: -+ --- -The {starlight-rabbitmq} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. -The Luna Helm chart simplifies deployment of the the RabbitMQ extension. - -The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the {starlight-rabbitmq} extension ready for use: - -. Make sure you meet the following prerequisites: -+ -* Install https://helm.sh/docs/intro/install/[Helm 3 CLI] version 3.8.0 or later. -* Install https://kubernetes.io/docs/tasks/tools/[kubectl CLI] version 1.23.4 or later. -* Have access to a Kubernetes cluster with permission to create a namespace, deployments, and pods. - -. Add the {company} Helm chart repo to your Helm store: -+ -[source,shell] ----- -helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart ----- - -. Install the Helm chart using a minimal values file. -The following command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart within a Kubernetes namespace named `datastax-pulsar`. -This minimal configuration creates only the essential components and has no ingress or load balanced services. -+ -[source,shell] ----- -VALUES_URL="https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main/starlight-for-rabbitmq/values.yaml" -helm install \ - --namespace datastax-pulsar \ - --create-namespace \ - --values $VALUES_URL \ - --version 3.0.4 \ - my-pulsar-cluster \ - datastax-pulsar/pulsar ----- - -. Wait for the broker pod to reach a running state. -It might restart a few times while the components start up. -+ -[source,shell] ----- -kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ----- - -. Enable port forwarding for the {pulsar-short} Admin and {starlight-rabbitmq} services that are running on the Kubernetes cluster: -+ -.. In a new terminal, port forward the {pulsar-short} Admin service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ----- - -.. In a separate terminal window, port forward the {starlight-rabbitmq} service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-proxy 5672:5672 ----- - -+ -[TIP] -==== -You don't need to open the {pulsar-short} binary port to accept new messages when using {starlight-rabbitmq}. -This is because RabbitMQ clients communicate using the AMQP protocol over the RabbitMQ port (5672). -==== -The Luna Helm chart deployed Starlight for RabbitMQ on the {pulsar-short} proxy and opened the correct port. -The forwarded ports allow you to access {pulsar-short} and {starlight-rabbitmq} services when running RabbitMQ client scripts and using CLI tools locally. -Your applications can now communicate with {pulsar-short} as if it were a real RabbitMQ host, as explained in the next section. - --- - -Self-managed:: -+ --- -To use {starlight-rabbitmq} with self-managed or standalone {pulsar-short} clusters, see xref:starlight-for-rabbitmq:installation:getting-started.adoc[]. --- -====== - -== Produce and consume messages with {starlight-rabbitmq} - -This section explains how to use your Pulsar tenant's connection details with a RabbitMQ client to produce and consume messages with {starlight-rabbitmq}. - -{starlight-rabbitmq} supports many different use cases. -With a {pulsar-short} cluster between publishers and consumers, you can change the type of publisher and consumer to fit your needs. - -The following examples use Python and Java. -The Java example uses Maven, but you can also use Gradle. -For complete source code examples and examples for other languages, see the https://github.com/datastax/astra-streaming-examples[{company} streaming examples repository]. -These examples are written for Astra Streaming but they can be adapted for Luna Streaming or self-managed {pulsar-short} clusters by replacing the connection details with those for your cluster. - -[tabs] -====== -Astra Streaming:: -+ --- -[tabs] -==== -Python client:: -+ -The following example uses a Python script to create a connection between RabbitMQ and your Astra Streaming tenant. -It also establishes a message queue named `queuename`, prints ten messages, and then closes the connection. -+ -. Enable {starlight-rabbitmq} and get the `rabbitmq.conf` connection details, as explained in <>. -+ -. Create a `connect-test.py` file containing the following code, and then replace the placeholders with the values from your `rabbitmq.conf` file: -+ -.connect-test.py -[source,python,subs="+quotes"] ----- -import ssl -import pika - -virtual_host = "**VIRTUAL_HOST**" -token = "**PASSWORD**" - -context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) -context.verify_mode = ssl.CERT_NONE -context.check_hostname = False -context.load_default_certs() -ssl_options = pika.SSLOptions(context) - -connection = pika.BlockingConnection(pika.ConnectionParameters( - virtual_host=virtual_host, - host="**HOST**", - ssl_options=ssl_options, - port=**PORT**, - credentials=pika.PlainCredentials("", token))) -print("connection success") - -channel = connection.channel() -print("started a channel") - -channel.queue_declare(queue='queuename') - -for x in range(10): - channel.basic_publish(exchange='', - routing_key='routingkey', - body='message body goes here') - print(" sent one") - -connection.close() ----- -+ -. Optional: Change the values for `queue`, `routing_key`, and `body`. -`queuename` and `routingkey` become the names of {pulsar-short} topics in your Astra Streaming tenant. -The `body` is the content of each message that is sent. -+ -. Save and run the `connect-test.py` script: -+ -[source,shell] ----- -python3 connect-test.py ----- -+ -. Make sure the output shows that the connection was successful and ten messages were sent: -+ -[source,console] ----- -connection success -started a channel - sent one - sent one - sent one - sent one - sent one - sent one - sent one - sent one - sent one - sent one ----- -+ -. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `rabbitmq` namespace. -+ -If you everything was configured correctly, then the `rabbitmq` namespace should have topics named `amq.default.__queuename` and `amq.default_routingkey` that were created by the Python script. -Additionally, the namespace's metrics should reflect that at least 10 messages were published and consumed by your Astra Streaming {pulsar-short} topics. - -Java client:: -+ -The following example uses a Java program to create a connection between RabbitMQ and your Astra Streaming tenant, and then it establishes a message queue and sends a message. -+ -. Enable {starlight-rabbitmq} and get the `rabbitmq.conf` connection details, as explained in <>. -+ -. Create a new Maven project: -+ -[source,shell] ----- -mvn archetype:generate \ - -DgroupId=org.example \ - -DartifactId=StarlightForRabbitMqClient \ - -DarchetypeArtifactId=maven-archetype-quickstart \ - -DinteractiveMode=false ----- -+ -. Change to the new project directory: -+ -[source,shell] ----- -cd StarlightForRabbitMqClient ----- -+ -. Open the new project in your IDE, and then add the RabbitMQ client dependency to `pom.xml`: -+ -.pom.xml -[source,xml] ----- - - com.rabbitmq - amqp-client - 5.16.0 - ----- -+ -. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preeixsting code in this file. -In the next steps, you will add code to this file to create a complete program that produces and consumes messages. -+ -. Paste the following code in the file, and then replace the placeholders with the values from your `rabbitmq.conf` file. -Your editor will report errors because this isn't a complete program yet. -+ -.App.java -[source,java,subs="+quotes"] ----- -package org.example; - -import com.rabbitmq.client.*; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.concurrent.TimeoutException; - -public class App { - private static final String username = ""; - private static final String password = "**PASSWORD**"; - private static final String host = "**HOST**"; - private static final int port = 5671; - private static final String virtual_host = "**VIRTUAL_HOST**"; - private static final String queueName = "queuename"; - private static final String amqp_URI = String.format("amqps://%s:%s@%s:%d/%s", username, password, host, port, virtual_host.replace("/","%2f")); - - public static void main(String[] args) throws IOException, TimeoutException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException, InterruptedException { ----- -+ -. Optional: Replace `queuename` with another name for the queue that publishes and consumes messages. -This name is also used as the corresponding topic name in Astra Streaming. -If the topic doesn't exist, it is created automatically when the producer sends the first message. -+ -. Add the following code to create a connection, channel, and queue that is used by both the producer and consumer: -+ -.App.java -[source,java] ----- - ConnectionFactory factory = new ConnectionFactory(); - factory.setUri(amqp_URI); - - /* - You could also set each value individually - factory.setHost(host); - factory.setPort(port); - factory.setUsername(username); - factory.setPassword(password); - factory.setVirtualHost(virtual_host); - factory.useSslProtocol(); - */ - - Connection connection = factory.newConnection(); - Channel channel = connection.createChannel(); - - channel.queueDeclare(queueName, false, false, false, null); ----- -+ -. Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: -+ -.App.java -[source,java] ----- - String publishMessage = "Hello World!"; - channel.basicPublish("", queueName, null, publishMessage.getBytes()); - System.out.println(" Sent '" + publishMessage + "'"); ----- -+ -. Add the consumer code, which creates a basic consumer with callback on message receipt. -Because the consumer isn't a blocking thread, the `sleep` allows time for messages to be received and processed. -+ -.App.java -[source,java] ----- - DeliverCallback deliverCallback = (consumerTag, delivery) -> { - String consumeMessage = new String(delivery.getBody(), StandardCharsets.UTF_8); - System.out.println(" Received '" + consumeMessage + "'"); - }; - - channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { }); - - Thread.sleep(4000); // wait a bit for messages to be received - - channel.close(); - connection.close(); - } -} ----- -+ -. Save `App.java`, and then build and run the JAR file for the complete program: -+ -[source,shell] ----- -mvn clean package assembly:single -java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.jar ----- -+ -. Make sure the result shows that a message was sent and received: -+ -[source,shell] ----- -Sent 'Hello World!' -Received 'Hello World!' ----- -+ -. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `rabbitmq` namespace. -+ -If you everything was configured correctly, then the `rabbitmq` namespace should have a topic named `amq.default.__queuename` that was created by the Java program. -Additionally, the namespace's metrics should reflect that at least one message was published and consumed by your Astra Streaming {pulsar-short} topic. -==== - --- - -Luna Streaming:: -+ --- -To use a RabbitMQ client with {starlight-rabbitmq}, you use your Luna Streaming {pulsar-short} tenant as the AMQP listener. -The following examples use a connection on `localhost:5672`. -For other connection methods, see the documentation for your preferred RabbitMQ client library. - -[tabs] -==== -Python client:: -+ -The following example uses the Pika RabbitMQ Python library to produce and consume messages from {pulsar-short}. -+ -. Save the following Python script to a safe place as `test-queue.py`. -The example script assumes you have opened the `localhost:5672` port, as explained in <>. -+ -.test-queue.py -[source,python] ----- -#!/usr/bin/env python -import pika - -connection = pika.BlockingConnection(pika.ConnectionParameters(port=5672)) -channel = connection.channel() - -try: - channel.queue_declare("test-queue") - print("created test-queue queue") - - channel.basic_publish(exchange="", routing_key="test-queue", body="test".encode('utf-8')) - print("published message test") - - _, _, res = channel.basic_get(queue="test-queue", auto_ack=True) - assert res is not None, "should have received a message" - print("received message: " + res.decode()) - - channel.queue_delete("test-queue") - print("deleted test-queue queue") - -finally: - connection.close() ----- -+ -. Optional: Replace `test-queue` with another name for the queue and routing key. These names are also used as the corresponding topic names in your {pulsar-short} tenant. If the topic doesn't exist, it is created automatically when the producer sends the first message. -+ -. Save and run the `test-queue.py` script: -+ -[source,shell] ----- -python ./test-queue.py ----- -+ -. Make sure the output shows that the queue was created and a message was sent: -+ -[source,shell] ----- -created test-queue queue -published message test -received message: test -deleted test-queue queue ----- -+ -. Use the {pulsar} admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity. -Make sure the `test-queue` topic was created and a message was published and consumed. - -Java client:: -+ -The following example uses a Java program to create a connection between RabbitMQ and your Luna Streaming {pulsar-short} tenant, and then it establishes a message queue and sends a message. -+ -. Create a new Maven project: -+ -[source,shell] ----- -mvn archetype:generate \ - -DgroupId=org.example \ - -DartifactId=StarlightForRabbitMqClient \ - -DarchetypeArtifactId=maven-archetype-quickstart \ - -DinteractiveMode=false ----- -+ -. Change to the new project directory: -+ -[source,shell] ----- -cd StarlightForRabbitMqClient ----- -+ -. Open the new project in your IDE, and then add the RabbitMQ client dependency to `pom.xml`: -+ -.pom.xml -[source,xml] ----- - - com.rabbitmq - amqp-client - 5.16.0 - ----- -+ -. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preeixsting code in this file. -In the next steps, you will add code to this file to create a complete program that produces and consumes messages. -+ -. Paste the following code in the file. -This code creates a connection, channel, and queue that is used by both the producer and consumer. -It uses the default connection values to connect on `localhost:5672`, which was port forwarded in <>. -Your editor will report errors because this isn't a complete program yet. -+ -.App.java -[source,java] ----- -package org.example; - -import com.rabbitmq.client.*; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.concurrent.TimeoutException; - -public class App { - private static final String queueName = "queuename"; - - public static void main(String[] args) throws IOException, TimeoutException, URISyntaxException, NoSuchAlgorithmException, KeyManagementException, InterruptedException { - - // Use the default values to connect on localhost:5672 - ConnectionFactory factory = new ConnectionFactory(); - factory.setUsername(userName); - factory.setPassword(password); - factory.setVirtualHost(virtualHost); - factory.setHost(hostName); - factory.setPort(portNumber); - - Connection connection = factory.newConnection(); - Channel channel = connection.createChannel(); - - channel.queueDeclare(queueName, false, false, false, null); ----- -+ -. Optional: Replace `queuename` with another name for the queue that publishes and consumes messages. -This name is also used as the corresponding topic name in Astra Streaming. -If the topic doesn't exist,it is created automatically when the producer sends the first message. -+ -. Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: -+ -.App.java -[source,java] ----- - String publishMessage = "Hello World!"; - channel.basicPublish("", queueName, null, publishMessage.getBytes()); - System.out.println(" Sent '" + publishMessage + "'"); ----- -+ -. Add the consumer code, which creates a basic consumer with callback on message receipt. -Because the consumer isn't a blocking thread, the `sleep` allows time for messages to be received and processed. -+ -.App.java -[source,java] ----- - DeliverCallback deliverCallback = (consumerTag, delivery) -> { - String consumeMessage = new String(delivery.getBody(), StandardCharsets.UTF_8); - System.out.println(" Received '" + consumeMessage + "'"); - }; - - channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { }); - - Thread.sleep(4000); // wait a bit for messages to be received - - channel.close(); - connection.close(); - } -} ----- -+ -. Save `App.java`, and then build and run the JAR file for the complete program: -+ -[source,shell] ----- -mvn clean package assembly:single -java -jar target/StarlightForRabbitMqClient-1.0-SNAPSHOT-jar-with-dependencies.jar ----- -+ -. Make sure the result shows that a message was sent and received: -+ -[source,shell] ----- -Sent 'Hello World!' -Received 'Hello World!' ----- -+ -. Use the {pulsar-short} Admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity. -Make sure the `queuename` topic was created and a message was published and consumed. -==== - --- - -Self-managed:: -+ --- -To use a RabbitMQ client with {starlight-rabbitmq}, you use your {pulsar-short} tenant as the AMQP listener. -You can also connect on `localhost` if you have port forwarded the RabbitMQ port (5672) to your local machine. - -For `localhost` examples, see the Luna Streaming tab. -However, the specific connection details and valid connection methods depend on your cluster's configuration. - -For more information, see the documentation for your preferred RabbitMQ client library. --- -====== - -== RabbitMQ exchanges and {pulsar-short} topics - -//Move to Publishing messages section under Pulsar protocol handler in Starlight for RabbitMQ docs. - -{starlight-rabbitmq} maps RabbitMQ _exchanges_ to {pulsar-short} _topics_, as described in the following table: - -[cols=4] -|=== -|Exchange |Routing key |{pulsar-short} topic name |Usage example - -|`amp.direct` -|Used -|`amq.direct.__{routing key}` -|`channel.basic_publish(exchange='amp.direct'),` - -|`amp.default` or empty string -|Used -|`amq.default.__{routing key}` -|`channel.basic_publish(exchange="),` - -|`amp.match` -|Not used -|`amp.match` -|`channel.basic_publish(exchange=amp.match),` - -|`amp.fanout` -|Not used -|`amp.fanout` -|`channel.basic_publish(exchange='amp.fanout'),` - -|`headers` -|Not used -|Header name -|`channel.exchange_declare(exchange='header_logs', exchange_type='headers')` - -`channel.basic_publish(exchange='header_logs'),` -|=== \ No newline at end of file From 210ae02cb04535ad6741f800fb47ccf18bbbeb9d Mon Sep 17 00:00:00 2001 From: April M <36110273+aimurphy@users.noreply.github.com> Date: Mon, 12 Jan 2026 13:28:06 -0800 Subject: [PATCH 9/9] move s4k to s4k repo --- .../images/s4k-architecture.png | Bin 86596 -> 0 bytes .../pages/starlight/kafka/index.adoc | 514 ------------------ 2 files changed, 514 deletions(-) delete mode 100644 modules/use-cases-architectures/images/s4k-architecture.png delete mode 100644 modules/use-cases-architectures/pages/starlight/kafka/index.adoc diff --git a/modules/use-cases-architectures/images/s4k-architecture.png b/modules/use-cases-architectures/images/s4k-architecture.png deleted file mode 100644 index 47af0ceae269b9702ae2dbd4af5410569c91fea7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86596 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¥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

BB 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 diff --git a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc b/modules/use-cases-architectures/pages/starlight/kafka/index.adoc deleted file mode 100644 index ac557db..0000000 --- a/modules/use-cases-architectures/pages/starlight/kafka/index.adoc +++ /dev/null @@ -1,514 +0,0 @@ -= Get started with the {starlight-kafka} extension -:navtitle: {starlight-kafka} -:description: Use the {starlight-kafka} extension with {pulsar-reg}. - -The https://github.com/datastax/starlight-for-kafka[{starlight-kafka} extension] brings the native Apache Kafka(R) protocol support to {pulsar-reg} by introducing a Kafka protocol handler on {pulsar-short} brokers. - -By adding the {starlight-kafka} protocol handler to your existing {pulsar-short} cluster, you can migrate your existing Kafka applications and services to {pulsar-short} without modifying the code. - -//Move this image to the Starlight for Kafka main index page -image:s4k-architecture.png[{starlight-kafka} Architecture] - -[#establish-the-kafka-protocol-handler] -== Establish the Kafka protocol handler - -Before a Kafka client can interact with your {pulsar-short} cluster, you need the {starlight-kafka} protocol handler installed in the cluster. - -[tabs] -====== -Astra Streaming:: -+ --- -These steps explain how to enable the {starlight-kafka} protocol handler in an Astra Streaming {pulsar-short} cluster, and then get the connection details for your Kafka client: - -. In the {astra-ui-link} header, click icon:grip[name="Applications"], and then select *Streaming*. - -. xref:astra-streaming:getting-started:index.adoc[Create a tenant] or click the name of an existing tenant. - -. Go to your tenant's **Connect** tab, select **Kafka**, and then click **Enable Kafka**. - -. Review the information about the {starlight-kafka} extension, and then click **Enable Kafka** to confirm that you want to enable this extension on your tenant. -+ -[IMPORTANT] -==== -This action creates a configuration file and the following three namespaces in your Astra Streaming tenant automatically: - -* `kafka`: Produces and consumes messages -* `+__kafka+`: Supports required Kafka functionality -* `+__kafka_unlimited+`: Stores metadata - -These namespaces are required for the {starlight-kafka} extension to function properly. -These are permanent namespaces that cannot be removed except by deleting the entire tenant and all of its data. -==== - -. Save the Kafka connection details to a file named `ssl.properties`. -The actual values depend on your Astra Streaming tenant's configuration and cloud provider. -+ -.ssl.properties -[source,plain,subs="+quotes,+attributes"] ----- -username: **TENANT_NAME** -password: token:{asterisk}{asterisk}{asterisk}{asterisk}{asterisk}{asterisk} -bootstrap.servers: kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 -schema.registry.url: https://kafka-**PROVIDER**-**REGION**.streaming.datastax.com:8081 -security.protocol: SASL_SSL -sasl.mechanism: PLAIN ----- -+ -[TIP] -==== -In Astra Streaming, if you click icon:download[name="Download"] or icon:clipboard[name="Copy"], then a {pulsar-short} token is included in the `password` field automatically. -You can also generate a token on your tenant's **Settings** tab. -==== - -. Optional: Add a session timeout value to the `ssl.properties` file to avoid connection issues with some Kafka clients: -+ -[source,properties] ----- -session.timeout.ms=45000 ----- -+ -Continue to the next section to learn how to use the connection details in a Kafka client script. - --- - -Luna Streaming:: -+ --- -The {starlight-kafka} extension is included in the `luna-streaming-all` image used to deploy a Luna cluster. -The Luna Helm chart simplifies deployment of the Kafka extension. - -The following steps explain how to deploy a Luna Streaming Helm chart to create a simple {pulsar-short} cluster with the {starlight-kafka} extension ready to use. - -. Make sure you meet the following prerequisites: -+ -* Install https://helm.sh/docs/intro/install/[Helm 3 CLI] version 3.8.0 or later. -* Install https://www.apache.org/dyn/closer.cgi?path=/kafka/3.3.1/kafka_2.13-3.3.1.tgz[Kafka CLI] version 3.3.1 or later -* Install https://kubernetes.io/docs/tasks/tools/[kubectl CLI] version 1.23.4 or later. -* Have access to a Kubernetes cluster with permission to create a namespace, deployments, and pods. - -. Add the {company} Helm chart repo to your Helm store: -+ -[source,shell] ----- -helm repo add datastax-pulsar https://datastax.github.io/pulsar-helm-chart ----- - -. Install the Helm chart using a minimal values file. -The following command creates a Helm release named `my-pulsar-cluster` using the {company} Luna Helm chart within a Kubernetes namespace named `datastax-pulsar`. -This minimal configuration creates only the essential components and has no ingress or load balanced services. -+ -[source,shell] ----- -VALUES_URL="https://raw.githubusercontent.com/datastaxdevs/luna-streaming-examples/main/starlight-for-kafka/values.yaml" -helm install \ - --namespace datastax-pulsar \ - --create-namespace \ - --values $VALUES_URL \ - --version 3.0.4 \ - my-pulsar-cluster \ - datastax-pulsar/pulsar ----- - -. Wait for the broker pod to reach a running state. -It might restart a few times while the components start up. -+ -[source,shell] ----- -kubectl -n datastax-pulsar wait --for=condition=Ready pod/pulsar-broker-0 --timeout=120s ----- - -. Use the {pulsar-short} Admin CLI to inspect the tenants, namespaces, and topics that were created in your {pulsar-short} cluster when you deployed the Helm chart with the {starlight-kafka} extension enabled. -+ -By default, the Helm chart create a tenant named `public` with a namespace named `default`. -In addition, the {starlight-kafka} extension creates several namespaces and topics that are required for its functionality. -These namespaces are prefixed with `+__kafka+`. -+ -List the namespaces in the `public` tenant: -+ -[source,shell] ----- -~/apache-pulsar-3.1.3$ ./bin/pulsar-admin namespaces list public ----- -+ -Make sure the output includes the `default` and `+__kafka+` namespaces: -+ -[source,shell] ----- -public/__kafka -public/__kafka_producerid -public/default ----- - -. Enable port forwarding for the {pulsar-short} Admin and {starlight-kafka} services that are running on the Kubernetes cluster: -+ -.. In a new terminal, port forward the {pulsar-short} Admin service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-broker 8080:8080 ----- - -.. In a separate terminal window, port forward the {starlight-kafka} service: -+ -[source,shell] ----- -kubectl port-forward -n datastax-pulsar service/pulsar-proxy 9092:9092 ----- - -+ -[TIP] -==== -You don't need to open the {pulsar-short} binary port to accept new messages when using {starlight-kafka}. -This is because Kafka clients communicate using the Kafka protocol on port 9092, which is handled by the {starlight-kafka} extension. -==== -After deploying the Helm chart and enabling port forwarding, your applications can communicate with {pulsar-short} as if it were a real Kafka host, as explained in the next section. - --- - -Self-managed:: -+ --- -To use {starlight-kafka} with self-managed or standalone {pulsar-short} clusters, see xref:starlight-for-kafka:installation:starlight-kafka-quickstart.adoc[]. --- -====== - -== Produce and consume messages with {starlight-kafka} - -This section explains how to use your Pulsar tenant's connection details with a Kafka client to produce and consume messages with {starlight-kafka}. - -{starlight-kafka} supports many different use cases. -With a {pulsar-short} cluster between publishers and consumers, you can change the type of publisher and consumer to fit your needs. - -The following examples use the Kafka CLI and Java. -For complete source code examples and examples for other languages, see the https://github.com/datastax/astra-streaming-examples[{company} streaming examples repository]. -These examples are written for Astra Streaming but they can be adapted for Luna Streaming or self-managed {pulsar-short} clusters by replacing the connection details with those for your cluster. - -[tabs] -====== -Astra Streaming:: -+ --- -[tabs] -==== -Kafka CLI:: -+ -This example uses command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball]. -+ -. Enable {starlight-kafka} and get the `ssl.properties` connection details, as explained in <>. -+ -. In Astra Streaming, in the `kafka` namespace, create a topic to receive messages from the `kafka-console-producer`. -You can use any valid name for the topic. -+ -. Move your Astra Streaming `ssl.properties` file into your Kafka installation's `config` subdirectory, such as `kafka_2.13-3.1.0/config`. -+ -. In a terminal window, use the `kafka-console-producer` tool to create a Kafka producer that produces messages on the topic you created in the `kafka` namespace: -+ -[source,shell,subs="+quotes"] ----- -bin/kafka-console-producer \ ---broker-list kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ ---topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ ---producer.config config/ssl.properties ----- -+ -When the producer is ready, it accepts standard input from the user. -To send a message, type it in the terminal, and then press kbd:[Return]. -Optionally, you can send some messages before starting the consumer to see how it retrieves past messages. -+ -. In a new terminal window, use the `kafka-console-consumer` tool to create a Kafka consumer that consumes messages from the beginning of your topic: -+ -[source,shell,subs="+quotes"] ----- -bin/kafka-console-consumer \ ---bootstrap-server kafka-**PROVIDER**-**REGION**.streaming.datastax.com:9093 \ ---topic **TENANT_NAME**/kafka/**TOPIC_NAME** \ ---consumer.config config/ssl.properties \ ---from-beginning ----- -+ -Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. -+ -. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. -+ -As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. -+ -. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. -To verify that your Kafka messages are being produced and consumed in your Astra Streaming {pulsar-short} cluster, check the **Data In** metrics. -The number of messages should be equal to the number of messages you sent with the `kafka-console-producer`. -+ -. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. - -Java client:: -+ -The following example uses a Java program to create a connection between Kafka and your Astra Streaming tenant, configures a producer and consumer, and then sends a message. -This example uses Maven, but you can also use Gradle. -+ -. Enable {starlight-kafka} and get the `ssl.properties` connection details, as explained in <>. -+ -. Create a new Maven project: -+ -[source,shell] ----- -mvn archetype:generate \ - -DgroupId=org.example \ - -DartifactId=StarlightForKafkaClient \ - -DarchetypeArtifactId=maven-archetype-quickstart \ - -DinteractiveMode=false ----- -+ -. Change to the new project directory: -+ -[source,shell] ----- -cd StarlightForKafkaClient ----- -+ -. Open the new project in your IDE, and then add the Kafka client dependency to `pom.xml`: -+ -.pom.xml -[source,xml] ----- - - org.apache.kafka - kafka-clients - 3.3.1 - ----- -+ -. Open the `App.java` file at `src/main/java/org/example/App.java`, and then delete any preexisting code in this file. -In the next steps, you will add code to this file to create a complete program that produces and consumes messages. -+ -. Paste the following code in the file, and then replace the placeholder values with the values from your `ssl.properties` file. -Your editor will report errors because this isn't a complete program yet. -+ -[source,java,subs="+quotes"] ----- -package org.example; - -import org.apache.kafka.clients.consumer.ConsumerConfig; -import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.kafka.clients.consumer.ConsumerRecords; -import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.producer.*; -import org.apache.kafka.common.serialization.LongSerializer; -import org.apache.kafka.common.serialization.StringDeserializer; -import org.apache.kafka.common.serialization.StringSerializer; - -import java.time.Duration; -import java.util.Collections; -import java.util.Properties; - -public class App { - private static String bootstrapServers = "**BOOTSTRAP_SERVER_URL**"; - private static String pulsarToken = "**PASSWORD**"; - private static String tenantName = "**USERNAME**"; - private static final String namespace = "kafka"; - private static final String topicName = "quickstart"; - private static final String topic = String.format("persistent://%s/%s/%s", tenantName,namespace,topicName); - - public static void main(String[] args) { ----- -+ -. Optional: Replace `quickstart` with another name for the topic that receives messages from the Kafka producer. -If the topic doesn't exist, it is created it automatically when the producer sends the first message. -+ -. Add the following code that builds the configuration for the producer and consumer: -+ -[source,java] ----- - Properties config = new Properties(); - config.put("bootstrap.servers",bootstrapServers); - config.put("security.protocol","SASL_SSL"); - config.put("sasl.jaas.config", String.format("org.apache.kafka.common.security.plain.PlainLoginModule required username='%s' password='token:%s';", tenantName, pulsarToken)); - config.put("sasl.mechanism","PLAIN"); - config.put("session.timeout.ms","45000"); - config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName()); - config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); - config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); - config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); - config.put("group.id", "my-consumer-group"); ----- -+ -. Add the producer code, which is a simple flow that sends a single message and awaits acknowledgment: -+ -[source,java] ----- - KafkaProducer producer = new KafkaProducer<>(config); - - final ProducerRecord producerRecord = new ProducerRecord<>(topic, System.currentTimeMillis(), "Hello World"); - producer.send(producerRecord, new Callback() { - public void onCompletion(RecordMetadata metadata, Exception e) { - if (e != null) - System.out.println(String.format("Send failed for record, %s. \nRecord data: %s",e.getMessage(), producerRecord)); - else - System.out.println("Successfully sent message"); - } - }); - - producer.flush(); - producer.close(); ----- -+ -. Add the consumer code, which creates a basic subscription and retrieves the latest messages on the topic: -+ -[source,java] ----- - final KafkaConsumer consumer = new KafkaConsumer(config); - - consumer.subscribe(Collections.singletonList(topic)); - ConsumerRecords consumerRecords = consumer.poll(Duration.ofMillis(5000)); - - System.out.println(String.format("Found %d total record(s)", consumerRecords.count())); - - for (ConsumerRecord consumerRecord : consumerRecords) { - System.out.println(consumerRecord); - } - - consumer.commitSync(); - consumer.close(); - } -} ----- -+ -. Save `App.java`, and then build and run the JAR file for the complete program: -+ -[source,shell] ----- -mvn clean package assembly:single -java -jar target/StarlightForKafkaClient-1.0-SNAPSHOT-jar-with-dependencies.jar ----- -+ -. Make sure the result shows that a message was produces and consumed: -+ -[source,shell] ----- -Successfully sent message - -Found 1 total record(s) -ConsumerRecord(topic = persistent://my-tenant-007/my-namespace/my-topic, partition = 0, leaderEpoch = null, offset = 22, CreateTime = 1673545962124, serialized key size = 8, serialized value size = 11, headers = RecordHeaders(headers = [], isReadOnly = false), key = xxxxx, value = Hello World) ----- -+ -. In Astra Streaming, go to your tenant's **Namespaces and Topics** tab to inspect the activity in the `kafka` namespace. -+ -If you everything was configured correctly, then the `kafka` namespace should have a topic named `quickstart` that was created by the Java program. -Additionally, the namespace's metrics should reflect that at least one message was published and consumed by your Astra Streaming {pulsar-short} topic. -==== - --- - -Luna Streaming:: -+ --- -To use the Kafka CLI or a Kafka client with {starlight-kafka}, you use your Luna Streaming {pulsar-short} tenant as the Kafka bootstrap server. -The following example command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball], and it connects on `localhost:9092` because port forwarding was enabled in <>. - -. In your Kafka installation directory, start the `kafka-console-producer` shell: -+ -[source,shell] ----- -bin/kafka-console-producer.sh \ ---topic quickstart \ ---bootstrap-server localhost:9092 ----- -+ -You can replace `quickstart` with any other name for the topic that will receive messages from the producer. -If the specified topic doesn't exist in your Luna Streaming tenant, it is created automatically when the producer sends the first message. -You can configure this behavior and other xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[{starlight-kafka} parameters] in the https://github.com/datastaxdevs/luna-streaming-examples/blob/main/starlight-for-kafka/values.yaml[Helm chart]. -+ -.Connect to a remote cluster -[%collapsible] -==== -To connect to a remote Luna Streaming cluster, provide the full topic name and the bootstrap server URL for your Luna Streaming tenant: - -[source,shell,subs="+quotes"] ----- -bin/kafka-console-producer.sh --topic "**TENANT_NAME**/**NAMESPACE_NAME**/**TOPIC_NAME**" --bootstrap-server "**SERVICE_URL**" ----- -==== - -. When the producer is ready, type a message, and then press kbd:[Return] to send it. -Optionally, you can send several messages before starting the consumer to see how it retrieves past messages. - -. In a new terminal window, start the `kafka-console-consumer` shell: -+ -[source,shell] ----- -bin/kafka-console-consumer.sh \ ---topic quickstart \ ---bootstrap-server localhost:9092 \ ---from-beginning ----- -+ -Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. - -. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. -+ -As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. - -. Use the {pulsar-short} Admin CLI or the Luna Streaming {pulsar-short} Admin Console to inspect your tenant's activity, and verify that messages were published and consumed on the specified topic. - -. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. --- - -Self-managed:: -+ --- -To use the Kafka CLI or a Kafka client with {starlight-kafka}, you use your {pulsar-short} tenant as the Kafka bootstrap server. -The following example command line tools included with the https://kafka.apache.org/downloads[Apache Kafka tarball], and it assumes port forwarding is enabled to connect on `localhost:9092`. - -. In your Kafka installation directory, start the `kafka-console-producer` shell: -+ -[source,shell] ----- -bin/kafka-console-producer.sh \ ---topic quickstart \ ---bootstrap-server localhost:9092 ----- -+ -You can replace `quickstart` with any other name for the topic that will receive messages from the producer. -If the specified topic doesn't exist in your {pulsar-short} tenant, it is created automatically when the producer sends the first message. -You can configure this behavior and other xref:starlight-for-kafka:configuration:starlight-kafka-configuration.adoc[{starlight-kafka} parameters]. -+ -.Connect to a remote cluster -[%collapsible] -==== -To connect to a remote {pulsar-short} cluster, provide the full topic name and the bootstrap server URL for your tenant: - -[source,shell,subs="+quotes"] ----- -bin/kafka-console-producer.sh --topic "**TENANT_NAME**/**NAMESPACE_NAME**/**TOPIC_NAME**" --bootstrap-server "**SERVICE_URL**" ----- -==== - -. When the producer is ready, type a message, and then press kbd:[Return] to send it. -Optionally, you can send several messages before starting the consumer to see how it retrieves past messages. - -. In a new terminal window, start the `kafka-console-consumer` shell: -+ -[source,shell] ----- -bin/kafka-console-consumer.sh \ ---topic quickstart \ ---bootstrap-server localhost:9092 \ ---from-beginning ----- -+ -Because this command uses the `--from-beginning` option, when the consumer starts, it retrieves any messages that were sent to the topic before it started. - -. Send a few messages in the `kafka-console-producer` terminal to generate more traffic on the tenant. -+ -As you send messages and the consumer receives them, they appear in the `kafka-console-consumer` terminal. - -. Use the {pulsar-short} Admin CLI to inspect your tenant's activity, and verify that messages were published and consumed on the specified topic. - -. To exit the producer and consumer shells, press kbd:[Ctrl]+kbd:[C] in each terminal. --- -====== - -== See also - -* xref:starlight-for-kafka:operations:starlight-kafka-kstreams.adoc[] -* xref:starlight-for-kafka:operations:starlight-kafka-implementation.adoc[] -* xref:starlight-for-kafka:operations:starlight-kafka-monitor.adoc[] -* xref:starlight-for-kafka:operations:starlight-kafka-security.adoc[] \ No newline at end of file