use alloc::{string::String, sync::Arc};
use crate::{
executor::Executor,
queue::{QueueWorker, WrappedTask},
task::{Response, Task},
};
#[cfg(test)]
mod tests;
#[cfg(all(feature = "nats-queue", feature = "std"))]
use crate::{executor::openai::ExecutorAsyncOpenai, queue::nats::NatsWorker};
#[cfg(all(feature = "nats-queue", feature = "std"))]
pub type NatsOpenaiWorker = Worker<NatsWorker, ExecutorAsyncOpenai>;
#[derive(Debug, Clone)]
pub struct Worker<Q: QueueWorker, E: Executor> {
queue: Q,
executor: E,
}
#[cfg(all(feature = "nats-queue", feature = "std"))]
impl NatsOpenaiWorker {
pub async fn from_env_or_default() -> anyhow::Result<Self> {
let queue = NatsWorker::from_env_or_default().await?;
let executor = ExecutorAsyncOpenai::from_env_or_default();
Ok(Self { queue, executor })
}
}
impl<Q: QueueWorker, E: Executor> Worker<Q, E> {
pub async fn run(self) -> anyhow::Result<()> {
tracing::info!("openai-api worker subscribed to queue");
while let Some(WrappedTask { message, task }) = self.queue.receive_task().await? {
let id = task.id;
tracing::debug!("received task id `{id}`");
let response = self.executor.execute(task).await?;
tracing::debug!(
"responding task id `{id}` with success({})",
response.success
);
if !response.success {
tracing::debug!(
"task id `{id}` responded with error `{}`",
response.contents
);
}
self.queue.send_response(message, response).await?;
tracing::debug!("task id `{id}` response sent to queue");
}
tracing::info!("openai-api worker terminated");
Ok(())
}
}
impl<Q: QueueWorker, E: Executor> QueueWorker for Worker<Q, E> {
type Message = Q::Message;
async fn receive_task(&self) -> anyhow::Result<Option<WrappedTask<Self::Message>>> {
self.queue.receive_task().await
}
async fn send_response(
&self,
message: Self::Message,
response: Response,
) -> anyhow::Result<()> {
self.queue.send_response(message, response).await
}
}
impl<Q: QueueWorker, E: Executor> Executor for Worker<Q, E> {
fn default_model(&self) -> &Arc<Option<String>> {
self.executor.default_model()
}
async fn execute(&self, task: Task) -> anyhow::Result<Response> {
self.executor.execute(task).await
}
}