import gleam/dict.{type Dict} import gleam/erlang/process import gleam/option.{type Option, None, Some} import gleam/otp/actor const max_requests_per_minute = 10 pub type StorageState { StorageState(pastes: Dict(String, String), rate_limits: Dict(String, Int)) } pub type StorageMsg { CreatePaste(key: String, content: String, reply: process.Subject(Bool)) GetPaste(key: String, reply: process.Subject(Option(String))) PeekPaste(key: String, reply: process.Subject(Option(String))) CheckRateLimit(ip: String, reply: process.Subject(Bool)) ResetRateLimits } pub fn handle_message(state: StorageState, msg: StorageMsg) { case msg { CreatePaste(key, content, reply) -> { let new_state = StorageState(dict.insert(state.pastes, key, content), state.rate_limits) process.send(reply, True) actor.continue(new_state) } PeekPaste(key, reply) -> { let content = case dict.get(state.pastes, key) { Ok(value) -> Some(value) Error(_) -> None } process.send(reply, content) actor.continue(state) } GetPaste(key, reply) -> { let content = case dict.get(state.pastes, key) { Ok(value) -> Some(value) Error(_) -> None } let new_pastes = dict.delete(state.pastes, key) let new_state = StorageState(new_pastes, state.rate_limits) process.send(reply, content) actor.continue(new_state) } CheckRateLimit(ip, reply) -> { let current_count = dict.get(state.rate_limits, ip) |> option.from_result |> option.unwrap(0) let allowed = current_count < max_requests_per_minute let new_limits = case allowed { True -> dict.insert(state.rate_limits, ip, current_count + 1) False -> state.rate_limits } process.send(reply, allowed) actor.continue(StorageState(state.pastes, new_limits)) } ResetRateLimits -> { actor.continue(StorageState(state.pastes, dict.new())) } } } pub fn start() { actor.new(StorageState(dict.new(), dict.new())) |> actor.on_message(handle_message) |> actor.start }