I have an automated YouTube channel, and all the tasks are handled using Oban. For the YouTube uploading part, I faced similar issues with the YouTube API quota limitations, which only allow a certain number of operations within a 24-hour period.
If you’re interested, I’ve also written a tutorial about uploading to YouTube with Elixir
From my experience running this pipeline for multiple years, it’s much more convenient to track how many quota units you have left on your API key so you can max out the quota. This becomes especially helpful if you plan to add more API keys either for handling actions on behalf of different users or just to increase your overall quota without doing the google verification.
I manage my multiple Google credentials and their current quotas using a model in my database:
schema "google_credentials" do
field :name, :string
field :client_id, :string
field :client_secret, :string
field :refresh_token, :string
field :quota, :integer, default: 0
timestamps()
end
To handle API requests, I wrap each operation with a database query to find a credential with enough quota available. If none are found, the job is rescheduled to run after the next quota reset, with the highest priority to ensure it gets handled before new jobs are queued.
Here’s a simplified example of how I manage the quota for YouTube uploads and other API operations:
def insert_simple(channel_name, video_path, title, description, tags) do
operation_cost = 1_600
quota_wrapper(channel_name, operation_cost, fn client ->
Api.insert_simple(client, video_path, title, description, tags)
end)
end
def set_thumbnail(channel_name, youtube_video_id, thumbnail_path) do
operation_cost = 50
quota_wrapper(channel_name, operation_cost, fn client ->
Api.set_thumbnail(client, youtube_video_id, thumbnail_path)
end)
end
defp quota_wrapper(channel_name, operation_cost, fun) do
with {:ok, credential} <- Google.fetch_credential_with_quota(channel_name, operation_cost),
client <- Api.new(credential.name),
:ok <- Google.increment_credential_quota(credential.name, operation_cost) do
fun.(client)
else
:error ->
Logger.info("Quota increment failed")
{:error, :quota_increment_failed}
end
end
And then you reset the quota at 0 Los_Angeles timezone which is what’s youtube is doing
{
Oban.Plugins.Cron,
crontab: [
{"0 0 * * *", Lor.Worker.ResetCredentialsQuota}
],
timezone: "America/Los_Angeles"
}
],