async Task Process(DataPointProcessor processor, IAsyncStreamReader <grpc.DataPoints> streamReader)
        {
            while (await streamReader.MoveNext().ConfigureAwait(false))
            {
                var dataPoints = streamReader.Current;

                try
                {
                    foreach (var dataPoint in dataPoints.DataPoints_)
                    {
                        await processor.Invoke(new TimeSeriesMetadata(dataPoint.TimeSeries.To <TimeSeriesId>()), dataPoint.ToDataPoint()).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "Error processing datapoint");
                }
            }
        }
 void Discover()
 {
     _processors.ForEach(_ =>
     {
         var methods          = _.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
         var processorMethods = methods.Where(method => method.GetCustomAttributes().Any(attribute => attribute is DataPointProcessorAttribute));
         if (!processorMethods.Any())
         {
             _logger.Warning($"DataPoint processor of type '{_.GetType().AssemblyQualifiedName}' does not seem to have any methods adorned with [DataPointProcessor] - this means it does not have any processors");
         }
         else
         {
             processorMethods.ForEach(method =>
             {
                 var processor = new DataPointProcessor(_, method);
                 _dataProcessors[processor.Id] = processor;
             });
         }
     });
 }