Flux.switchOnNext variant that switches when the next publisher _emits_ rather than when it _is emitted_ - project-reactor

Reactor has the switchOnNext operator which mirrors a sequence of publishers, cancelling the previous subscription whenever a new publisher becomes available:
For my use case I need a variation on this theme, where instead of cancelling the first publisher before subscribing to the next, I continue to mirror the sequence of publisher 1 until the point when publisher 2 emits its first item, and only then make the switch, as in this marble diagram (for anyone who finds this question later this is not a diagram of an existing operator from the Reactor docs, it's one I've just sketched myself):
I appreciate that in the general case this could potentially involve the operator maintaining an unbounded number of subscriptions waiting for any one of them to emit before cancelling the others, but for my use case I know that the initial flux-of-fluxes is finite (so I don't necessarily need the fully general publisher-of-publishers solution, something that works for a finite list of N publishers would be sufficient).
Can anyone see a clever combination of the existing operators that would implement this behaviour or do I need to write it from first principles?

Interesting problem! I think something like this might work:
#Test
void switchOnNextEmit() {
Duration gracePeriod = Duration.ofSeconds(2);
Flux.concat(
Mono.just(sequence("a", 1)),
Mono.just(sequence("b", 3)).delaySubscription(Duration.ofSeconds(5)),
Mono.just(sequence("c", 10)).delaySubscription(Duration.ofSeconds(10)))
.map(seq -> seq.publish().refCount(1, gracePeriod))
.scan(
Tuples.of(Flux.<String>never(), Flux.<String>never()),
(acc, next) -> Tuples.of(acc.getT2().takeUntilOther(next), next))
.switchMap(t -> Flux.merge(t.getT1(), t.getT2()))
.doOnNext(it -> System.out.println("Result: " + it))
.then()
.block();
}
private static Flux<String> sequence(String name, int interval) {
return Flux.interval(Duration.ofSeconds(interval))
.map(i -> name + i)
.doOnSubscribe(__ -> System.out.println("Subscribe: " + name))
.doOnCancel(() -> System.out.println("Cancel: " + name));
}
The important part is that we convert the sequences into hot publishers (meaning that resubscribing them doesn't cause another subscription, rather than we share the initial subscription). Then we use scan to emit a tuple containing the previous and the next, and finally we just use a regular switchMap to observe both (note how the first will stop when the second emits, due to takeUntilOther).
Note that the grace period is important because switchMap will first cancel and then subscribe the next, so if there isn't any grace period it would cause the current hot publisher to fully stop and start from scratch, which is not what we want.

Related

doAfterSuccessOrError and doOnSuccess not called in order if there is intermediate operators

I'm using reactor-core 3.2.10.RELEASE. By default the doAfterSuccessOrError should be called after doOnSuccess called. But if I add then or publishOn operators it seems that it creates an inner Mono and the order of the doXXX changes.
Is this an intended behavior?
Mono.just(1)
.doAfterTerminate(() -> System.out.println("Terminated"))
.doAfterSuccessOrError((i, e) -> System.out.println("AfterSuccessOrError: " + i))
// Uncommenting any of these will change the order to
// .then(Mono.empty())
// .then()
// .publishOn(Schedulers.elastic())
.doFinally(s -> System.out.println("Finally called"))
.doOnSuccess(s -> System.out.println("Success"))
.subscribe(i -> System.out.println("Result: " + i));
Expected output:
Success
Result: 1
AfterSuccessOrError: 1
Terminated
Finally called
After uncommenting then or publishOn the order changes.
AfterSuccessOrError: 1
Terminated
Success
Result: 1
Finally called
Is this an intended behavior?
Yes. As per the docs for `then():
Let this Mono complete then play another Mono.
...so in this case, it's because the Mono up until that point completes (hence the first two operators print), and then the output from your next Mono prints (the final 3 operators).
For publishOn(), it's slightly different:
This operator influences the threading context where the rest of the operators in the chain below it will execute, up to a new occurrence of publishOn.
This means that you have your first two operators executing on one thread, and then the rest of your operators executing on a separate thread (defined by the elastic scheduler) - which is why you see the output. The mechanism is different here, but the end result happens to be exactly the same.

Restricting number of function iterations

I'm writing a code in Erlang which suppose to generate a random number for a random amount of time and add each number to a list. I managed a function which can generate random numbers and i kinda managed a method for adding it to a list,but my main problem is restricting the number of iterations of the function. I like the function to produce several numbers and add them to the list and then kill that process or something like that.
Here is my code so far:
generator(L1)->
random:seed(now()),
A = random:uniform(100),
L2 = lists:append(L1,A),
generator(L2),
producer(B,L) ->
receive
{last_element} ->
consumer ! {lists:droplast(B)}
end
consumer()->
timer:send_after(random:uniform(1000),producer,{last_element,self()}),
receive
{Answer, Producer_PID} ->
io:format("the last item is:~w~n",[Answer])
end,
consumer().
start() ->
register(consumer,spawn(lis,consumer,[])),
register(producer,spawn(lis,producer,[])),
register(generator,spawn(lis,generator,[random:uniform(10)])).
I know it's a little bit sloppy and incomplete but that's not the case.
First, you should use rand to generate random numbers instead of random, it is an improved module.
In addition, when using rand:uniform/1 you won't need to change the seed every time you run your program. From erlang documentation:
If a process calls uniform/0 or uniform/1 without setting a seed
first, seed/1 is called automatically with the default algorithm and
creates a non-constant seed.
Finally, in order to create a list of random numbers, take a look at How to create a list of 1000 random number in erlang.
If I conclude all this, you can just do:
[rand:uniform(100) || _ <- lists:seq(1, 1000)].
There have some issue in your code:
timer:send_after(random:uniform(1000),producer,{last_element,self()}),, you send {last_element,self()} to producer process, but in producer, you just receive {last_element}, these messages are not matched.
you can change
producer(B,L) ->
receive
{last_element} ->
consumer ! {lists:droplast(B)}
end.
to
producer(B,L) ->
receive
{last_element, FromPid} ->
FromPid! {lists:droplast(B)}
end.
the same reason for consumer ! {lists:droplast(B)} and {Answer, Producer_PID} ->.

Erlang Dialyzer: only accept certain integers?

Say I have a function,foo/1, whose spec is -spec foo(atom()) -> #r{}., where #r{} is a record defined as -record(r, {a :: 1..789})., however, I have foo(a) -> 800. in my code, when I run dialyzer against it, it didn't warn me about this, (800 is not a "valid" return value for function foo/1), can I make dialyzer warn me about this?
Edit
Learn You Some Erlang says:
Dialyzer reserves the right to expand this range into a bigger one.
But I couldn't find how to disable this.
As of Erlang 18, the handling of integer ranges is done by erl_types:t_from_range/2. As you can see, there are a lot of generalizations happening to get a "safe" overapproximation of a range.
If you tried to ?USE_UNSAFE_RANGES (see the code) it is likely that your particular error would be caught, but at a terrible cost: native compilation and dialyzing of recursive integer functions would not ever finish!
The reason is that the type analysis for recursive functions uses a simple fixpoint approach, where the initial types accept the base cases and are repeatedly expanded using the recursive cases to include more values. At some point overapproximations must happen if the process is to terminate. Here is a concrete example:
fact(1) -> 1;
fact(N) -> N * fact(N - 1).
Initially fact/1 is assumed to have type fun(none()) -> none(). Using that to analyse the code, the second clause is 'failing' and only the first one is ok. Therefore after the first iteration the new type is fun(1) -> 1. Using the new type the second clause can succeed, expanding the type to fun(1|2) -> 1|2. Then fun(1|2|3) -> 1|2|6 this continues until the ?SET_LIMIT is reached in which case t_from_range stops using the individual values and type becomes fun(1..255) -> pos_integer(). The next iteration expands 1..255 to pos_integer() and then fun(pos_integer()) -> pos_integer() is a fixpoint!
Incorrect answer follows (explains the first comment below):
You should get a warning for this code if you use the -Woverspecs option. This option is not enabled by default, since Dialyzer operates under the assumption that it is 'ok' to over-approximate the return values of a function. In your particular case, however, you actually want any extra values to produce warnings.

Spawn many processes erlang

I wanna measure the performance to my database by measuring the time taken to do something as the number of processes increase. The intention is to plot a graph of performance vs number of processes after, anyone has an idea how? i am a beginner in elrlang please helo
Assuming your database is mnesia, this should not be hard. one way would be to have a write function and a read function. However, note that there are several Activity access contexts with mnesia. To test write times, you should NOT use the context of transaction because it returns immediately to the calling process, even before a disc write has occured. However, for disc writes, its important that you look at the context called: sync_transaction. Here is an example:
write(Record)->
Fun = fun(R)-> mnesia:write(R) end,
mnesia:activity(sync_transaction,Fun,[Record],mnesia_frag).
The function above will return only when all active replicas of the mnesia table have committed the record onto the data disc file. Hence to test the speed as processes increase, you need to have a record generator,a a process spawner , the write function and finally a timing mechanism. For timing, we have a built in function called: timer:tc/1, timer:tc/2 and timer:tc/3 which returns the exact time it took to execute (completely) a given function. To cut the story short, this is how i would do this:
-module(stress_test).
-compile(export_all).
-define(LIMIT,10000).
-record(book,{
isbn,
title,
price,
version}).
%% ensure this table is {type,bag}
-record(write_time,{
isbn,
num_of_processes,
write_time
}).
%% Assuming table (book) already exists
%% Assuming mnesia running already
start()->
ensure_gproc(),
tv:start(),
spawn_many(?LIMIT).
spawn_many(0)-> ok;
spawn_many(N)->
spawn(?MODULE,process,[]),
spawn_many(N - 1).
process()->
gproc:reg({n, l,guid()},ignored),
timer:apply_interval(timer:seconds(2),?MODULE,write,[]),
receive
<<"stop">> -> exit(normal)
end.
total_processes()->
proplists:get_value(size,ets:info(gproc)) div 3.
ensure_gproc()->
case lists:keymember(gproc,1,application:which_applications()) of
true -> ok;
false -> application:start(gproc)
end.
guid()->
random:seed(now()),
MD5 = erlang:md5(term_to_binary([random:uniform(152629977),{node(), now(), make_ref()}])),
MD5List = lists:nthtail(3, binary_to_list(MD5)),
F = fun(N) -> f("~2.16.0B", [N]) end,
L = [F(N) || N <- MD5List],
lists:flatten(L).
generate_record()->
#book{isbn = guid(),title = guid(),price = guid()}.
write()->
Record = generate_record(),
Fun = fun(R)-> ok = mnesia:write(R),ok end,
%% Here is now the actual write we measure
{Time,ok} = timer:tc(mnesia,activity,[sync_transaction,Fun,[Record],mnesia_frag]),
%% The we save that time, the number of processes
%% at that instant
NoteTime = #write_time{
isbn = Record#book.isbn,
num_of_processes = total_processes(),
write_time = Time
},
mnesia:activity(transaction,Fun,[NoteTime],mnesia_frag).
Now there are dependencies here, especially: gproc download and build it into your erlang lib path from here Download Gproc.To run this, just call: stress_test:start(). The table write_time will help you draw a graph of number of processes against time taken to write. As the number of processes increase from 0 to the upper limit (?LIMIT), we note the time taken to write a given record at the given instant and we also note the number of processes at that time.UPDATE
f(S)-> f(S,[]).
f(S,Args) -> lists:flatten(io_lib:format(S, Args)).
That is the missing function. Apologies.... Remember to study the table write_time, using the application tv, a window is opened in which you can examine the mnesia tables. Use this table to see increasing write times/ or decreasing performance as number of processes increase from time to time. An element i have left out is to note the actual time of the write action using time() which may be important parameter. You may add it in the table definition of the write_time table.
Also look at http://wiki.basho.com/Benchmarking.html
you might look at tsung http://tsung.erlang-projects.org/

Is it necessary to invent IDs for wxErlang widgets?

I've been poking around with Erlang's wx module and this tutorial. I haven't used wxwidgets before, so maybe this is just how it's done, but this code seems really terrible to me:
%% create widgets
T1001 = wxTextCtrl:new(Panel, 1001,[]),
ST2001 = wxStaticText:new(Panel, 2001,"Output Area", []),
B101 = wxButton:new(Panel, 101, [{label, "&Countdown"}]),
B102 = wxButton:new(Panel, ?wxID_EXIT, [{label, "E&xit"}]),
wxFrame:show(Frame),
Do people really have to assign widget IDs to widgets when creating them? Is it normal to name the variable that points to the widget after the widget's ID?
I don't know about Erlang but in C++ (and in the other bindings I know about) it's often preferable to use wxID_ANY as the widget id, meaning that you don't care about its specific value, and then use Connect() to handle events from the widget. Explicit ids may be convenient if you need to find the widget by its id later (although you can also use widget names for this) or if you need a consecutive range for ids (e.g. it would make sense to use ids 100, 101, ..., 109 for the buttons of a calculator as you could then easily deduce each buttons value from its id) but there is no need to always use them.
As for the naming, there is, of course, no need to use this strange convention (and a quick look at the tutorial shows that it's a personal preference of the author -- which, needless to say, I don't share).
Like VZ mentioned above, you can use wxID_ANY if you won't need to lookup a widget by its id later.
However, I believe that not only it's not normal to name the variables after the ids, but rather it's a very bad idea to do so. Name your variables according to their meaning and not using some obscure id.
Also, you'd better define the ids you need and give them proper (semantic) names, so that they are defined in only one place and you can later easily change the ids without affecting your program at all, like this:
-define(ID_TEXT_CTRL, 1001).
-define(ID_OUTPUT_AREA, 2001).
-define(ID_COUNTDOWN_BUTTON, 101).
-define(ID_EXIT_BUTTON, ?wxID_EXIT).
TextCtrl = wxTextCtrl:new(Panel, ?ID_TEXT_CTRL,[]),
OutputArea = wxStaticText:new(Panel, ?ID_OUTPUT_AREA,"Output Area", []),
CountdownButton = wxButton:new(Panel, ?ID_COUNTDOWN_BUTTON, [{label, "&Countdown"}]),
ExitButton = wxButton:new(Panel, ?ID_EXIT_BUTTON, [{label, "E&xit"}])
You may put the definitions either in your .erl file, if it's only one, or in an .hrl file, which you'll have to include in all your GUI-related .erl files.
No. The cases in which you would want to look something up by ID are roughly the same cases in which you would want to look something up by ID in C++. This applies across any widget library I can think of -- every time you react to a signal coded some_standard_button_name and matches a label like ?wxID_OK you are waiting for a numeric ID that is represented by a label hidden by a macro. Most GUI libraries do a lot of preprocessing to wash this out, so often you don't notice it (in the case of sooper-dooper libraries like Qt its still going on, just in the background, and all of your code is run through a precompiler before it becomes "real" C++...).
So how do you get a hold of a wx thingy that's been created? By using its returned reference.
Almost every wx*:new() call returns an object reference[note1]. This is an abstract reference (internally a tuple, but don't count on that) with enough information for the Erlang bindings and the Wx system processes to talk unambiguously about specific Wx objects that have been created. Passing these references around is the typical way of accessing Wx objects later on:
GridSz = wxFlexGridSizer:new(2, 2, 4, 4),
ok = wxFlexGridSizer:setFlexibleDirection(GridSz, ?wxHORIZONTAL),
ok = wxFlexGridSizer:addGrowableCol(GridSz, 1),
A less obvious case, though, is when you want something like a grid of input fields that you can cycle through or pull by key value:
Scripts = [katakana, hiragana, kanji, latin],
Ilks = [family, given, middle, maiden],
Rows = [{Tag, j(J, Tag)} || Tag <- Scripts],
Cols = [{Tag, j(J, Tag)} || Tag <- Ilks],
{GridSz, Fields} = zxw:text_input_grid(Dialog, Rows, Cols),
% Later on, extracting only present values as
Keys = [{S, I} || S <- Scripts, I <- Ilks],
Extract =
fun(Key, Acc) ->
case wxTextCtrl:getValue(proplists:get_value(Key, Fields)) of
"" -> Acc;
Val -> [{Key, Val} | Acc]
end
end,
NewParts = lists:foldl(Extract, [], Keys),
And so on. (zxw:text_input_grid/3 definition, and docs)
The one time you really do want to reference an object by its ID and not its object reference is the same as in C++: when you are listening for a specific click event:
{AddressPicker, _, _, AddressSz} =
zxw:list_picker(Frame,
?widgetADDRESS, ?addADDRESS, ?delADDRESS,
AddressHeader, Addresses, j(J, address)),
And then later in the message handling loop of the generic wx_object:
handle_event(Wx = #wx{id = Id,
event = #wxCommand{type = command_button_clicked}},
State) ->
case Id of
?editNAME -> {noreply, edit_name(State)};
?editDOB -> {noreply, edit_dob(State)};
?editPORTRAIT -> {noreply, edit_portrait(State)};
?addCONTACT -> {noreply, add_contact_info(State)};
?delCONTACT -> {noreply, del_contact_info(State)};
?addADDRESS -> {noreply, add_address_info(State)};
?delADDRESS -> {noreply, del_address_info(State)};
_ ->
ok = unexpected(Wx),
{noreply, State}
end;
handle_event(Wx = #wx{id = Id,
event = #wxList{type = command_list_item_selected,
itemIndex = Index}},
State) ->
case Id of
?widgetCONTACT -> {noreply, update_selection(contact, Index, State)};
?widgetADDRESS -> {noreply, update_selection(address, Index, State)};
_ ->
ok = unexpected(Wx),
{noreply, State}
end;
The first clause deals specifically with clicks on non-standard buttons, and the second with list-control widget selection events to do some arbitrary things in the interface. While unwrapping the #wx{} event record isn't very visually appealing, using matching in clause formation makes this GUI code much easier to understand during maintenance than the gigantic cascade of checks, exception catches and follow-on if elif elif elif elif..., switch or case..break, etc. type code necessary in languages that lack matching.
In the above case all the specific IDs are labeled as macros, exactly the same way this is done in Wx in C++ and other C++ widget kits. Most of the time your needs are served simply by using the standard pre-defined Wx button types and reacting to them accordingly; the example above is from code that is forced to dive a bit below that because of some specific interface requirements (and the equivalent C++ code winds up essentially the same, but dramatically more verbose to accomplish the same task).
Some platforms in slightly higher level languages have different ways of dealing with the identity issue. iOS and Android widget kits (and QtQuick, for that matter) hide this detail behind something like a slightly more universally useful object reference rather than depending on IDs. That is to say those widget kits essentially store all widgets created in a hash of {ID => ObjReference}, pick the ID out of every signal, retrieve the object reference before passing control to your handling callbacks, and return the reference stored in the hash instead of just passing the ID through directly.
That's slick, but its not the way older widget kits bound to C-style enums-as-labels code work. When its all said and done computers still have only one real type: integers -- we invent all sorts of other stuff on top of this and enjoy the illusion of types and other fun.
We could do this ID-to-reference thing in Erlang also, but the way WxErlang code is typically written is to follow the C++ tradition of using object IDs behind macro labels for events you can't avoid identifying uniquely, and object references and standard labels for everything else.
The zx_widgets library employed above is a set of pre-defined meta-widgets that cover some of the most common cases of boilerplate field construction and return data structures that are easy to handle functionally. The OOP style of Wx isn't a very natural fit for Erlang in some ways (the looooooongest functions you'll ever write in Erlang are likely to be GUI code for this reason), so an extra layer is sometimes necessary to make the logic-bearing code jibe with the rest of Erlang. GUI code is pretty universally annoying, though, in any language and in any environment.
[note1: There are some weird, uncomfortable cases where a few C++-style mysteries leak through the bindings into your Erlang code, such as the magical environment creation procedure involved in using 2D graphics DC canvasses and whatnot.]

Resources