@@ -2,15 +2,15 @@ use std::future::Future;
2
2
use std:: path:: PathBuf ;
3
3
4
4
use chrono:: { DateTime , Utc } ;
5
+ use serde_json:: Value ;
5
6
use tonic:: { async_trait, Request , Response , Status } ;
6
7
7
8
use crate :: shared;
8
9
9
-
10
10
const DEFAULT_MAX_MESSAGE_SIZE : usize = 64 * 1024 * 1024 ;
11
11
const DEFAULT_SOCK_ADDR : & str = "/var/run/numaflow/map.sock" ;
12
12
const DEFAULT_SERVER_INFO_FILE : & str = "/var/run/numaflow/mapper-server-info" ;
13
-
13
+ const DROP : & str = "U+005C__DROP__" ;
14
14
/// Numaflow Map Proto definitions.
15
15
pub mod proto {
16
16
tonic:: include_proto!( "map.v1" ) ;
@@ -45,11 +45,9 @@ pub trait Mapper {
45
45
/// #[tonic::async_trait]
46
46
/// impl map::Mapper for Cat {
47
47
/// 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]
53
51
/// }
54
52
/// }
55
53
/// ```
@@ -79,22 +77,115 @@ where
79
77
}
80
78
81
79
/// Message is the response struct from the [`Mapper::map`] .
80
+ #[ derive( Debug , PartialEq ) ]
82
81
pub struct Message {
83
82
/// Keys are a collection of strings which will be passed on to the next vertex as is. It can
84
83
/// be an empty collection.
85
- pub keys : Vec < String > ,
84
+ pub keys : Option < Vec < String > > ,
86
85
/// Value is the value passed to the next vertex.
87
86
pub value : Vec < u8 > ,
88
87
/// 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
+
90
181
}
91
182
92
183
impl From < Message > for proto:: map_response:: Result {
93
184
fn from ( value : Message ) -> Self {
94
185
proto:: map_response:: Result {
95
- keys : value. keys ,
186
+ keys : value. keys . unwrap_or_default ( ) ,
96
187
value : value. value ,
97
- tags : value. tags ,
188
+ tags : value. tags . unwrap_or_default ( ) ,
98
189
}
99
190
}
100
191
}
@@ -209,14 +300,14 @@ impl<T> Server<T> {
209
300
210
301
#[ cfg( test) ]
211
302
mod tests {
212
- use std:: { error:: Error , time:: Duration } ;
213
- use tower:: service_fn;
214
-
215
303
use crate :: map;
216
304
use crate :: map:: proto:: map_client:: MapClient ;
305
+ use crate :: map:: { Message } ;
306
+ use std:: { error:: Error , time:: Duration } ;
217
307
use tempfile:: TempDir ;
218
308
use tokio:: sync:: oneshot;
219
309
use tonic:: transport:: Uri ;
310
+ use tower:: service_fn;
220
311
221
312
#[ tokio:: test]
222
313
async fn map_server ( ) -> Result < ( ) , Box < dyn Error > > {
@@ -225,9 +316,9 @@ mod tests {
225
316
impl map:: Mapper for Cat {
226
317
async fn map ( & self , input : map:: MapRequest ) -> Vec < map:: Message > {
227
318
vec ! [ map:: Message {
228
- keys: input. keys,
319
+ keys: Some ( input. keys) ,
229
320
value: input. value,
230
- tags: vec![ ] ,
321
+ tags: Some ( vec![ ] ) ,
231
322
} ]
232
323
}
233
324
}
@@ -284,4 +375,6 @@ mod tests {
284
375
assert ! ( task. is_finished( ) , "gRPC server is still running" ) ;
285
376
Ok ( ( ) )
286
377
}
378
+
379
+
287
380
}
0 commit comments