public async Task StartAsync(CancellationToken cancellationToken) { using (LogContext.PushProperty("FunctionId", nameof(StartAsync))) { Log.Information("Opening Edge Module Connection"); await ModuleClient.OpenAsync(); Log.Information("Initializing InfluxDBRecorder"); await TimeSeriesRecorder.InitializeAsync(); Log.Information("Beginning to Process Messages"); await ModuleClient.SetInputMessageHandlerAsync("telemetry", new MessageHandler( async(message, e) => { Log.Information("Processing message.."); var telemetryJson = Encoding.UTF8.GetString(message.GetBytes()); try { await TimeSeriesRecorder.RecordMessageAsync(telemetryJson); } catch (Exception ex) { Log.Error(ex, $"Error for message {telemetryJson}"); } return(await Task.FromResult(MessageResponse.Completed)); } ), ModuleClient); } }
public void CreateStreamTest() { const string symbol = "Symbol"; const string column = "Column"; var mockStream1 = new MockStream(3); var mockDbUpdater = Substitute.For <ITimeSeriesDbUpdater>(); mockDbUpdater.CreateColumnWriter(Arg.Any <string>(), Arg.Any <ColumnInfo>(), Arg.Any <DateTime>()) .Returns(mockStream1); var allocator = new DummyPinnedAllocator(); var recorder = new TimeSeriesRecorder( symbol, mockDbUpdater, allocator); var now = "08:00:00"; recorder.AddRow(now) .Record(column, 1) .Record(column, 2); mockDbUpdater.Received(1) .CreateColumnWriter( Arg.Is <string>(i => i == symbol), Arg.Is <ColumnInfo>(i => i.Name == column && i.Type == FieldType.Int32), Arg.Is <DateTime>(i => i == "08:00:00".ToDateTime())); mockDbUpdater.ClearReceivedCalls(); mockStream1.CheckCallsThenClear(); now = "08:00:01"; recorder.AddRow(now) .Record(column, 3) .Record(column, 4) .Record(column, 5); mockDbUpdater.ClearReceivedCalls(); mockStream1.CheckCallsThenClear(); mockStream1.CheckData(E("08:00:00", 1), E("08:00:00", 2), E("08:00:01", 3), E("08:00:01", 4), E("08:00:01", 5)); now = "08:00:02"; recorder.AddRow(now) .Record(column, 6); recorder.Commit(); mockStream1.CheckCallsThenClear(1, 0, 1); var columns = new[] { C(column, FieldType.Int32, "08:00:00", "08:00:02") }; mockDbUpdater.Received(1).Commit( Arg.Is <string>(i => i == symbol), Arg.Is <ColumnCommit[]>(i => IsEqual(i, columns))); }
public void RecordTimelineWithManyColumns() { const string symbol = "Symbol"; const string intColumn1 = "Int32Column1"; const string intColumn2 = "Int32Column2"; const string intColumn3 = "Int32Column3"; const string longColumn = "Int64Column"; const string floatColumn = "FloatColumn"; const string doubleColumn = "DoubletColumn"; var columnNames = new[] { intColumn1, intColumn2, intColumn3, longColumn, floatColumn, doubleColumn }; var mockDbUpdater = Substitute.For <ITimeSeriesDbUpdater>(); var streams = columnNames.ToDictionary(p => p, p => new MockStream()); foreach (var pair in streams) { mockDbUpdater.CreateColumnWriter( Arg.Any <string>(), Arg.Is <ColumnInfo>(i => i.Name == pair.Key), Arg.Any <DateTime>()) .Returns(streams[pair.Key]); } var allocator = new DummyPinnedAllocator(); var recorder = new TimeSeriesRecorder( symbol, mockDbUpdater, allocator); var now = "08:00:00"; recorder.AddRow(now) .Record(intColumn1, 1) .Record(intColumn2, 2) .Record(intColumn3, 3) .Record(longColumn, 100L) .Record(floatColumn, 1.23f) .Record(doubleColumn, 7.89); foreach (var pair in streams) { var timestamp = now.ToDateTime(); mockDbUpdater.Received(1).CreateColumnWriter( Arg.Is <string>(i => i == symbol), Arg.Is <ColumnInfo>(i => i.Name == pair.Key), Arg.Is <DateTime>(i => i == timestamp)); pair.Value.CheckCallsThenClear(); } mockDbUpdater.ClearReceivedCalls(); streams[intColumn1].CheckData(E(now, 1)); streams[intColumn2].CheckData(E(now, 2)); streams[intColumn3].CheckData(E(now, 3)); streams[longColumn].CheckData(E(now, 100L)); streams[floatColumn].CheckData(E(now, 1.23f)); streams[doubleColumn].CheckData(E(now, 7.89)); // Partial update now = "08:00:01"; recorder.AddRow(now) .Record(intColumn1, 10) .Record(intColumn3, 30) .Record(longColumn, 101L) .Record(doubleColumn, 7.99); streams[intColumn1].CheckData(E(now, 10)); streams[intColumn2].CheckNoData(); streams[intColumn3].CheckData(E(now, 30)); streams[longColumn].CheckData(E(now, 101L)); streams[floatColumn].CheckNoData(); streams[doubleColumn].CheckData(E(now, 7.99)); // Partial update now = "08:00:02"; recorder.AddRow(now) .Record(intColumn1, 11) .Record(intColumn2, 21) .Record(floatColumn, 1.24f); streams[intColumn1].CheckData(E(now, 11)); streams[intColumn2].CheckData(E(now, 21)); streams[intColumn3].CheckNoData(); streams[longColumn].CheckNoData(); streams[floatColumn].CheckData(E(now, 1.24f)); streams[doubleColumn].CheckNoData(); // Many ticks on the same timestamp now = "08:00:03"; recorder.AddRow(now) .Record(intColumn1, 12) .Record(intColumn1, 13) .Record(intColumn1, 14); streams[intColumn1].CheckData(E(now, 12), E(now, 13), E(now, 14)); streams[intColumn2].CheckNoData(); streams[intColumn3].CheckNoData(); streams[longColumn].CheckNoData(); streams[floatColumn].CheckNoData(); streams[doubleColumn].CheckNoData(); foreach (var pair in streams) { pair.Value.CheckCallsThenClear(); } mockDbUpdater.DidNotReceive().CreateColumnWriter( Arg.Any <string>(), Arg.Any <ColumnInfo>(), Arg.Any <DateTime>()); mockDbUpdater.DidNotReceive().Commit( Arg.Any <string>(), Arg.Any <ColumnCommit[]>()); mockDbUpdater.DidNotReceive().Revert( Arg.Any <string>(), Arg.Any <ColumnCommit[]>()); recorder.Commit(); foreach (var pair in streams) { pair.Value.CheckCallsThenClear(1, 0, 1); } var columns = new[] { C(intColumn1, FieldType.Int32, "08:00:00", "08:00:03"), C(intColumn2, FieldType.Int32, "08:00:00", "08:00:02"), C(intColumn3, FieldType.Int32, "08:00:00", "08:00:01"), C(longColumn, FieldType.Int64, "08:00:00", "08:00:01"), C(floatColumn, FieldType.Float, "08:00:00", "08:00:02"), C(doubleColumn, FieldType.Double, "08:00:00", "08:00:01") }; mockDbUpdater.Received(1).Commit( Arg.Is <string>(i => i == symbol), Arg.Is <ColumnCommit[]>(i => IsEqual(i, columns))); mockDbUpdater.DidNotReceive().CreateColumnWriter( Arg.Any <string>(), Arg.Any <ColumnInfo>(), Arg.Any <DateTime>()); mockDbUpdater.DidNotReceive().Revert( Arg.Any <string>(), Arg.Any <ColumnCommit[]>()); }