This commit is contained in:
47
lib/elixir_ai/audio/audio_processing.ex
Normal file
47
lib/elixir_ai/audio/audio_processing.ex
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule ElixirAi.AudioProcessing do
|
||||
@moduledoc """
|
||||
Public API for the demand-driven audio transcription pool.
|
||||
|
||||
Dispatch strategy:
|
||||
1. Pick a random idle worker from the :available pg group.
|
||||
2. If none are idle and the pool is below @max_workers, spawn a fresh worker
|
||||
under AudioWorkerSupervisor and route the job directly to it.
|
||||
3. If already at @max_workers, queue the job to a random existing worker via
|
||||
its Erlang mailbox — it will process it when its current job finishes.
|
||||
|
||||
Scale-up is fully automatic (on demand). Scale-down is handled by each worker's
|
||||
idle-timeout logic; workers exit after idling and the pool can reach 0.
|
||||
"""
|
||||
|
||||
@max_workers 10
|
||||
@all_group :all
|
||||
@available_group :available
|
||||
|
||||
@doc """
|
||||
Submit audio for transcription. The result is delivered asynchronously to
|
||||
`caller_pid` as:
|
||||
|
||||
{:transcription_result, {:ok, text} | {:error, reason}}
|
||||
"""
|
||||
def submit(audio_binary, mime_type, caller_pid) do
|
||||
case :pg.get_members(ElixirAi.AudioProcessingPG, @available_group) do
|
||||
[] ->
|
||||
all = :pg.get_members(ElixirAi.AudioProcessingPG, @all_group)
|
||||
|
||||
if length(all) < @max_workers do
|
||||
{:ok, pid} =
|
||||
DynamicSupervisor.start_child(ElixirAi.AudioWorkerSupervisor, ElixirAi.AudioWorker)
|
||||
|
||||
GenServer.cast(pid, {:transcribe, caller_pid, audio_binary, mime_type})
|
||||
else
|
||||
# At max capacity — overflow to a random worker's mailbox
|
||||
GenServer.cast(Enum.random(all), {:transcribe, caller_pid, audio_binary, mime_type})
|
||||
end
|
||||
|
||||
available ->
|
||||
GenServer.cast(Enum.random(available), {:transcribe, caller_pid, audio_binary, mime_type})
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user