.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

AI: Where in the Loop Should Humans Go?

This is a re-publishing of a blog post I originally wrote for work, but wanted on my own blog as well.AI is everywhere, and its impressive claims are leading to rapid adoption. At this stage, I’d qualify it as charismatic technology—someth…

via Ferd.ca

More Good Programming Quotes, Part 6

Here are more good programming quotes I have found since my last post. Programming “Configuration is coding in a poorly designed programming language without tests, version control, or documentation.”Gregor Hohpe “It’s the developers misunderstanding, not…

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