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,61 @@ 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
+ consumers = Consumers ,
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 = maps :fold (
697
+ fun (_Cid , # consumer {checked_out = Ch }, Acc0 ) ->
698
+ maps :fold (
699
+ fun (_MsgId , ? MSG (I , _ ), Acc ) ->
700
+ [I | Acc ]
701
+ end , Acc0 , Ch )
702
+ end , RtnIndexes ++ DlxIndexes , Consumers ),
703
+
704
+
705
+ CheckedIdxs ++ rabbit_fifo_q :indexes (Messages ).
706
+
707
+
708
+ -spec snapshot_installed (Meta , State , OldMeta , OldState ) ->
709
+ ra_machine :effects () when
710
+ Meta :: ra_snapshot :meta (),
711
+ State :: state (),
712
+ OldMeta :: ra_snapshot :meta (),
713
+ OldState :: state ().
714
+ snapshot_installed (_Meta , #? MODULE {cfg = # cfg {resource = QR },
715
+ consumers = Consumers } = State ,
716
+ _OldMeta , _OldState ) ->
717
+ % % here we need to redliver all pending consumer messages
718
+ % % to local consumers
719
+ % % TODO: with some additional state (raft indexes assigned to consumer)
720
+ % % we could reduce the number of resends but it is questionable if this
721
+ % % complexity is worth the effort. rabbit_fifo_index will de-duplicate
722
+ % % deliveries anyway
723
+ SendAcc = maps :fold (
724
+ fun (_ConsumerKey , # consumer {cfg = # consumer_cfg {tag = Tag ,
725
+ pid = Pid },
726
+ checked_out = Checked },
727
+ Acc ) ->
728
+ case node (Pid ) == node () of
729
+ true ->
730
+ Acc #{{Tag , Pid } => maps :to_list (Checked )};
731
+ false ->
732
+ Acc
733
+ end
734
+ end , #{}, Consumers ),
735
+ ? LOG_DEBUG (" ~ts : rabbit_fifo: install snapshot sending ~p " ,
736
+ [rabbit_misc :rs (QR ), SendAcc ]),
737
+ Effs = add_delivery_effects ([], SendAcc , State ),
738
+ ? LOG_DEBUG (" ~ts : rabbit_fifo: effs ~p " ,
739
+ [rabbit_misc :rs (QR ), Effs ]),
740
+ Effs .
741
+
742
+
692
743
693
744
convert_v3_to_v4 (#{} = _Meta , StateV3 ) ->
694
745
% % TODO: consider emitting release cursors as checkpoints
@@ -965,7 +1016,7 @@ which_module(8) -> ?MODULE.
965
1016
-record (snapshot , {index :: ra :index (),
966
1017
timestamp :: milliseconds (),
967
1018
% smallest_index :: undefined | ra:index(),
968
- messages_total :: non_neg_integer (),
1019
+ messages_total = 0 :: non_neg_integer (),
969
1020
% indexes = ?CHECK_MIN_INDEXES :: non_neg_integer(),
970
1021
bytes_out = 0 :: non_neg_integer ()}).
971
1022
-record (aux_gc , {last_raft_idx = 0 :: ra :index ()}).
@@ -990,10 +1041,9 @@ init_aux(Name) when is_atom(Name) ->
990
1041
Now = erlang :monotonic_time (microsecond ),
991
1042
#? AUX {name = Name ,
992
1043
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 }}.
1044
+ last_checkpoint = # checkpoint {index = 0 ,
1045
+ timestamp = erlang :system_time (millisecond ),
1046
+ messages_total = 0 }}.
997
1047
998
1048
handle_aux (RaftState , Tag , Cmd , # aux {name = Name ,
999
1049
capacity = Cap ,
@@ -1018,7 +1068,13 @@ handle_aux(leader, cast, eval,
1018
1068
ra_aux :machine_state (RaAux ),
1019
1069
1020
1070
Ts = erlang :system_time (millisecond ),
1021
- EffMacVer = ra_aux :effective_machine_version (RaAux ),
1071
+ EffMacVer = try ra_aux :effective_machine_version (RaAux ) of
1072
+ V -> V
1073
+ catch _ :_ ->
1074
+ % % this function is not available in older aux states.
1075
+ % % this is a guess
1076
+ undefined
1077
+ end ,
1022
1078
{Check , Effects0 } = do_checkpoints (EffMacVer , Ts , Check0 , RaAux ,
1023
1079
BytesIn , BytesOut , false ),
1024
1080
@@ -1834,7 +1890,7 @@ complete(Meta, ConsumerKey, [MsgId],
1834
1890
{State1 #? STATE {ra_indexes = Indexes ,
1835
1891
msg_bytes_checkout = BytesCheckout - SettledSize ,
1836
1892
messages_total = Tot - 1 },
1837
- [{aux , {bytes_out , SettledSize }}, Effects ]};
1893
+ [{aux , {bytes_out , SettledSize }} | Effects ]};
1838
1894
error ->
1839
1895
{State0 , Effects }
1840
1896
end ;
@@ -1861,7 +1917,7 @@ complete(Meta, ConsumerKey, MsgIds,
1861
1917
{State1 #? STATE {ra_indexes = Indexes ,
1862
1918
msg_bytes_checkout = BytesCheckout - SettledSize ,
1863
1919
messages_total = Tot - Len },
1864
- [{aux , {bytes_out , SettledSize }}, Effects ]}.
1920
+ [{aux , {bytes_out , SettledSize }} | Effects ]}.
1865
1921
1866
1922
increase_credit (# consumer {cfg = # consumer_cfg {lifetime = once },
1867
1923
credit = Credit }, _ ) ->
@@ -3025,29 +3081,34 @@ priority_tag(Msg) ->
3025
3081
no
3026
3082
end .
3027
3083
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 );
3084
+ do_checkpoints (MacVer , Ts , # checkpoint {timestamp = LastTs ,
3085
+ index = Idx },
3086
+ RaAux , BytesIn , BytesOut , Force )
3087
+ when is_integer (MacVer ) andalso MacVer >= 8 ->
3088
+ do_checkpoints (MacVer , Ts , # snapshot {index = Idx ,
3089
+ timestamp = LastTs }, RaAux , BytesIn ,
3090
+ BytesOut , Force );
3033
3091
do_checkpoints (MacVer , Ts , # snapshot {index = _ChIdx ,
3034
- timestamp = SnapTime ,
3035
- bytes_out = LastBytesOut } = Snap0 ,
3036
- RaAux , _BytesIn , BytesOut , _Force ) when MacVer >= 8 ->
3092
+ timestamp = SnapTime ,
3093
+ bytes_out = LastBytesOut } = Snap0 ,
3094
+ RaAux , _BytesIn , BytesOut , Force )
3095
+ when is_integer (MacVer ) andalso MacVer >= 8 ->
3037
3096
LastAppliedIdx = ra_aux :last_applied (RaAux ),
3038
3097
#? STATE {} = MacState = ra_aux :machine_state (RaAux ),
3039
3098
TimeSince = Ts - SnapTime ,
3040
3099
MsgsTot = messages_total (MacState ),
3041
- ra_aux :overview (RaAux ),
3100
+ % ra_aux:overview(RaAux),
3042
3101
% MaxBytesFactor = max(1, MsgsTot / CheckMaxIndexes),
3102
+ % TODO: snapshots also need to be triggered by non settled commands
3103
+ % that aren't enqueues
3043
3104
EnoughDataRemoved = BytesOut - LastBytesOut > ? SNAP_OUT_BYTES ,
3044
3105
{CheckMinInterval , _CheckMinIndexes , _CheckMaxIndexes } =
3045
3106
persistent_term :get (quorum_queue_checkpoint_config ,
3046
3107
{? CHECK_MIN_INTERVAL_MS , ? CHECK_MIN_INDEXES ,
3047
3108
? CHECK_MAX_INDEXES }),
3048
3109
EnoughTimeHasPassed = TimeSince > CheckMinInterval ,
3049
- case (EnoughTimeHasPassed andalso
3050
- EnoughDataRemoved ) of
3110
+ case (EnoughTimeHasPassed andalso EnoughDataRemoved ) orelse
3111
+ Force of
3051
3112
true ->
3052
3113
{# snapshot {index = LastAppliedIdx ,
3053
3114
timestamp = Ts ,
@@ -3062,7 +3123,8 @@ do_checkpoints(MacVer,Ts, #checkpoint{index = ChIdx,
3062
3123
smallest_index = LastSmallest ,
3063
3124
bytes_in = LastBytesIn ,
3064
3125
indexes = MinIndexes } = Check0 ,
3065
- RaAux , BytesIn , _BytesOut , Force ) when MacVer < 8 ->
3126
+ RaAux , BytesIn , _BytesOut , Force )
3127
+ when not is_integer (MacVer ) orelse MacVer < 8 ->
3066
3128
LastAppliedIdx = ra_aux :last_applied (RaAux ),
3067
3129
IndexesSince = LastAppliedIdx - ChIdx ,
3068
3130
#? STATE {} = MacState = ra_aux :machine_state (RaAux ),
0 commit comments