krishvishal commented on code in PR #3784:
URL: https://github.com/apache/iggy/pull/3784#discussion_r3719634810


##########
core/connectors/sinks/iggy_sink/src/lib.rs:
##########
@@ -0,0 +1,232 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::mem;
+
+use async_trait::async_trait;
+use bytes::Bytes;
+use iggy::clients::client::IggyClient;
+use iggy_common::{Client, Identifier, IggyMessage, MessageClient, 
Partitioning};
+use iggy_connector_sdk::{
+    ConsumedMessage, Error, MessagesMetadata, Payload, Sink, TopicMetadata, 
sink_connector,
+};
+use serde::{Deserialize, Serialize};
+use tracing::{debug, info};
+
+sink_connector!(IggySink);
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct IggySinkConfig {
+    pub server_address: String,
+    pub stream_id: Option<String>,
+    pub topic_id: Option<String>,
+}
+
+#[derive(Debug)]
+pub struct IggySink {
+    id: u32,
+    config: IggySinkConfig,
+    client: Option<IggyClient>,
+}
+
+impl IggySink {
+    pub fn new(id: u32, config: IggySinkConfig) -> Self {
+        IggySink {
+            id,
+            config,
+            client: None,
+        }
+    }
+}
+
+#[async_trait]
+impl Sink for IggySink {
+    async fn open(&mut self) -> Result<(), Error> {
+        info!(
+            "Opened iggy_sink with ID: {}, connecting to: {}",
+            self.id, self.config.server_address
+        );
+
+        let client = 
IggyClient::from_connection_string(&self.config.server_address)
+            .map_err(|e| Error::InitError(format!("Failed to build client: 
{e}")))?;
+
+        client
+            .connect()
+            .await
+            .map_err(|e| Error::InitError(format!("Failed to connect: {e}")))?;
+
+        info!("Successfully connected to downstream Iggy cluster");
+
+        self.client = Some(client);
+        Ok(())
+    }
+
+    async fn consume(
+        &self,
+        topic_metadata: &TopicMetadata,
+        messages_metadata: MessagesMetadata,
+        messages: Vec<ConsumedMessage>,
+    ) -> Result<(), Error> {
+        let client = self
+            .client
+            .as_ref()
+            .ok_or_else(|| Error::InitError("Client not 
initialized".to_string()))?;
+
+        let stream = self
+            .config
+            .stream_id
+            .as_ref()
+            .unwrap_or(&topic_metadata.stream);
+        let topic = self
+            .config
+            .topic_id
+            .as_ref()
+            .unwrap_or(&topic_metadata.topic);
+
+        let stream_id: Identifier = stream
+            .as_str()
+            .try_into()
+            .map_err(|_| Error::InvalidConfigValue(format!("Invalid stream: 
{stream}")))?;
+        let topic_id: Identifier = topic
+            .as_str()
+            .try_into()
+            .map_err(|_| Error::InvalidConfigValue(format!("Invalid topic: 
{topic}")))?;
+
+        let partitioning = 
Partitioning::partition_id(messages_metadata.partition_id);

Review Comment:
   Multi-partition source topics can have their messages silently misrouted:  
(Partitioning::partition_id(messages_metadata.partition_id)) forwards the last 
message's source partition ID as the routing key for the entire flushed batch. 
Traced in runtime/src/sink.rs's consume_messages: partition_id is reassigned 
every loop iteration from whatever partition the last poll returned, and a 
single sink consumer (one consumer-group member) round-robins across all 
partitions assigned to it. A batch can end up containing messages from 
partitions 0 and 1, tagged and routed entirely under partition 1's ID. This 
label-only field is harmless for every other sink (none of them route by it); 
iggy_sink is the first
     to turn it into an actual write-path decision. 
   
   Reachability: any source topic with >1 partition (the norm), not exercised 
by this PR's own
     single-partition example/test config. Fix: group ConsumedMessages by 
originating partition before building the target batch (one send_messages call 
per source partition) — sink-local, reduces batching efficiency slightly when a 
poll straddles
     partitions. A structural fix (guarantee single-partition batches at the 
runtime level) affects every sink and needs separate sign-off.
   



##########
core/connectors/sinks/iggy_sink/src/lib.rs:
##########
@@ -0,0 +1,232 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::mem;
+
+use async_trait::async_trait;
+use bytes::Bytes;
+use iggy::clients::client::IggyClient;
+use iggy_common::{Client, Identifier, IggyMessage, MessageClient, 
Partitioning};
+use iggy_connector_sdk::{
+    ConsumedMessage, Error, MessagesMetadata, Payload, Sink, TopicMetadata, 
sink_connector,
+};
+use serde::{Deserialize, Serialize};
+use tracing::{debug, info};
+
+sink_connector!(IggySink);
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct IggySinkConfig {
+    pub server_address: String,

Review Comment:
   Credentials logged in plaintext; not `SecretString`. logged unredacted at 
:59-62 `(info!("Opened iggy_sink with ID: {}, connecting to: {}", self.id,  
self.config.server_address))`. Every config shipped in this PR embeds 
credentials (iggy://iggy:[email protected]:8090).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to