.Net Circular Queue Wrapper

August 7, 2017

Geçtiğimiz aylara kadar java ile haşır neşir olurken bir anda ibre .net tarafına kaydı. Birbirleri ile çok ortak noktaları olsa da implementasyonlar ve api lar farklı olabiliyor. Java yazarken circular queue (aka ring buffer) ihtiyacım olduğu zaman guava içindeki com.google.common.collect.EvictingQueue sınıfını kullanıyordum. .Net Frameworkü üzerinde circular queue implementasyonu bulamadım. Stackoverflow üzerinde yaptığım arama sonucunda https://stackoverflow.com/a/9371346  adresindeki çözüme ulaştım. Problemimiz web api uygulamamıza gelen son 100 isteğin cevap zamanlarının ortalaması belli bir değeri aşarsa başka bir uygulamaya uyarı göndermek. İlgili kısımları burada paylaşıyorum.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class FixedSizedQueue<T> : ConcurrentQueue<T>
{
    private object lockObject = new object();

    private int limit;

    public FixedSizedQueue(int limit)
    {
        this.limit = limit;
    }
    public new void Enqueue(T obj)
    {
        base.Enqueue(obj);
        lock (lockObject)
        {
            T overflow;
            while (base.Count > limit && base.TryDequeue(out overflow)) ;
        }
    }

    public T[] ReadAll()
    {
        return base.ToArray();
    }
}

public class StopWatchAttribute : ActionFilterAttribute
{
    private static string KEY = "Response.Time";
    private static long LastWarning = DateTime.Now.Ticks;
    private static long PERIOD = TimeSpan.TicksPerSecond * 15;
    private static int SIZE = 100;
    private FixedSizedQueue<long> queue = new FixedSizedQueue<long>(SIZE);

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
        actionContext.Request.Properties[KEY] = Stopwatch.StartNew();
    }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);
        Stopwatch stopwatch = (Stopwatch)actionExecutedContext.Request.Properties[KEY];
        var elapsed = stopwatch.ElapsedMilliseconds;
        queue.Enqueue(elapsed);

        var averageResponseTime = queue.ReadAll().Sum() / SIZE;
        var responseTimeIncresing = averageResponseTime > 100;
        var notInPeriod = DateTime.Now.Ticks - LastWarning > PERIOD;
        if (responseTimeIncresing && notInPeriod)
        {
            LastWarning = DateTime.Now.Ticks;
            Debug.WriteLine($"{elapsed} ms elapsed.");
            // TODO whatever you want with this, log or feed another service
        }
    }
}

public class ValuesController : ApiController
{
    [StopWatch]
    public string Get()
    {
        return "ok";
    }
}

hidden

The Review Is the Action Item

2024/05/30The Review Is the Action ItemI like to consider running an incident review to be its own action item. Other follow-ups emerging from it are a plus, but the point is to learn from incidents, and the review gives room for that to happen.This is no…

via Ferd.ca

Finding a New Software Developer Job

For the first time ever, I was laid off, and had to find a new software developer job. I managed to find a new one, but it took longer than I thought, and it was a lot of work. I … Continue reading →

via Henrik Warne's blog

HOWTO: Change your behavior

In theory, behavior change should be easy. At first glance, it seems like you control your behavior. So, if you desire different behavior, why doesn’t your behavior change as instantly as your desire to change it? In short, lasting change of habitual behavio…

via Matt Might's blog