I ended up in Rx spree, so to speak, and this question is related to mine here and here . However, perhaps they help someone, as I could see them as useful options for the same topic.
Question:. How can one group a random stream of int (say, on the interval [0, 10], created on a random interval) of objects into groups, and provide the earch group with a variable number of no event alarms (due to the lack of a better definition, for further background see related messages ) More specifically, with the code, how can you determine the throttle settings for each group in the following:
var idAlarmStream = idStream .Select(i => i) .GroupByUntil(key => key.Id, grp => grp.Throttle(Timespan.FromMilliseconds(1000)) .SelectMany(grp => grp.TakeLast(1)) .Subscribe(i => Console.WriteLine(i));
Here, the subscription function will be called if there is more than one second per group. What if you want to determine three different values for the absence of events (say, one second, five seconds and ten seconds) and all are canceled when an event arrives? Can I think:
- Divide each identifier in
idStream into several synthetic ones and provide a bijective mapping between real identifiers and synthetic ones. For example, in this case ID: 1 → 100, 101, 102; ID: 2 → 200, 201, 203, and then define the selector function in Throttle , e.g. Func<int, Timespan>(i => /* switch(i)...*/) , and then when Subscribe is called return the id back. See Also Related Questions for more information. - Create a nested group in which identifiers are grouped, and then the identifier groups will be copied / replicated / branched (I don't know the right term) into groups according to the throttling values. This approach, I think, is rather complicated, and I'm not sure if this will be the best. However, I would be interested to see such a request.
In a more general setup, I suspect this is a situation where there are several handlers per group, although I could not find anything related to this.
<editing: As a (hopefully clarifying) example, idStream one ID: 1, on which three different counters will be triggered, each of which waits for the next event or alarm if a new ID 1 is not detected on time. Counter 1 (C1) waits for five seconds, counter 2 (C2) for seven seconds and counter 3 (C3) for ten seconds. If a new ID 1 is received within the interval [0, 5] seconds, all counters will be reinitialized with the above values and no alarm will be sent. If a new identifier is received within the interval [0, 7) seconds, signals C1 and C2 and C3 will be reinitialized. Similarly, if a new identifier is received within a period of [0, 10) seconds C1 and C2, but C3 will simply be reinitialized.
That is, there would be several “no alarms” or actions taken in general with respect to one ID under certain conditions. I’m not sure what would be a good analogue ... Perhaps laying the “signal lights” in the tower so that it was green first, then yellow, and finally red. Since the absence of the identifier lasts longer and longer, the color after the color lights up (in this case, red is the last). Then, when one identifier is detected, all lights will be turned off.
<edit 2: After finalizing the James code in the following example and leaving the rest as written, I found that Subscribe would be called right in the first event at both alarm levels.
const int MaxLevels = 2; var idAlarmStream = idStream .Select(i => i) .AlarmSystem(keySelector, thresholdSelector, MaxLevels, TaskPoolScheduler.Default) .Subscribe(i => { Debug.WriteLine("Alarm on id \"{0}\" at {1}", i, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture)); });
Let's see what happens here, and if MaxLevels can be provided dynamically ...
<edit 3: James code works. The problem was between the chair and the keyboard! Changing the time to something more reasonable certainly helped. In fact, I changed them to large pieces, but that was .FromTicks , and it slipped away for a few minutes.