Add rate limiting to Wikipedia and BraveSearch APIs

Closes #133
This commit is contained in:
Claudio Ortolina
2026-03-25 11:38:17 +00:00
parent 766a1dd7ed
commit 0295e58e57
7 changed files with 33 additions and 10 deletions
+5 -2
View File
@@ -68,9 +68,12 @@ config :music_library, Discogs,
user_agent: user_agent, user_agent: user_agent,
api_cooldown: 1000 api_cooldown: 1000
config :music_library, Wikipedia, user_agent: user_agent config :music_library, Wikipedia, user_agent: user_agent, api_cooldown: 1000
config :music_library, BraveSearch, api_key: "change me", user_agent: user_agent config :music_library, BraveSearch,
api_key: "change me",
user_agent: user_agent,
api_cooldown: 1000
config :music_library, OpenAI, api_key: "change me" config :music_library, OpenAI, api_key: "change me"
+4 -2
View File
@@ -79,14 +79,16 @@ config :music_library, Wikipedia,
req_options: [ req_options: [
plug: {Req.Test, Wikipedia.API}, plug: {Req.Test, Wikipedia.API},
max_retries: 0 max_retries: 0
] ],
api_cooldown: 0
config :music_library, BraveSearch, config :music_library, BraveSearch,
api_key: "test_key", api_key: "test_key",
req_options: [ req_options: [
plug: {Req.Test, BraveSearch.API}, plug: {Req.Test, BraveSearch.API},
max_retries: 0 max_retries: 0
] ],
api_cooldown: 0
config :music_library, OpenAI, config :music_library, OpenAI,
api_key: "test_key", api_key: "test_key",
+2 -2
View File
@@ -229,8 +229,8 @@ All HTTP clients use `Req` with per-API rate limiting (`Req.RateLimiter`, ETS-ba
| MusicBrainz | 500 ms cooldown | Release/artist metadata, search | | MusicBrainz | 500 ms cooldown | Release/artist metadata, search |
| Last.fm | 500 ms cooldown | Scrobbling, listening history, artist tags | | Last.fm | 500 ms cooldown | Scrobbling, listening history, artist tags |
| Discogs | 1000 ms cooldown | Artist profiles, images | | Discogs | 1000 ms cooldown | Artist profiles, images |
| Wikipedia | | Artist biographies | | Wikipedia | 1000 ms cooldown | Artist biographies |
| Brave Search | | Cover art, artist image search | | Brave Search | 1000 ms cooldown | Cover art, artist image search |
| OpenAI | — | Text embeddings (similarity), streaming chat | | OpenAI | — | Text embeddings (similarity), streaming chat |
--- ---
+1
View File
@@ -57,6 +57,7 @@ defmodule BraveSearch.API do
headers: %{"x-subscription-token" => config.api_key} headers: %{"x-subscription-token" => config.api_key}
) )
|> Req.Request.merge_options(config.req_options) |> Req.Request.merge_options(config.req_options)
|> Req.RateLimiter.attach(name: :brave_search, cooldown: config.api_cooldown)
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|> Req.Request.append_response_steps(log_error: &log_error/1) |> Req.Request.append_response_steps(log_error: &log_error/1)
end end
+9 -2
View File
@@ -2,13 +2,15 @@ defmodule BraveSearch.Config do
@type t :: %__MODULE__{ @type t :: %__MODULE__{
api_key: String.t(), api_key: String.t(),
user_agent: String.t(), user_agent: String.t(),
req_options: Keyword.t() req_options: Keyword.t(),
api_cooldown: non_neg_integer()
} }
@enforce_keys [:api_key] @enforce_keys [:api_key]
defstruct api_key: "", defstruct api_key: "",
user_agent: "change me", user_agent: "change me",
req_options: [] req_options: [],
api_cooldown: 1000
@schema NimbleOptions.new!( @schema NimbleOptions.new!(
api_key: [ api_key: [
@@ -24,6 +26,11 @@ defmodule BraveSearch.Config do
type: :keyword_list, type: :keyword_list,
required: false, required: false,
default: [] default: []
],
api_cooldown: [
type: :integer,
required: false,
default: 1000
] ]
) )
+3
View File
@@ -15,6 +15,7 @@ defmodule Wikipedia.API do
user_agent: config.user_agent user_agent: config.user_agent
) )
|> Req.Request.merge_options(config.req_options) |> Req.Request.merge_options(config.req_options)
|> Req.RateLimiter.attach(name: :wikipedia, cooldown: config.api_cooldown)
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|> Req.Request.append_response_steps(log_error: &log_error/1) |> Req.Request.append_response_steps(log_error: &log_error/1)
|> Req.merge( |> Req.merge(
@@ -52,6 +53,7 @@ defmodule Wikipedia.API do
user_agent: config.user_agent user_agent: config.user_agent
) )
|> Req.Request.merge_options(config.req_options) |> Req.Request.merge_options(config.req_options)
|> Req.RateLimiter.attach(name: :wikipedia, cooldown: config.api_cooldown)
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|> Req.Request.append_response_steps(log_error: &log_error/1) |> Req.Request.append_response_steps(log_error: &log_error/1)
|> Req.merge(url: "/api/rest_v1/page/summary/#{URI.encode(title)}") |> Req.merge(url: "/api/rest_v1/page/summary/#{URI.encode(title)}")
@@ -78,6 +80,7 @@ defmodule Wikipedia.API do
user_agent: config.user_agent user_agent: config.user_agent
) )
|> Req.Request.merge_options(config.req_options) |> Req.Request.merge_options(config.req_options)
|> Req.RateLimiter.attach(name: :wikipedia, cooldown: config.api_cooldown)
|> Req.Request.append_request_steps(log_attempt: &log_attempt/1) |> Req.Request.append_request_steps(log_attempt: &log_attempt/1)
|> Req.Request.append_response_steps(log_error: &log_error/1) |> Req.Request.append_response_steps(log_error: &log_error/1)
|> Req.merge( |> Req.merge(
+9 -2
View File
@@ -1,11 +1,13 @@
defmodule Wikipedia.Config do defmodule Wikipedia.Config do
@type t :: %__MODULE__{ @type t :: %__MODULE__{
user_agent: String.t(), user_agent: String.t(),
req_options: Keyword.t() req_options: Keyword.t(),
api_cooldown: non_neg_integer()
} }
defstruct user_agent: "change me", defstruct user_agent: "change me",
req_options: [] req_options: [],
api_cooldown: 1000
@schema NimbleOptions.new!( @schema NimbleOptions.new!(
user_agent: [ user_agent: [
@@ -17,6 +19,11 @@ defmodule Wikipedia.Config do
type: :keyword_list, type: :keyword_list,
required: false, required: false,
default: [] default: []
],
api_cooldown: [
type: :integer,
required: false,
default: 1000
] ]
) )