pub struct QueueManager { /* private fields */ }
Expand description
§Call Queue Manager
The central coordinator for all call queuing operations in the call center. Manages multiple named queues, coordinates call assignment, and provides comprehensive queue statistics and monitoring.
§Key Features
- Multi-Queue Management: Handles multiple named queues simultaneously
- Priority-Based Queuing: Automatic priority ordering within queues
- Assignment Tracking: Prevents race conditions during call assignment
- Comprehensive Statistics: Real-time queue performance metrics
- Expiration Management: Automatic cleanup of expired calls
§Thread Safety
QueueManager
is designed for single-threaded use within the call center engine.
For multi-threaded access, wrap in appropriate synchronization primitives.
§Examples
§Basic Usage
use rvoip_call_engine::queue::{QueueManager, QueuedCall};
use rvoip_session_core::SessionId;
let mut queue_manager = QueueManager::new();
// Create department queues
queue_manager.create_queue("support".to_string(), "Technical Support".to_string(), 50)?;
queue_manager.create_queue("sales".to_string(), "Sales Team".to_string(), 30)?;
// Queue a high-priority call
let urgent_call = QueuedCall {
session_id: SessionId::new(),
caller_id: "+1-555-0123".to_string(),
priority: 1,
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(30),
retry_count: 0,
};
queue_manager.enqueue_call("support", urgent_call)?;
// Get next call for an agent
if let Some(call) = queue_manager.dequeue_for_agent("support")? {
println!("Assigning call to agent: {}", call.session_id);
}
Implementations§
Source§impl QueueManager
impl QueueManager
Sourcepub fn new() -> Self
pub fn new() -> Self
Create a new queue manager
Initializes an empty queue manager ready to handle call queuing operations.
No queues are created by default - use create_queue
to add queues.
§Examples
use rvoip_call_engine::queue::QueueManager;
let queue_manager = QueueManager::new();
assert_eq!(queue_manager.total_queued_calls(), 0);
Sourcepub fn get_queue_ids(&self) -> Vec<String>
pub fn get_queue_ids(&self) -> Vec<String>
Get all queue IDs
Returns a list of all queue identifiers currently managed by this queue manager. Useful for iterating over all queues or administrative operations.
§Returns
Vector of queue ID strings.
§Examples
use rvoip_call_engine::queue::QueueManager;
let mut queue_manager = QueueManager::new();
queue_manager.create_queue("support".to_string(), "Support".to_string(), 50)?;
queue_manager.create_queue("sales".to_string(), "Sales".to_string(), 30)?;
let queue_ids = queue_manager.get_queue_ids();
assert_eq!(queue_ids.len(), 2);
assert!(queue_ids.contains(&"support".to_string()));
assert!(queue_ids.contains(&"sales".to_string()));
Sourcepub fn create_queue(
&mut self,
queue_id: String,
name: String,
max_size: usize,
) -> Result<()>
pub fn create_queue( &mut self, queue_id: String, name: String, max_size: usize, ) -> Result<()>
Create a new queue
Adds a new named queue to the queue manager with the specified configuration. Each queue has its own capacity limits and policies.
§Arguments
queue_id
- Unique identifier for the queuename
- Human-readable name for the queuemax_size
- Maximum number of calls allowed in this queue
§Returns
Ok(())
if queue was created successfully, error if queue already exists.
§Examples
use rvoip_call_engine::queue::QueueManager;
let mut queue_manager = QueueManager::new();
// Create queues for different departments
queue_manager.create_queue("support".to_string(), "Technical Support".to_string(), 50)?;
queue_manager.create_queue("sales".to_string(), "Sales Team".to_string(), 30)?;
queue_manager.create_queue("billing".to_string(), "Billing Department".to_string(), 20)?;
// Verify queues were created
assert_eq!(queue_manager.get_queue_ids().len(), 3);
§Production Notes
- Choose appropriate
max_size
values based on expected call volume - Queue IDs should follow a consistent naming convention
- Consider using department codes or service types as queue IDs
Sourcepub fn is_call_queued(&self, queue_id: &str, session_id: &SessionId) -> bool
pub fn is_call_queued(&self, queue_id: &str, session_id: &SessionId) -> bool
Check if a call is already in the queue
Determines whether a specific call (identified by session ID) is already present in the specified queue. Useful for preventing duplicate queueing operations.
§Arguments
queue_id
- Queue to checksession_id
- Session ID of the call to check
§Returns
true
if the call is already queued, false
otherwise.
§Examples
use rvoip_call_engine::queue::{QueueManager, QueuedCall};
use rvoip_session_core::SessionId;
let session_id = SessionId::new();
// Initially not queued
assert!(!queue_manager.is_call_queued("support", &session_id));
// Add call to queue
let call = QueuedCall {
session_id: session_id.clone(),
caller_id: "+1-555-1234".to_string(),
priority: 5,
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(120),
retry_count: 0,
};
queue_manager.enqueue_call("support", call)?;
// Now it's queued
assert!(queue_manager.is_call_queued("support", &session_id));
Sourcepub fn is_call_being_assigned(&self, session_id: &SessionId) -> bool
pub fn is_call_being_assigned(&self, session_id: &SessionId) -> bool
Check if a call is being assigned
Determines whether a call is currently in the process of being assigned to an agent. This prevents race conditions where a call might be assigned to multiple agents simultaneously.
§Arguments
session_id
- Session ID of the call to check
§Returns
true
if the call is being assigned, false
otherwise.
§Examples
use rvoip_call_engine::queue::QueueManager;
use rvoip_session_core::SessionId;
let mut queue_manager = QueueManager::new();
let session_id = SessionId::new();
// Initially not being assigned
assert!(!queue_manager.is_call_being_assigned(&session_id));
// Mark as being assigned
queue_manager.mark_as_assigned(&session_id);
assert!(queue_manager.is_call_being_assigned(&session_id));
// Mark as no longer being assigned
queue_manager.mark_as_not_assigned(&session_id);
assert!(!queue_manager.is_call_being_assigned(&session_id));
Sourcepub fn enqueue_call(
&mut self,
queue_id: &str,
call: QueuedCall,
) -> Result<usize>
pub fn enqueue_call( &mut self, queue_id: &str, call: QueuedCall, ) -> Result<usize>
Enqueue a call
Adds a call to the specified queue with automatic priority ordering. Higher priority calls (lower priority numbers) are placed ahead of lower priority calls in the queue.
§Arguments
queue_id
- Target queue for the callcall
- Call information including priority and metadata
§Returns
Returns the position in the queue where the call was inserted (0-based), or an error if the operation failed.
§Examples
use rvoip_call_engine::queue::{QueueManager, QueuedCall};
use rvoip_session_core::SessionId;
// Add a normal priority call
let normal_call = QueuedCall {
session_id: SessionId::new(),
caller_id: "+1-555-1234".to_string(),
priority: 5,
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(120),
retry_count: 0,
};
let position1 = queue_manager.enqueue_call("support", normal_call)?;
assert_eq!(position1, 0); // First call, position 0
// Add a high priority call (should jump to front)
let urgent_call = QueuedCall {
session_id: SessionId::new(),
caller_id: "+1-555-VIP1".to_string(),
priority: 1, // Higher priority
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(30),
retry_count: 0,
};
let position2 = queue_manager.enqueue_call("support", urgent_call)?;
assert_eq!(position2, 0); // Jumped to front due to higher priority
§Errors
CallCenterError::Queue
- Queue is full or other queue-related errorCallCenterError::NotFound
- Specified queue doesn’t exist
§Behavior
- Prevents duplicate queueing of the same call
- Prevents queueing calls that are currently being assigned
- Enforces queue capacity limits
- Maintains priority ordering automatically
Sourcepub fn mark_as_assigned(&mut self, session_id: &SessionId)
pub fn mark_as_assigned(&mut self, session_id: &SessionId)
Mark a call as being assigned (to prevent duplicate processing)
Marks a call as currently being assigned to an agent to prevent race conditions where the same call might be processed by multiple threads or assigned to multiple agents.
§Arguments
session_id
- Session ID of the call being assigned
§Examples
use rvoip_call_engine::queue::QueueManager;
use rvoip_session_core::SessionId;
let mut queue_manager = QueueManager::new();
let session_id = SessionId::new();
// Mark call as being assigned
queue_manager.mark_as_assigned(&session_id);
// Verify it's marked
assert!(queue_manager.is_call_being_assigned(&session_id));
§Usage Pattern
This method should be called when a call is dequeued and assignment
begins. If assignment succeeds, the call remains dequeued. If assignment
fails, call mark_as_not_assigned
to allow re-queuing.
Sourcepub fn mark_as_not_assigned(&mut self, session_id: &SessionId)
pub fn mark_as_not_assigned(&mut self, session_id: &SessionId)
Mark a call as no longer being assigned (on failure)
Removes the assignment lock on a call, allowing it to be processed again. This should be called when call assignment fails and the call should be made available for re-queuing or re-assignment.
§Arguments
session_id
- Session ID of the call to unlock
§Examples
use rvoip_call_engine::queue::QueueManager;
use rvoip_session_core::SessionId;
let mut queue_manager = QueueManager::new();
let session_id = SessionId::new();
// Mark as assigned, then unmark due to failure
queue_manager.mark_as_assigned(&session_id);
queue_manager.mark_as_not_assigned(&session_id);
// Verify it's no longer marked
assert!(!queue_manager.is_call_being_assigned(&session_id));
§Usage Pattern
// Dequeue call (automatically marked as assigned)
if let Some(call) = queue_manager.dequeue_for_agent("support")? {
// Attempt to assign to agent
match assign_to_agent(&call).await {
Ok(_) => {
// Success - call remains dequeued and assigned
info!("Call assigned successfully");
}
Err(e) => {
// Failure - allow re-queuing
queue_manager.mark_as_not_assigned(&call.session_id);
warn!("Assignment failed: {}", e);
}
}
}
Sourcepub fn dequeue_for_agent(
&mut self,
queue_id: &str,
) -> Result<Option<QueuedCall>>
pub fn dequeue_for_agent( &mut self, queue_id: &str, ) -> Result<Option<QueuedCall>>
Dequeue the next call for an agent
Removes and returns the highest priority call from the specified queue that is not currently being assigned. The returned call is automatically marked as being assigned to prevent duplicate processing.
§Arguments
queue_id
- Queue to dequeue from
§Returns
Ok(Some(QueuedCall))
- Call was successfully dequeuedOk(None)
- No calls available in the queueErr(...)
- Queue doesn’t exist or other error
§Examples
use rvoip_call_engine::queue::{QueueManager, QueuedCall};
use rvoip_session_core::SessionId;
// Add some calls to the queue
let call1 = QueuedCall {
session_id: SessionId::new(),
caller_id: "+1-555-1234".to_string(),
priority: 5, // Normal priority
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(120),
retry_count: 0,
};
queue_manager.enqueue_call("support", call1)?;
let urgent_call = QueuedCall {
session_id: SessionId::new(),
caller_id: "+1-555-VIP1".to_string(),
priority: 1, // High priority
queued_at: chrono::Utc::now(),
estimated_wait_time: Some(30),
retry_count: 0,
};
queue_manager.enqueue_call("support", urgent_call)?;
// Dequeue - should get the high priority call first
if let Some(call) = queue_manager.dequeue_for_agent("support")? {
assert_eq!(call.priority, 1); // High priority call came first
assert_eq!(call.caller_id, "+1-555-VIP1");
// Call is now marked as being assigned
assert!(queue_manager.is_call_being_assigned(&call.session_id));
}
§Behavior
- Returns highest priority call (lowest priority number)
- Skips calls that are already being assigned
- Automatically marks returned call as being assigned
- Maintains queue statistics and logging
Sourcepub fn remove_expired_calls(&mut self) -> Vec<SessionId>
pub fn remove_expired_calls(&mut self) -> Vec<SessionId>
Remove expired calls from all queues
Sourcepub fn total_queued_calls(&self) -> usize
pub fn total_queued_calls(&self) -> usize
Get total number of queued calls across all queues
Sourcepub fn get_queue_stats(&self, queue_id: &str) -> Result<QueueStats>
pub fn get_queue_stats(&self, queue_id: &str) -> Result<QueueStats>
Get queue statistics
Sourcepub fn cleanup_stuck_assignments(
&mut self,
timeout_seconds: u64,
) -> Vec<SessionId>
pub fn cleanup_stuck_assignments( &mut self, timeout_seconds: u64, ) -> Vec<SessionId>
Clean up calls that have been stuck in “being assigned” state
Sourcepub fn force_unmark_assigned(&mut self, session_id: &SessionId) -> bool
pub fn force_unmark_assigned(&mut self, session_id: &SessionId) -> bool
Force remove a call from being assigned state
Trait Implementations§
Auto Trait Implementations§
impl Freeze for QueueManager
impl RefUnwindSafe for QueueManager
impl Send for QueueManager
impl Sync for QueueManager
impl Unpin for QueueManager
impl UnwindSafe for QueueManager
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more