andreluizsecco / RingBufferPlus

A generic circular buffer (ring buffer) in C# with Auto-Scaler, Health-Check and Metrics-Report.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

# Welcome to RingBufferPlus

Build Publish Downloads NuGet License

A generic circular buffer (ring buffer) in C# with Auto-Scaler, Health-Check and Metrics-Report.

Visit the RingBufferPlus official page for complete documentation

Install

RingBufferPlus was developed in c# with the netstandard2.1, .NET 5 AND .NET6 target frameworks.

Install-Package RingBufferPlus [-pre]
dotnet add package RingBufferPlus [--prerelease]

Note: [-pre]/[--prerelease] usage for pre-release versions

Examples

The project in the folder DotNetProbes contains the samples with RabbitMQ(publish).

dotnet run --project DotNetProbes

Basic concept

Top

A ring buffer is a memory allocation scheme where memory is reused (reclaimed) when an index, incremented modulo the buffer size, writes over a previously used location. A ring buffer makes a bounded queue when separate indices are used for inserting and removing data. The queue can be safely shared between threads (or processors) without further synchronization so long as one processor enqueues data and the other dequeues it. (Also, modifications to the read/write pointers must be atomic, and this is a non-blocking queue--an error is returned when trying to write to a full queue or read from an empty queue).

Implemented concept

Top

The implementation follows the basic principle. There is a capacity that is provided to the consumer that may or may not be modified to optimize the consumption of used resources. As there may be resources that may become unavailable and/or invalid, the health status validation functionality was added and for critical failure scenarios, a pause for a retry (broken circuit). As an extra resource, a metric-report functionality was created to monitor the performance of the component.

Usage

RingBufferPlus - Sample Minimum Usage

Top

public class MyClass
{
   private readonly Guid _id;
   public MyClassTest()
   {
      _id = Guid.NewGuid();
   }
   public Guid Id => _id;
}

var rb = RingBuffer<MyClass>
        .CreateBuffer() //default 2 (Initial/min/max)
        .MaxBuffer(10)
        .Factory((ctk) => new MyClass())
        .Build()
        .Run();

using (var buffer = rb.Accquire())
{ 
   Console.WriteLine(buffer.Id);
}

rb.Dispose();

RingBufferPlus - Sample Complex Usage

Top

public class MyClass : IDisposable
{
   private readonly Guid _id;
   private bool _disposedValue;

   public MyClassTest()
   {
      _id = Guid.NewGuid();
   }
   public bool IsValidState => true;	
   public Guid Id => _id;
   protected virtual void Dispose(bool disposing)
   {
      if (!_disposedValue)
      {
         if (disposing)
         {
           _disposedValue = true;
         }
      }
   }
   public void Dispose()
   {
      // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
      Dispose(disposing: true);
      GC.SuppressFinalize(this);
   }
}

var build_rb = RingBuffer<MyClass>
                .CreateBuffer(5)
                .MinBuffer(3)
                .MaxBuffer(10)
                .AliasName("Test")
                .SetPolicyTimeout(RingBufferPolicyTimeout.UserPolicy, (metric,ctk) => true)
                .SetTimeoutAccquire(10)
                .SetIntervalAutoScaler(500)
                .SetIntervalHealthCheck(1000)
                .SetIntervalFailureState(TimeSpan.FromSeconds(30))
                .SetIntervalReport(1000)
                .LinkedFailureState(() => true)
                .Factory((ctk) => New MyClass() )
                .HealthCheck((buffer, ctk) => buffer.IsValidState)
                .MetricsReport((metric,ctk) => Console.WriteLine(metric.ErrorCount))
                .AddLogProvider(_loggerFactory,RingBufferLogLevel.Information)
                .AutoScaler((RingBufferMetric, CancellationToken) =>
                {
                   return 5;	
                })
                .Build();

build_rb.AutoScalerCallback += Ring_AutoScalerCallback;
build_rb.ErrorCallBack += Ring_ErrorCallBack;
build_rb.TimeoutCallBack += Ring_TimeoutCallBack;

var rb = build_rb.Run(cancellationToken);

using (var buffer = rb.Accquire())
{ 
   Console.WriteLine(buffer.Id);
}

rb.Dispose();

private void Ring_ErrorCallBack(object sender, RingBufferErrorEventArgs e)
{
   Console.WriteLine($"{e.Alias} => Error: {e.Error?.Message ?? "Null"}.");
}

private void Ring_TimeoutCallBack(object sender, RingBufferTimeoutEventArgs e)
{
   Console.WriteLine($"{e.Alias} => TimeOut = {e.ElapsedTime}");
}

private void Ring_AutoScalerCallback(object sender, RingBufferAutoScaleEventArgs e)
{
   Console.WriteLine($"{e.Alias} => {e.OldCapacity} to {e.NewCapacity}.");
}

Inspiration notes

This work was inspired by the project by Luis Carlos Farias.

My thanks for your great work of bringing knowledge to the community!

Supported platforms

Top

  • Windows
  • Linux (Ubuntu, etc)

License

This project is licensed under the MIT License

About

A generic circular buffer (ring buffer) in C# with Auto-Scaler, Health-Check and Metrics-Report.

License:MIT License


Languages

Language:C# 100.0%