fix(ds): Move responsibility of returning end_of_stream to the CBM
This commit is contained in:
parent
0ff307e789
commit
60edf5e9b8
|
@ -35,7 +35,7 @@
|
||||||
make_iterator/5,
|
make_iterator/5,
|
||||||
make_delete_iterator/5,
|
make_delete_iterator/5,
|
||||||
update_iterator/4,
|
update_iterator/4,
|
||||||
next/5,
|
next/6,
|
||||||
delete_next/6,
|
delete_next/6,
|
||||||
post_creation_actions/1,
|
post_creation_actions/1,
|
||||||
|
|
||||||
|
@ -424,23 +424,21 @@ next(
|
||||||
Schema = #s{ts_offset = TSOffset, ts_bits = TSBits},
|
Schema = #s{ts_offset = TSOffset, ts_bits = TSBits},
|
||||||
It = #{?storage_key := Stream},
|
It = #{?storage_key := Stream},
|
||||||
BatchSize,
|
BatchSize,
|
||||||
Now
|
Now,
|
||||||
|
IsCurrent
|
||||||
) ->
|
) ->
|
||||||
init_counters(),
|
init_counters(),
|
||||||
%% Compute safe cutoff time. It's the point in time where the last
|
%% Compute safe cutoff time. It's the point in time where the last
|
||||||
%% complete epoch ends, so we need to know the current time to
|
%% complete epoch ends, so we need to know the current time to
|
||||||
%% compute it. This is needed because new keys can be added before
|
%% compute it. This is needed because new keys can be added before
|
||||||
%% the iterator.
|
%% the iterator.
|
||||||
IsWildcard =
|
%%
|
||||||
|
%% This is needed to avoid situations when the iterator advances
|
||||||
|
%% to position k1, and then a new message with k2, such that k2 <
|
||||||
|
%% k1 is inserted. k2 would be missed.
|
||||||
|
HasCutoff =
|
||||||
case Stream of
|
case Stream of
|
||||||
{_StaticKey, []} -> false;
|
{_StaticKey, []} ->
|
||||||
_ -> true
|
|
||||||
end,
|
|
||||||
SafeCutoffTime =
|
|
||||||
case IsWildcard of
|
|
||||||
true ->
|
|
||||||
(Now bsr TSOffset) bsl TSOffset;
|
|
||||||
false ->
|
|
||||||
%% Iterators scanning streams without varying topic
|
%% Iterators scanning streams without varying topic
|
||||||
%% levels can operate on incomplete epochs, since new
|
%% levels can operate on incomplete epochs, since new
|
||||||
%% matching keys for the single topic are added in
|
%% matching keys for the single topic are added in
|
||||||
|
@ -450,10 +448,27 @@ next(
|
||||||
%% filters operating on streams with varying parts:
|
%% filters operating on streams with varying parts:
|
||||||
%% iterator can jump to the next topic and then it
|
%% iterator can jump to the next topic and then it
|
||||||
%% won't backtrack.
|
%% won't backtrack.
|
||||||
|
false;
|
||||||
|
_ ->
|
||||||
|
%% New batches are only added to the current
|
||||||
|
%% generation. We can ignore cutoff time for old
|
||||||
|
%% generations:
|
||||||
|
IsCurrent
|
||||||
|
end,
|
||||||
|
SafeCutoffTime =
|
||||||
|
case HasCutoff of
|
||||||
|
true ->
|
||||||
|
(Now bsr TSOffset) bsl TSOffset;
|
||||||
|
false ->
|
||||||
1 bsl TSBits - 1
|
1 bsl TSBits - 1
|
||||||
end,
|
end,
|
||||||
try
|
try
|
||||||
next_until(Schema, It, SafeCutoffTime, BatchSize)
|
case next_until(Schema, It, SafeCutoffTime, BatchSize) of
|
||||||
|
{ok, _, []} when not IsCurrent ->
|
||||||
|
{ok, end_of_stream};
|
||||||
|
Result ->
|
||||||
|
Result
|
||||||
|
end
|
||||||
after
|
after
|
||||||
report_counters(Shard)
|
report_counters(Shard)
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -248,8 +248,8 @@
|
||||||
) ->
|
) ->
|
||||||
emqx_ds:make_delete_iterator_result(_Iterator).
|
emqx_ds:make_delete_iterator_result(_Iterator).
|
||||||
|
|
||||||
-callback next(shard_id(), _Data, Iter, pos_integer(), emqx_ds:time()) ->
|
-callback next(shard_id(), _Data, Iter, pos_integer(), emqx_ds:time(), _IsCurrent :: boolean()) ->
|
||||||
{ok, Iter, [emqx_types:message()]} | {error, _}.
|
{ok, Iter, [emqx_types:message()]} | {ok, end_of_stream} | {error, _}.
|
||||||
|
|
||||||
-callback delete_next(
|
-callback delete_next(
|
||||||
shard_id(), _Data, DeleteIterator, emqx_ds:delete_selector(), pos_integer(), emqx_ds:time()
|
shard_id(), _Data, DeleteIterator, emqx_ds:delete_selector(), pos_integer(), emqx_ds:time()
|
||||||
|
@ -449,15 +449,12 @@ update_iterator(
|
||||||
next(Shard, Iter = #{?tag := ?IT, ?generation := GenId, ?enc := GenIter0}, BatchSize, Now) ->
|
next(Shard, Iter = #{?tag := ?IT, ?generation := GenId, ?enc := GenIter0}, BatchSize, Now) ->
|
||||||
case generation_get(Shard, GenId) of
|
case generation_get(Shard, GenId) of
|
||||||
#{module := Mod, data := GenData} ->
|
#{module := Mod, data := GenData} ->
|
||||||
Current = generation_current(Shard),
|
IsCurrent = GenId =:= generation_current(Shard),
|
||||||
case Mod:next(Shard, GenData, GenIter0, BatchSize, Now) of
|
case Mod:next(Shard, GenData, GenIter0, BatchSize, Now, IsCurrent) of
|
||||||
{ok, _GenIter, []} when GenId < Current ->
|
|
||||||
%% This is a past generation. Storage layer won't write
|
|
||||||
%% any more messages here. The iterator reached the end:
|
|
||||||
%% the stream has been fully replayed.
|
|
||||||
{ok, end_of_stream};
|
|
||||||
{ok, GenIter, Batch} ->
|
{ok, GenIter, Batch} ->
|
||||||
{ok, Iter#{?enc := GenIter}, Batch};
|
{ok, Iter#{?enc := GenIter}, Batch};
|
||||||
|
{ok, end_of_stream} ->
|
||||||
|
{ok, end_of_stream};
|
||||||
Error = {error, _, _} ->
|
Error = {error, _, _} ->
|
||||||
Error
|
Error
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
make_iterator/5,
|
make_iterator/5,
|
||||||
make_delete_iterator/5,
|
make_delete_iterator/5,
|
||||||
update_iterator/4,
|
update_iterator/4,
|
||||||
next/5,
|
next/6,
|
||||||
delete_next/6
|
delete_next/6
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ update_iterator(_Shard, _Data, OldIter, DSKey) ->
|
||||||
last_seen_message_key = DSKey
|
last_seen_message_key = DSKey
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
next(_Shard, #s{db = DB, cf = CF}, It0, BatchSize, _Now) ->
|
next(_Shard, #s{db = DB, cf = CF}, It0, BatchSize, _Now, IsCurrent) ->
|
||||||
#it{topic_filter = TopicFilter, start_time = StartTime, last_seen_message_key = Key0} = It0,
|
#it{topic_filter = TopicFilter, start_time = StartTime, last_seen_message_key = Key0} = It0,
|
||||||
{ok, ITHandle} = rocksdb:iterator(DB, CF, []),
|
{ok, ITHandle} = rocksdb:iterator(DB, CF, []),
|
||||||
Action =
|
Action =
|
||||||
|
@ -162,7 +162,12 @@ next(_Shard, #s{db = DB, cf = CF}, It0, BatchSize, _Now) ->
|
||||||
{Key, Messages} = do_next(TopicFilter, StartTime, ITHandle, Action, BatchSize, Key0, []),
|
{Key, Messages} = do_next(TopicFilter, StartTime, ITHandle, Action, BatchSize, Key0, []),
|
||||||
rocksdb:iterator_close(ITHandle),
|
rocksdb:iterator_close(ITHandle),
|
||||||
It = It0#it{last_seen_message_key = Key},
|
It = It0#it{last_seen_message_key = Key},
|
||||||
{ok, It, lists:reverse(Messages)}.
|
case Messages of
|
||||||
|
[] when not IsCurrent ->
|
||||||
|
{ok, end_of_stream};
|
||||||
|
_ ->
|
||||||
|
{ok, It, lists:reverse(Messages)}
|
||||||
|
end.
|
||||||
|
|
||||||
delete_next(_Shard, #s{db = DB, cf = CF}, It0, Selector, BatchSize, _Now) ->
|
delete_next(_Shard, #s{db = DB, cf = CF}, It0, Selector, BatchSize, _Now) ->
|
||||||
#delete_it{
|
#delete_it{
|
||||||
|
|
Loading…
Reference in New Issue