Skip to content

Commit 293ccf6

Browse files
feat: Message To Drop Semantics (#47)
Signed-off-by: shubham <[email protected]> Signed-off-by: Yashash H L <[email protected]> Co-authored-by: Yashash H L <[email protected]>
1 parent e993a18 commit 293ccf6

File tree

7 files changed

+367
-71
lines changed

7 files changed

+367
-71
lines changed

examples/map-cat/src/main.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ struct Cat;
1111
#[tonic::async_trait]
1212
impl map::Mapper for Cat {
1313
async fn map(&self, input: map::MapRequest) -> Vec<map::Message> {
14-
vec![map::Message {
15-
keys: input.keys,
16-
value: input.value,
17-
tags: vec![],
18-
}]
14+
let message = map::Message::new(input.value)
15+
.keys(input.keys)
16+
.tags(vec![]);
17+
vec![message]
1918
}
2019
}

examples/map-tickgen-serde/src/main.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use numaflow::map;
2+
use numaflow::map::Message;
23

34
#[tokio::main]
45
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
@@ -38,14 +39,15 @@ impl map::Mapper for TickGen {
3839
let ts = Utc
3940
.timestamp_nanos(payload.created_ts)
4041
.to_rfc3339_opts(SecondsFormat::Nanos, true);
41-
vec![map::Message {
42-
keys: input.keys,
43-
value: serde_json::to_vec(&ResultPayload {
42+
let message = map::Message::new(
43+
serde_json::to_vec(&ResultPayload {
4444
value: payload.data.value,
4545
time: ts,
4646
})
4747
.unwrap_or_default(),
48-
tags: vec![],
49-
}]
48+
)
49+
.keys(input.keys)
50+
.tags(vec![]);
51+
vec![message]
5052
}
5153
}

examples/reduce-counter/src/main.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,10 @@ mod counter {
4848
md.start_time(),
4949
md.end_time()
5050
);
51-
vec![Message {
52-
keys: keys.clone(),
53-
value: counter.to_string().into_bytes(),
54-
tags: vec![],
55-
}]
51+
let message = reduce::Message::new(counter.to_string().into_bytes())
52+
.keys(keys.clone())
53+
.tags(vec![]);
54+
vec![message]
5655
}
5756
}
5857
}

examples/source-transformer-now/src/main.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ impl sourcetransform::SourceTransformer for NowCat {
1616
&self,
1717
input: sourcetransform::SourceTransformRequest,
1818
) -> Vec<sourcetransform::Message> {
19-
vec![sourcetransform::Message {
20-
keys: input.keys,
21-
value: input.value,
22-
event_time: chrono::offset::Utc::now(),
23-
tags: vec![],
24-
}]
19+
let message = sourcetransform::Message::new(input.value, chrono::offset::Utc::now())
20+
.keys(input.keys)
21+
.tags(vec![]);
22+
vec![message]
2523
}
2624
}

src/map.rs

+109-16
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use std::future::Future;
22
use std::path::PathBuf;
33

44
use chrono::{DateTime, Utc};
5+
use serde_json::Value;
56
use tonic::{async_trait, Request, Response, Status};
67

78
use crate::shared;
89

9-
1010
const DEFAULT_MAX_MESSAGE_SIZE: usize = 64 * 1024 * 1024;
1111
const DEFAULT_SOCK_ADDR: &str = "/var/run/numaflow/map.sock";
1212
const DEFAULT_SERVER_INFO_FILE: &str = "/var/run/numaflow/mapper-server-info";
13-
13+
const DROP: &str = "U+005C__DROP__";
1414
/// Numaflow Map Proto definitions.
1515
pub mod proto {
1616
tonic::include_proto!("map.v1");
@@ -45,11 +45,9 @@ pub trait Mapper {
4545
/// #[tonic::async_trait]
4646
/// impl map::Mapper for Cat {
4747
/// async fn map(&self, input: map::MapRequest) -> Vec<map::Message> {
48-
/// vec![map::Message {
49-
/// keys: input.keys,
50-
/// value: input.value,
51-
/// tags: vec![],
52-
/// }]
48+
/// use numaflow::map::Message;
49+
/// let message=Message::new(input.value).keys(input.keys).tags(vec![]);
50+
/// vec![message]
5351
/// }
5452
/// }
5553
/// ```
@@ -79,22 +77,115 @@ where
7977
}
8078

8179
/// Message is the response struct from the [`Mapper::map`] .
80+
#[derive(Debug, PartialEq)]
8281
pub struct Message {
8382
/// Keys are a collection of strings which will be passed on to the next vertex as is. It can
8483
/// be an empty collection.
85-
pub keys: Vec<String>,
84+
pub keys: Option<Vec<String>>,
8685
/// Value is the value passed to the next vertex.
8786
pub value: Vec<u8>,
8887
/// Tags are used for [conditional forwarding](https://numaflow.numaproj.io/user-guide/reference/conditional-forwarding/).
89-
pub tags: Vec<String>,
88+
pub tags: Option<Vec<String>>,
89+
}
90+
/// Represents a message that can be modified and forwarded.
91+
impl Message {
92+
/// Creates a new message with the specified value.
93+
///
94+
/// This constructor initializes the message with no keys, tags, or specific event time.
95+
///
96+
/// # Arguments
97+
///
98+
/// * `value` - A vector of bytes representing the message's payload.
99+
///
100+
/// # Examples
101+
///
102+
/// ```
103+
/// use numaflow::map::Message;
104+
/// let message = Message::new(vec![1, 2, 3, 4]);
105+
/// ```
106+
pub fn new(value:Vec<u8>) -> Self {
107+
Self{
108+
value,
109+
keys:None,
110+
tags:None
111+
}
112+
}
113+
/// Marks the message to be dropped by creating a new `Message` with an empty value and a special "DROP" tag.
114+
///
115+
/// # Examples
116+
///
117+
/// ```
118+
/// use numaflow::map::Message;
119+
/// let dropped_message = Message::message_to_drop();
120+
/// ```
121+
pub fn message_to_drop() -> Message {
122+
Message {
123+
keys: None,
124+
value: vec![],
125+
tags: Some(vec![DROP.to_string()]),
126+
}
127+
}
128+
129+
130+
/// Sets or replaces the keys associated with this message.
131+
///
132+
/// # Arguments
133+
///
134+
/// * `keys` - A vector of strings representing the keys.
135+
///
136+
/// # Examples
137+
///
138+
/// ```
139+
/// use numaflow::map::Message;
140+
/// let message = Message::new(vec![1, 2, 3]).keys(vec!["key1".to_string(), "key2".to_string()]);
141+
/// ```
142+
pub fn keys(mut self, keys: Vec<String>) -> Self {
143+
self.keys = Some(keys);
144+
self
145+
}
146+
147+
/// Sets or replaces the tags associated with this message.
148+
///
149+
/// # Arguments
150+
///
151+
/// * `tags` - A vector of strings representing the tags.
152+
///
153+
/// # Examples
154+
///
155+
/// ```
156+
/// use numaflow::map::Message;
157+
/// let message = Message::new(vec![1, 2, 3]).tags(vec!["tag1".to_string(), "tag2".to_string()]);
158+
/// ```
159+
pub fn tags(mut self, tags: Vec<String>) -> Self {
160+
self.tags = Some(tags);
161+
self
162+
}
163+
164+
/// Replaces the value of the message.
165+
///
166+
/// # Arguments
167+
///
168+
/// * `value` - A new vector of bytes that replaces the current message value.
169+
///
170+
/// # Examples
171+
///
172+
/// ```
173+
/// use numaflow::map::Message;
174+
/// let message = Message::new(vec![1, 2, 3]).value(vec![4, 5, 6]);
175+
/// ```
176+
pub fn value(mut self, value: Vec<u8>) -> Self {
177+
self.value = value;
178+
self
179+
}
180+
90181
}
91182

92183
impl From<Message> for proto::map_response::Result {
93184
fn from(value: Message) -> Self {
94185
proto::map_response::Result {
95-
keys: value.keys,
186+
keys: value.keys.unwrap_or_default(),
96187
value: value.value,
97-
tags: value.tags,
188+
tags: value.tags.unwrap_or_default(),
98189
}
99190
}
100191
}
@@ -209,14 +300,14 @@ impl<T> Server<T> {
209300

210301
#[cfg(test)]
211302
mod tests {
212-
use std::{error::Error, time::Duration};
213-
use tower::service_fn;
214-
215303
use crate::map;
216304
use crate::map::proto::map_client::MapClient;
305+
use crate::map::{Message};
306+
use std::{error::Error, time::Duration};
217307
use tempfile::TempDir;
218308
use tokio::sync::oneshot;
219309
use tonic::transport::Uri;
310+
use tower::service_fn;
220311

221312
#[tokio::test]
222313
async fn map_server() -> Result<(), Box<dyn Error>> {
@@ -225,9 +316,9 @@ mod tests {
225316
impl map::Mapper for Cat {
226317
async fn map(&self, input: map::MapRequest) -> Vec<map::Message> {
227318
vec![map::Message {
228-
keys: input.keys,
319+
keys: Some(input.keys),
229320
value: input.value,
230-
tags: vec![],
321+
tags: Some(vec![]),
231322
}]
232323
}
233324
}
@@ -284,4 +375,6 @@ mod tests {
284375
assert!(task.is_finished(), "gRPC server is still running");
285376
Ok(())
286377
}
378+
379+
287380
}

0 commit comments

Comments
 (0)