Stream: helpdesk (published)

Topic: Conveyor vector?


view this post on Zulip Kevin Bonham (Mar 17 2022 at 15:37):

I think I have need of an vector of fixed size, where push!ing a new value basically shifts everything down, so that the first element gets dropped, the thing at index 2 goes to index 1, etc. The use-case is that I'm writing a wrapper for a web API that has a rate-limit of 5 requests / sec. I'm thinking of basically storing the time of the last 5 requests, and if the first one (earliest) is < 1 sec ago, pause for long enough to make it > 1 sec ago, then do the new request.

I have an idea of how to do this with a mutable struct that just stores the vector and an index that cycles 1-5 , but I'm wondering if there's some data structure like this that already exists / has a julia implementation.

view this post on Zulip Felix Kastner (Mar 17 2022 at 15:43):

I think this is called a circular buffer. Have a look at DataStructures.jl which provides a CircularBuffer type.

view this post on Zulip Felix Kastner (Mar 17 2022 at 15:43):

https://juliacollections.github.io/DataStructures.jl/latest/circ_buffer/

view this post on Zulip Kevin Bonham (Mar 17 2022 at 16:07):

Ahh, exactly!

view this post on Zulip Kevin Bonham (Mar 17 2022 at 16:08):

Though thinking through it, I think given my specific use case, the custom solution is maybe lighter weight. Here's what I have:

mutable struct Timer
    idx::Int
    last5::Vector{DateTime}

    Timer() = new(1, zeros(DateTime, 5))
end

function _ratelimit!(t::Timer)
    n = now()
    e = t.last5[t.idx]
    rl = n - e
    if rl < Millisecond(1000)
        sleep(Millisecond(1000) - rl)
        n = now()
    end

    t.last5[t.idx] = n
    t.idx = 1 + (t.idx % 5)
end

Last updated: Oct 02 2023 at 04:34 UTC