2

I am using Reactive library in my C# project to group data according to configured policies. All these data implement the following interface

public interface IPoint
{
    object Value { get; }
    DateTimeOffset Timestamp { get; }
}

One of the grouping policies I have to implement consists creating non-overlappable groups of a fixed time size, which looking at Reactive documentation could be achieved using Buffer(TimeSpan) function. This is exactly what I need, but instead of using a runtime calculated timestamp I need to use the ones defined in the Timestamp property of my objects.

I found this solution, which seems quite working:

public void Subscribe(Action<IEnumerable<IPoint>> callback)
{
    long windowSizeTicks = TimeRange.Ticks;    // TimeRange is my TimeSpan "buffer" size

    dataPoints.GroupByUntil(x => x.Timestamp.Ticks / windowSizeTicks,
                            g => dataPoints.Where(x => x.Timestamp.Ticks / windowSizeTicks != g.Key))
              .SelectMany(x => x.ToList())
              .Subscribe(callback);
    // dataPoints is ISubject<IPoint>
}

This solution just creates groups according to Ticks divisibility by TimeRange, which doesn't work correctly if the first item is not divisible by it.

An example to explain what I mean: considering the following points

Value: 1, Timestamp: "2021-04-26T00:00:01"
Value: 2, Timestamp: "2021-04-26T00:00:02"
Value: 3, Timestamp: "2021-04-26T00:00:03"
Value: 4, Timestamp: "2021-04-26T00:00:04"

and a "buffer size" of 2 seconds, I am expecting them to be grouped as [1, 2], [3, 4], but instead I receive [1], [2, 3], [4]. This happens because the grouping key is created considering the absolute time and not the difference from the starting of the data list.

I could save the timestamp of the first item and change the grouping function in this way, but I think (or at least I hope) there could be a better solution:

public void Subscribe(Action<IEnumerable<IPoint>> callback)
{
    long windowSizeTicks = TimeRange.Ticks;    // TimeRange is my TimeSpan "buffer" size

    dataPoints.GroupByUntil(x => (x.Timestamp.Ticks - firstPoint.Timestamp.Ticks) / windowSizeTicks,
                            g => dataPoints.Where(x => (x.Timestamp.Ticks - firstPoint.Timestamp.Ticks) / windowSizeTicks != g.Key))
              .SelectMany(x => x.ToList())
              .Subscribe(callback);
    // dataPoints is ISubject<IPoint>
}

I am a newbie at Reactive, so any helpful comment is welcome.

Thank you.

maradev21
  • 576
  • 2
  • 6
  • 20

0 Answers0