43
43
init /1 ,
44
44
apply /3 ,
45
45
live_indexes /1 ,
46
+ snapshot_installed /4 ,
46
47
state_enter /2 ,
47
48
tick /2 ,
48
49
overview /1 ,
@@ -487,7 +488,8 @@ apply(#{index := Idx} = Meta,
487
488
apply (#{index := Index }, # purge {},
488
489
#? STATE {messages_total = Total ,
489
490
returns = Returns ,
490
- ra_indexes = Indexes0
491
+ ra_indexes = Indexes0 ,
492
+ msg_bytes_enqueue = MsgBytesEnqueue
491
493
} = State0 ) ->
492
494
NumReady = messages_ready (State0 ),
493
495
Indexes = case Total of
@@ -514,7 +516,9 @@ apply(#{index := Index}, #purge{},
514
516
returns = lqueue :new (),
515
517
msg_bytes_enqueue = 0
516
518
},
517
- Effects0 = [{aux , force_checkpoint }, garbage_collection ],
519
+ Effects0 = [{aux , {bytes_out , MsgBytesEnqueue }},
520
+ {aux , force_checkpoint },
521
+ garbage_collection ],
518
522
Reply = {purge , NumReady },
519
523
{State , _ , Effects } = evaluate_limit (Index , false , State0 ,
520
524
State1 , Effects0 ),
@@ -681,14 +685,56 @@ apply(_Meta, Cmd, State) ->
681
685
? LOG_DEBUG (" rabbit_fifo: unhandled command ~W " , [Cmd , 10 ]),
682
686
{State , ok , []}.
683
687
684
- -spec live_indexes (state ()) ->
685
- [ ra : index ()].
686
- live_indexes (# ? STATE { returns = Returns ,
688
+ -spec live_indexes (state ()) -> [ ra : index ()].
689
+ live_indexes (# ? STATE { cfg = # cfg {},
690
+ returns = Returns ,
687
691
messages = Messages ,
692
+ ra_indexes = Indexes ,
688
693
dlx = Dlx }) ->
689
694
DlxIndexes = rabbit_fifo_dlx :live_indexes (Dlx ),
690
695
RtnIndexes = [I || ? MSG (I , _ ) <- lqueue :to_list (Returns )],
691
- DlxIndexes ++ RtnIndexes ++ rabbit_fifo_q :indexes (Messages ).
696
+ CheckedIdxs = rabbit_fifo_index :indexes (Indexes ),
697
+ CheckedIdxs ++
698
+ DlxIndexes ++
699
+ RtnIndexes ++
700
+ rabbit_fifo_q :indexes (Messages ).
701
+
702
+
703
+ -spec snapshot_installed (Meta , State , OldMeta , OldState ) ->
704
+ ra_machine :effects () when
705
+ Meta :: ra_snapshot :meta (),
706
+ State :: state (),
707
+ OldMeta :: ra_snapshot :meta (),
708
+ OldState :: state ().
709
+ snapshot_installed (_Meta , #? MODULE {cfg = # cfg {resource = QR },
710
+ consumers = Consumers } = State ,
711
+ _OldMeta , _OldState ) ->
712
+ % % here we need to redliver all pending consumer messages
713
+ % % to local consumers
714
+ % % TODO: with some additional state (raft indexes assigned to consumer)
715
+ % % we could reduce the number of resends but it is questionable if this
716
+ % % complexity is worth the effort. rabbit_fifo_index will de-duplicate
717
+ % % deliveries anyway
718
+ SendAcc = maps :fold (
719
+ fun (_ConsumerKey , # consumer {cfg = # consumer_cfg {tag = Tag ,
720
+ pid = Pid },
721
+ checked_out = Checked },
722
+ Acc ) ->
723
+ case node (Pid ) == node () of
724
+ true ->
725
+ Acc #{{Tag , Pid } => maps :to_list (Checked )};
726
+ false ->
727
+ Acc
728
+ end
729
+ end , #{}, Consumers ),
730
+ ? LOG_DEBUG (" ~ts : rabbit_fifo: install snapshot sending ~p " ,
731
+ [rabbit_misc :rs (QR ), SendAcc ]),
732
+ Effs = add_delivery_effects ([], SendAcc , State ),
733
+ ? LOG_DEBUG (" ~ts : rabbit_fifo: effs ~p " ,
734
+ [rabbit_misc :rs (QR ), Effs ]),
735
+ Effs .
736
+
737
+
692
738
693
739
convert_v3_to_v4 (#{} = _Meta , StateV3 ) ->
694
740
% % TODO: consider emitting release cursors as checkpoints
@@ -965,7 +1011,7 @@ which_module(8) -> ?MODULE.
965
1011
-record (snapshot , {index :: ra :index (),
966
1012
timestamp :: milliseconds (),
967
1013
% smallest_index :: undefined | ra:index(),
968
- messages_total :: non_neg_integer (),
1014
+ messages_total = 0 :: non_neg_integer (),
969
1015
% indexes = ?CHECK_MIN_INDEXES :: non_neg_integer(),
970
1016
bytes_out = 0 :: non_neg_integer ()}).
971
1017
-record (aux_gc , {last_raft_idx = 0 :: ra :index ()}).
@@ -990,10 +1036,9 @@ init_aux(Name) when is_atom(Name) ->
990
1036
Now = erlang :monotonic_time (microsecond ),
991
1037
#? AUX {name = Name ,
992
1038
capacity = {inactive , Now , 1 , 1.0 },
993
- last_checkpoint = # snapshot {index = 0 ,
994
- timestamp = erlang :system_time (millisecond ),
995
- messages_total = 0 ,
996
- bytes_out = 0 }}.
1039
+ last_checkpoint = # checkpoint {index = 0 ,
1040
+ timestamp = erlang :system_time (millisecond ),
1041
+ messages_total = 0 }}.
997
1042
998
1043
handle_aux (RaftState , Tag , Cmd , # aux {name = Name ,
999
1044
capacity = Cap ,
@@ -1018,7 +1063,13 @@ handle_aux(leader, cast, eval,
1018
1063
ra_aux :machine_state (RaAux ),
1019
1064
1020
1065
Ts = erlang :system_time (millisecond ),
1021
- EffMacVer = ra_aux :effective_machine_version (RaAux ),
1066
+ EffMacVer = try ra_aux :effective_machine_version (RaAux ) of
1067
+ V -> V
1068
+ catch _ :_ ->
1069
+ % % this function is not available in older aux states.
1070
+ % % this is a guess
1071
+ undefined
1072
+ end ,
1022
1073
{Check , Effects0 } = do_checkpoints (EffMacVer , Ts , Check0 , RaAux ,
1023
1074
BytesIn , BytesOut , false ),
1024
1075
@@ -1834,7 +1885,7 @@ complete(Meta, ConsumerKey, [MsgId],
1834
1885
{State1 #? STATE {ra_indexes = Indexes ,
1835
1886
msg_bytes_checkout = BytesCheckout - SettledSize ,
1836
1887
messages_total = Tot - 1 },
1837
- [{aux , {bytes_out , SettledSize }}, Effects ]};
1888
+ [{aux , {bytes_out , SettledSize }} | Effects ]};
1838
1889
error ->
1839
1890
{State0 , Effects }
1840
1891
end ;
@@ -1861,7 +1912,7 @@ complete(Meta, ConsumerKey, MsgIds,
1861
1912
{State1 #? STATE {ra_indexes = Indexes ,
1862
1913
msg_bytes_checkout = BytesCheckout - SettledSize ,
1863
1914
messages_total = Tot - Len },
1864
- [{aux , {bytes_out , SettledSize }}, Effects ]}.
1915
+ [{aux , {bytes_out , SettledSize }} | Effects ]}.
1865
1916
1866
1917
increase_credit (# consumer {cfg = # consumer_cfg {lifetime = once },
1867
1918
credit = Credit }, _ ) ->
@@ -3025,29 +3076,34 @@ priority_tag(Msg) ->
3025
3076
no
3026
3077
end .
3027
3078
3028
-
3029
- do_checkpoints (MacVer , Ts , # checkpoint {index = _ChIdx ,
3030
- timestamp = _SnapTime },
3031
- RaAux , BytesIn , BytesOut , Force ) when MacVer >= 8 ->
3032
- do_checkpoints (MacVer , Ts , # snapshot {}, RaAux , BytesIn , BytesOut , Force );
3079
+ do_checkpoints (MacVer , Ts , # checkpoint {timestamp = LastTs ,
3080
+ index = Idx },
3081
+ RaAux , BytesIn , BytesOut , Force )
3082
+ when is_integer (MacVer ) andalso MacVer >= 8 ->
3083
+ do_checkpoints (MacVer , Ts , # snapshot {index = Idx ,
3084
+ timestamp = LastTs }, RaAux , BytesIn ,
3085
+ BytesOut , Force );
3033
3086
do_checkpoints (MacVer , Ts , # snapshot {index = _ChIdx ,
3034
- timestamp = SnapTime ,
3035
- bytes_out = LastBytesOut } = Snap0 ,
3036
- RaAux , _BytesIn , BytesOut , _Force ) when MacVer >= 8 ->
3087
+ timestamp = SnapTime ,
3088
+ bytes_out = LastBytesOut } = Snap0 ,
3089
+ RaAux , _BytesIn , BytesOut , Force )
3090
+ when is_integer (MacVer ) andalso MacVer >= 8 ->
3037
3091
LastAppliedIdx = ra_aux :last_applied (RaAux ),
3038
3092
#? STATE {} = MacState = ra_aux :machine_state (RaAux ),
3039
3093
TimeSince = Ts - SnapTime ,
3040
3094
MsgsTot = messages_total (MacState ),
3041
- ra_aux :overview (RaAux ),
3095
+ % ra_aux:overview(RaAux),
3042
3096
% MaxBytesFactor = max(1, MsgsTot / CheckMaxIndexes),
3097
+ % TODO: snapshots also need to be triggered by non settled commands
3098
+ % that aren't enqueues
3043
3099
EnoughDataRemoved = BytesOut - LastBytesOut > ? SNAP_OUT_BYTES ,
3044
3100
{CheckMinInterval , _CheckMinIndexes , _CheckMaxIndexes } =
3045
3101
persistent_term :get (quorum_queue_checkpoint_config ,
3046
3102
{? CHECK_MIN_INTERVAL_MS , ? CHECK_MIN_INDEXES ,
3047
3103
? CHECK_MAX_INDEXES }),
3048
3104
EnoughTimeHasPassed = TimeSince > CheckMinInterval ,
3049
- case (EnoughTimeHasPassed andalso
3050
- EnoughDataRemoved ) of
3105
+ case (EnoughTimeHasPassed andalso EnoughDataRemoved ) orelse
3106
+ Force of
3051
3107
true ->
3052
3108
{# snapshot {index = LastAppliedIdx ,
3053
3109
timestamp = Ts ,
@@ -3062,7 +3118,8 @@ do_checkpoints(MacVer,Ts, #checkpoint{index = ChIdx,
3062
3118
smallest_index = LastSmallest ,
3063
3119
bytes_in = LastBytesIn ,
3064
3120
indexes = MinIndexes } = Check0 ,
3065
- RaAux , BytesIn , _BytesOut , Force ) when MacVer < 8 ->
3121
+ RaAux , BytesIn , _BytesOut , Force )
3122
+ when not is_integer (MacVer ) orelse MacVer < 8 ->
3066
3123
LastAppliedIdx = ra_aux :last_applied (RaAux ),
3067
3124
IndexesSince = LastAppliedIdx - ChIdx ,
3068
3125
#? STATE {} = MacState = ra_aux :machine_state (RaAux ),
0 commit comments