@@ -2,77 +2,85 @@ use crate::{
2
2
client:: Client ,
3
3
environment:: Environment ,
4
4
error:: { ProducerCreateError , ProducerPublishError } ,
5
- producer:: { ConfirmationStatus , Producer } ,
6
- superstream:: { RouteType , RoutingStrategy } ,
5
+ producer:: { ConfirmationStatus , Producer , NoDedup } ,
6
+ superstream:: { DefaultSuperStreamMetadata , RoutingStrategy } ,
7
7
} ;
8
8
use rabbitmq_stream_protocol:: message:: Message ;
9
+ use std:: collections:: HashMap ;
9
10
use std:: future:: Future ;
10
11
use std:: marker:: PhantomData ;
11
12
use std:: sync:: Arc ;
12
13
13
14
type FilterValueExtractor = Arc < dyn Fn ( & Message ) -> String + ' static + Send + Sync > ;
14
15
15
16
#[ derive( Clone ) ]
16
- pub struct NoDedup { }
17
-
18
- pub struct Dedup { }
19
-
20
- #[ derive( Clone ) ]
21
- pub struct SuperStreamProducer < T > ( Arc < SuperStreamProducerInternal > , PhantomData < T > ) ;
17
+ pub struct SuperStreamProducer < T > ( Arc < SuperStreamProducerInternal < T > > , PhantomData < T > ) ;
22
18
23
19
/// Builder for [`SuperStreamProducer`]
24
- pub struct SuperStreamProducerBuilder < ' a > {
20
+ pub struct SuperStreamProducerBuilder < T > {
25
21
pub ( crate ) environment : Environment ,
26
22
pub ( crate ) name : Option < String > ,
27
23
pub filter_value_extractor : Option < FilterValueExtractor > ,
28
- pub routing_strategy : & ' a dyn RoutingStrategy ,
24
+ pub routing_strategy : RoutingStrategy ,
25
+ pub ( crate ) data : PhantomData < T > ,
29
26
}
30
27
31
- pub struct SuperStreamProducerInternal < ' a > {
28
+ pub struct SuperStreamProducerInternal < T > {
29
+ pub ( crate ) environment : Environment ,
32
30
client : Client ,
33
31
super_stream : String ,
34
32
publish_version : u16 ,
35
- producers : Vec < Producer ( ) > ,
33
+ producers : HashMap < String , Producer < T > > ,
36
34
filter_value_extractor : Option < FilterValueExtractor > ,
37
- routing_strategy : & ' a dyn RoutingStrategy ,
35
+ super_stream_metadata : DefaultSuperStreamMetadata ,
36
+ routing_strategy : RoutingStrategy ,
38
37
}
39
38
40
39
impl SuperStreamProducer < NoDedup > {
41
40
pub async fn send < Fut > (
42
41
& self ,
43
42
message : Message ,
44
- cb : impl Fn ( Result < ConfirmationStatus , ProducerPublishError > ) -> Fut + Send + Sync + ' static ,
45
- ) -> Result < ( ) , ProducerPublishError >
46
- where
43
+ cb : impl Fn ( Result < ConfirmationStatus , ProducerPublishError > ) -> Fut + Send + Sync + ' static + Clone ,
44
+ ) where
47
45
Fut : Future < Output = ( ) > + Send + Sync + ' static ,
48
46
{
49
- self . do_send ( message, cb) . await
50
- }
51
- }
47
+ let routes = match self . 0 . routing_strategy . clone ( ) {
48
+ RoutingStrategy :: HashRoutingStrategy ( routing_strategy) => {
49
+ routing_strategy
50
+ . routes ( message. clone ( ) , & mut self . 0 . super_stream_metadata . clone ( ) )
51
+ . await
52
+ }
53
+ RoutingStrategy :: RoutingKeyStrategy ( routing_strategy) => {
54
+ routing_strategy
55
+ . routes ( message. clone ( ) , & mut self . 0 . super_stream_metadata . clone ( ) )
56
+ . await
57
+ }
58
+ } ;
52
59
53
- impl SuperStreamProducer < Dedup > {
54
- pub async fn send < Fut > (
55
- & self ,
56
- message : Message ,
57
- cb : impl Fn ( Result < ConfirmationStatus , ProducerPublishError > ) -> Fut + Send + Sync + ' static ,
58
- ) -> Result < ( ) , ProducerPublishError >
59
- where
60
- Fut : Future < Output = ( ) > + Send + Sync + ' static ,
61
- {
62
- self . do_send ( message, cb) . await
60
+ for route in routes. into_iter ( ) {
61
+ if !self . 0 . producers . contains_key ( route. as_str ( ) ) {
62
+ let producer = self . 0 . environment . producer ( ) . build ( route. as_str ( ) ) . await ;
63
+ self . 0 . producers . clone ( ) . insert ( route. clone ( ) , producer. unwrap ( ) . clone ( ) ) ;
64
+ }
65
+
66
+ let producer = self . 0 . producers . get ( route. as_str ( ) ) . unwrap ( ) ;
67
+ _ = producer
68
+ . send ( message. clone ( ) , cb. clone ( ) )
69
+ . await ;
70
+ }
63
71
}
64
72
}
65
73
66
74
impl < T > SuperStreamProducerBuilder < T > {
67
75
pub async fn build (
68
76
self ,
69
77
super_stream : & str ,
70
- route_type : RouteType ,
78
+ route_type : RoutingStrategy ,
71
79
) -> Result < SuperStreamProducer < T > , ProducerCreateError > {
72
80
// Connect to the user specified node first, then look for the stream leader.
73
81
// The leader is the recommended node for writing, because writing to a replica will redundantly pass these messages
74
82
// to the leader anyway - it is the only one capable of writing.
75
- let mut client = self . environment . create_client ( ) . await ?;
83
+ let client = self . environment . create_client ( ) . await ?;
76
84
77
85
let mut publish_version = 1 ;
78
86
@@ -84,14 +92,21 @@ impl<T> SuperStreamProducerBuilder<T> {
84
92
}
85
93
}
86
94
87
- let producers = Vec :: new ( ) ;
95
+ let producers = HashMap :: new ( ) ;
88
96
89
97
let super_stream_producer = SuperStreamProducerInternal {
98
+ environment : self . environment . clone ( ) ,
90
99
super_stream : super_stream. to_string ( ) ,
91
100
client,
92
101
publish_version,
93
102
filter_value_extractor : self . filter_value_extractor ,
94
103
routing_strategy : route_type,
104
+ super_stream_metadata : DefaultSuperStreamMetadata {
105
+ super_stream : super_stream. to_string ( ) ,
106
+ client : self . environment . create_client ( ) . await ?,
107
+ partitions : Vec :: new ( ) ,
108
+ routes : Vec :: new ( ) ,
109
+ } ,
95
110
producers,
96
111
} ;
97
112
0 commit comments