11package io .numaproj .numaflow .sinker ;
22
3+ import com .google .protobuf .ByteString ;
4+ import common .MetadataOuterClass ;
5+ import io .numaproj .numaflow .sink .v1 .SinkOuterClass .SinkResponse ;
36import lombok .AccessLevel ;
47import lombok .AllArgsConstructor ;
58import lombok .Getter ;
69
10+ import java .util .Collections ;
11+ import java .util .Map ;
12+ import java .util .stream .Collectors ;
13+
714/**
815 * Response is used to send response from the user defined sinker. It contains the id of the
916 * message, success status, an optional error message and a fallback status. Various static factory
@@ -16,15 +23,21 @@ public class Response {
1623 private final Boolean success ;
1724 private final String err ;
1825 private final Boolean fallback ;
26+ private final Boolean serve ;
27+ private final byte [] serveResponse ;
28+ private final Boolean onSuccess ;
29+ // FIXME: Should this be Message object from this package? That would allow parity with other SDKs (specially Go)
30+ // Currently done this way to prevent conversion in buildResult method.
31+ private final SinkResponse .Result .Message onSuccessMessage ;
1932
20- /**
33+ /**
2134 * Static method to create response for successful message processing.
2235 *
2336 * @param id id of the message
2437 * @return Response object with success status
2538 */
2639 public static Response responseOK (String id ) {
27- return new Response (id , true , null , false );
40+ return new Response (id , true , null , false , false , null , false , null );
2841 }
2942
3043 /**
@@ -35,7 +48,7 @@ public static Response responseOK(String id) {
3548 * @return Response object with failure status and error message
3649 */
3750 public static Response responseFailure (String id , String errMsg ) {
38- return new Response (id , false , errMsg , false );
51+ return new Response (id , false , errMsg , false , false , null , false , null );
3952 }
4053
4154 /**
@@ -46,6 +59,89 @@ public static Response responseFailure(String id, String errMsg) {
4659 * @return Response object with fallback status
4760 */
4861 public static Response responseFallback (String id ) {
49- return new Response (id , false , null , true );
62+ return new Response (id , false , null , true , false , null , false , null );
63+ }
64+
65+ /**
66+ * Static method to create response for serve message which is raw bytes.
67+ * This indicates that the message should be sent to the serving store.
68+ * Allows creation of serve message from raw bytes.
69+ *
70+ * @param id id of the message
71+ * @param serveResponse Response object to be sent to the serving store
72+ * @return Response object with serve status and serve response
73+ */
74+ public static Response responseServe (String id , byte [] serveResponse ) {
75+ return new Response (id , false , null , false , true , serveResponse , false , null );
76+ }
77+
78+ /**
79+ * Static method to create response for onSuccess message. Allows creation of onSuccess message
80+ * from protobuf Message object.
81+ *
82+ * @param id id of the message
83+ * @param onSuccessMessage OnSuccessMessage object to be sent to the onSuccess sink
84+ * @return Response object with onSuccess status and onSuccess message
85+ */
86+ public static Response responseOnSuccess (String id , SinkResponse .Result .Message onSuccessMessage ) {
87+ return new Response (id , false , null , false , false , null , true , onSuccessMessage );
88+ }
89+
90+ /**
91+ * Overloaded static method to create response for onSuccess message. Allows creation of onSuccess message
92+ * from OnSuccessMessage object.
93+ *
94+ * @param id id of the message
95+ * @param onSuccessMessage OnSuccessMessage object to be sent to the onSuccess sink. Can be null
96+ * if original message needs to be written to onSuccess sink
97+ * @return Response object with onSuccess status and onSuccess message
98+ */
99+ public static Response responseOnSuccess (String id , Message onSuccessMessage ) {
100+ if (onSuccessMessage == null ) {
101+ return new Response (id , false , null , false , false , null , true , null );
102+ } else {
103+
104+ Map <String , MetadataOuterClass .KeyValueGroup > pbUserMetadata = MetadataOuterClass .Metadata
105+ .getDefaultInstance ()
106+ .getUserMetadataMap ();
107+
108+ if (onSuccessMessage .getUserMetadata () != null ) {
109+ pbUserMetadata =
110+ onSuccessMessage .getUserMetadata ()
111+ .entrySet ()
112+ .stream ()
113+ .filter (e -> e .getKey () != null && e .getValue () != null )
114+ .collect (Collectors .toMap (
115+ Map .Entry ::getKey ,
116+ e -> MetadataOuterClass .KeyValueGroup .newBuilder ()
117+ .putAllKeyValue (e .getValue ().getKeyValue () == null
118+ ? Collections .emptyMap ()
119+ : e .getValue ()
120+ .getKeyValue ()
121+ .entrySet ()
122+ .stream ()
123+ .filter (kv -> kv .getKey () != null
124+ && kv .getValue () != null )
125+ .collect (Collectors .toMap (
126+ Map .Entry ::getKey ,
127+ kv -> ByteString .copyFrom (kv .getValue ())
128+ ))
129+ )
130+ .build ()
131+ ));
132+ }
133+
134+ MetadataOuterClass .Metadata pbMetadata = MetadataOuterClass .Metadata .newBuilder ()
135+ .putAllUserMetadata (pbUserMetadata )
136+ .build ();
137+
138+ SinkResponse .Result .Message pbOnSuccessMessage = SinkResponse .Result .Message .newBuilder ()
139+ .addKeys (onSuccessMessage .getKey () == null ? "" : onSuccessMessage .getKey ())
140+ .setValue (onSuccessMessage .getValue () == null ? ByteString .EMPTY : ByteString .copyFrom (onSuccessMessage .getValue ()))
141+ .setMetadata (pbMetadata )
142+ .build ();
143+
144+ return new Response (id , false , null , false , false , null , true , pbOnSuccessMessage );
145+ }
50146 }
51147}
0 commit comments