Current section
Files
Jump to
Current section
Files
src/gleam/otp/intensity_tracker.gleam
//// The intensity tracker is used to monitor how frequently an event happens,
//// erroring if it happens too many times within a period of time.
import gleam/list
// TODO: test
pub opaque type IntensityTracker {
IntensityTracker(limit: Int, period: Int, events: List(Int))
}
pub type TooIntense {
TooIntense
}
pub fn new(limit limit: Int, period period: Int) -> IntensityTracker {
IntensityTracker(limit: limit, period: period, events: [])
}
@external(erlang, "erlang", "monotonic_time")
fn monotonic_time(a: Int) -> Int
fn now_seconds() -> Int {
monotonic_time(1)
}
pub fn trim_window(events: List(Int), now: Int, period: Int) -> List(Int) {
case events {
[] -> []
[event, ..events] ->
case now >= event + period {
True -> [event, ..trim_window(events, now, period)]
False -> []
}
}
}
pub fn add_event(
tracker: IntensityTracker,
) -> Result(IntensityTracker, TooIntense) {
let now = now_seconds()
let events = trim_window([now, ..tracker.events], now, tracker.period)
case list.length(events) >= tracker.limit {
True -> Error(TooIntense)
False -> Ok(IntensityTracker(..tracker, events: events))
}
}