@@ -43,7 +43,13 @@ description() ->
43
43
<<" Add a super stream (experimental feature)" >>.
44
44
45
45
switches () ->
46
- [{partitions , integer }, {routing_keys , string }].
46
+ [{partitions , integer },
47
+ {routing_keys , string },
48
+ {max_length_bytes , string },
49
+ {max_age , string },
50
+ {stream_max_segment_size_bytes , string },
51
+ {leader_locator , string },
52
+ {initial_cluster_size , integer }].
47
53
48
54
help_section () ->
49
55
{plugin , stream }.
@@ -55,11 +61,73 @@ validate([_Name], #{partitions := _, routing_keys := _}) ->
55
61
" Specify --partitions or routing-keys, not both." };
56
62
validate ([_Name ], #{partitions := Partitions }) when Partitions < 1 ->
57
63
{validation_failure , " The partition number must be greater than 0" };
58
- validate ([_Name ], _Opts ) ->
59
- ok ;
64
+ validate ([_Name ], Opts ) ->
65
+ validate_stream_arguments ( Opts ) ;
60
66
validate (_ , _Opts ) ->
61
67
{validation_failure , too_many_args }.
62
68
69
+ validate_stream_arguments (#{max_length_bytes := Value } = Opts ) ->
70
+ case parse_information_unit (Value ) of
71
+ error ->
72
+ {validation_failure ,
73
+ " Invalid value for --max-length-bytes, valid example "
74
+ " values: 100gb, 50mb" };
75
+ _ ->
76
+ validate_stream_arguments (maps :remove (max_length_bytes , Opts ))
77
+ end ;
78
+ validate_stream_arguments (#{max_age := Value } = Opts ) ->
79
+ case rabbit_date_time :parse_duration (Value ) of
80
+ {ok , _ } ->
81
+ validate_stream_arguments (maps :remove (max_age , Opts ));
82
+ error ->
83
+ {validation_failure ,
84
+ " Invalid value for --max-age, the value must a "
85
+ " ISO 8601 duration, e.g. e.g. PT10M30S for 10 "
86
+ " minutes 30 seconds, P5DT8H for 5 days 8 hours." }
87
+ end ;
88
+ validate_stream_arguments (#{stream_max_segment_size_bytes := Value } =
89
+ Opts ) ->
90
+ case parse_information_unit (Value ) of
91
+ error ->
92
+ {validation_failure ,
93
+ " Invalid value for --stream-max-segment-size-bytes, "
94
+ " valid example values: 100gb, 50mb" };
95
+ _ ->
96
+ validate_stream_arguments (maps :remove (stream_max_segment_size_bytes ,
97
+ Opts ))
98
+ end ;
99
+ validate_stream_arguments (#{leader_locator := <<" client-local" >>} =
100
+ Opts ) ->
101
+ validate_stream_arguments (maps :remove (leader_locator , Opts ));
102
+ validate_stream_arguments (#{leader_locator := <<" random" >>} = Opts ) ->
103
+ validate_stream_arguments (maps :remove (leader_locator , Opts ));
104
+ validate_stream_arguments (#{leader_locator := <<" least-leaders" >>} =
105
+ Opts ) ->
106
+ validate_stream_arguments (maps :remove (leader_locator , Opts ));
107
+ validate_stream_arguments (#{leader_locator := _ }) ->
108
+ {validation_failure ,
109
+ " Invalid value for --leader-locator, valid values "
110
+ " are client-local, random, least-leaders." };
111
+ validate_stream_arguments (#{initial_cluster_size := Value } = Opts ) ->
112
+ try
113
+ case rabbit_data_coercion :to_integer (Value ) of
114
+ S when S > 0 ->
115
+ validate_stream_arguments (maps :remove (initial_cluster_size ,
116
+ Opts ));
117
+ _ ->
118
+ {validation_failure ,
119
+ " Invalid value for --initial-cluster-size, the "
120
+ " value must be positive." }
121
+ end
122
+ catch
123
+ error :_ ->
124
+ {validation_failure ,
125
+ " Invalid value for --initial-cluster-size, the "
126
+ " value must be a positive integer." }
127
+ end ;
128
+ validate_stream_arguments (_ ) ->
129
+ ok .
130
+
63
131
merge_defaults (_Args , #{routing_keys := _V } = Opts ) ->
64
132
{_Args , maps :merge (#{vhost => <<" /" >>}, Opts )};
65
133
merge_defaults (_Args , Opts ) ->
@@ -77,7 +145,25 @@ usage_additional() ->
77
145
" exclusive with --routing-keys." ],
78
146
[" --routing-keys <routing-keys>" ,
79
147
" Comma-separated list of routing keys. Mutually "
80
- " exclusive with --partitions." ]].
148
+ " exclusive with --partitions." ],
149
+ [" --max-length-bytes <max-length-bytes>" ,
150
+ " The maximum size of partition streams, example "
151
+ " values: 20gb, 500mb." ],
152
+ [" --max-age <max-age>" ,
153
+ " The maximum age of partition stream segments, "
154
+ " using the ISO 8601 duration format, e.g. PT10M30S "
155
+ " for 10 minutes 30 seconds, P5DT8H for 5 days "
156
+ " 8 hours." ],
157
+ [" --stream-max-segment-size-bytes <stream-max-segment-si"
158
+ " ze-bytes>" ,
159
+ " The maximum size of partition stream segments, "
160
+ " example values: 500mb, 1gb." ],
161
+ [" --leader-locator <leader-locator>" ,
162
+ " Leader locator strategy for partition streams, "
163
+ " possible values are client-local, least-leaders, "
164
+ " random." ],
165
+ [" --initial-cluster-size <initial-cluster-size>" ,
166
+ " The initial cluster size of partition streams." ]].
81
167
82
168
usage_doc_guides () ->
83
169
[? STREAM_GUIDE_URL ].
@@ -86,7 +172,8 @@ run([SuperStream],
86
172
#{node := NodeName ,
87
173
vhost := VHost ,
88
174
timeout := Timeout ,
89
- partitions := Partitions }) ->
175
+ partitions := Partitions } =
176
+ Opts ) ->
90
177
Streams =
91
178
[list_to_binary (binary_to_list (SuperStream )
92
179
++ " -"
@@ -99,12 +186,14 @@ run([SuperStream],
99
186
VHost ,
100
187
SuperStream ,
101
188
Streams ,
189
+ stream_arguments (Opts ),
102
190
RoutingKeys );
103
191
run ([SuperStream ],
104
192
#{node := NodeName ,
105
193
vhost := VHost ,
106
194
timeout := Timeout ,
107
- routing_keys := RoutingKeysStr }) ->
195
+ routing_keys := RoutingKeysStr } =
196
+ Opts ) ->
108
197
RoutingKeys =
109
198
[rabbit_data_coercion :to_binary (
110
199
string :strip (K ))
@@ -121,21 +210,64 @@ run([SuperStream],
121
210
VHost ,
122
211
SuperStream ,
123
212
Streams ,
213
+ stream_arguments (Opts ),
124
214
RoutingKeys ).
125
215
216
+ stream_arguments (Opts ) ->
217
+ stream_arguments (#{}, Opts ).
218
+
219
+ stream_arguments (Acc , Arguments ) when map_size (Arguments ) =:= 0 ->
220
+ Acc ;
221
+ stream_arguments (Acc , #{max_length_bytes := Value } = Arguments ) ->
222
+ stream_arguments (maps :put (<<" max-length-bytes" >>,
223
+ parse_information_unit (Value ), Acc ),
224
+ maps :remove (max_length_bytes , Arguments ));
225
+ stream_arguments (Acc , #{max_age := Value } = Arguments ) ->
226
+ {ok , Duration } = rabbit_date_time :parse_duration (Value ),
227
+ DurationInSeconds = duration_to_seconds (Duration ),
228
+ stream_arguments (maps :put (<<" max-age" >>,
229
+ list_to_binary (integer_to_list (DurationInSeconds )
230
+ ++ " s" ),
231
+ Acc ),
232
+ maps :remove (max_age , Arguments ));
233
+ stream_arguments (Acc ,
234
+ #{stream_max_segment_size_bytes := Value } = Arguments ) ->
235
+ stream_arguments (maps :put (<<" stream-max-segment-size-bytes" >>,
236
+ parse_information_unit (Value ), Acc ),
237
+ maps :remove (stream_max_segment_size_bytes , Arguments ));
238
+ stream_arguments (Acc , #{initial_cluster_size := Value } = Arguments ) ->
239
+ stream_arguments (maps :put (<<" initial-cluster-size" >>,
240
+ rabbit_data_coercion :to_binary (Value ), Acc ),
241
+ maps :remove (initial_cluster_size , Arguments ));
242
+ stream_arguments (Acc , #{leader_locator := Value } = Arguments ) ->
243
+ stream_arguments (maps :put (<<" queue-leader-locator" >>, Value , Acc ),
244
+ maps :remove (leader_locator , Arguments ));
245
+ stream_arguments (ArgumentsAcc , _Arguments ) ->
246
+ ArgumentsAcc .
247
+
248
+ duration_to_seconds ([{sign , _ },
249
+ {years , Y },
250
+ {months , M },
251
+ {days , D },
252
+ {hours , H },
253
+ {minutes , Mn },
254
+ {seconds , S }]) ->
255
+ Y * 365 * 86400 + M * 30 * 86400 + D * 86400 + H * 3600 + Mn * 60 + S .
256
+
126
257
create_super_stream (NodeName ,
127
258
Timeout ,
128
259
VHost ,
129
260
SuperStream ,
130
261
Streams ,
262
+ Arguments ,
131
263
RoutingKeys ) ->
132
264
case rabbit_misc :rpc_call (NodeName ,
133
265
rabbit_stream_manager ,
134
266
create_super_stream ,
135
267
[VHost ,
136
268
SuperStream ,
137
269
Streams ,
138
- [] ,
270
+ Arguments ,
139
271
RoutingKeys ,
140
272
cli_acting_user ()],
141
273
Timeout )
@@ -149,7 +281,7 @@ create_super_stream(NodeName,
149
281
end .
150
282
151
283
banner (_ , _ ) ->
152
- <<" Adding a super stream ..." >>.
284
+ <<" Adding a super stream (experimental feature) ..." >>.
153
285
154
286
output ({error , Msg }, _Opts ) ->
155
287
{error , 'Elixir.RabbitMQ.CLI.Core.ExitCodes' :exit_software (), Msg };
@@ -158,3 +290,11 @@ output({ok, Msg}, _Opts) ->
158
290
159
291
cli_acting_user () ->
160
292
'Elixir.RabbitMQ.CLI.Core.Helpers' :cli_acting_user ().
293
+
294
+ parse_information_unit (Value ) ->
295
+ case rabbit_resource_monitor_misc :parse_information_unit (Value ) of
296
+ {ok , R } ->
297
+ integer_to_binary (R );
298
+ {error , _ } ->
299
+ error
300
+ end .
0 commit comments