Backend, sync, infra, docs: ETag, API versioning, k8s, web scaffold, Android 16, domain stubs
- Backend: ShallowEtagHeaderFilter for /api/v1/*, API-VERSIONING.md, README (tenant, CORS, Flyway, ETag) - k8s: backend-deployment.yaml (Deployment, Service, Secret/ConfigMap) - Web: scaffold with directory pull, 304 handling, touch-friendly UI - Android 16: ANDROID-16-TARGET.md; BuildConfig STUN/signaling, SMOAApplication configures InfrastructureManager - Domain: CertificateManager revocation stub, ReportService signReports, ZeroTrust/ThreatDetection minimal docs - TODO.md and IMPLEMENTATION_STATUS.md updated; communications README for endpoint config Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -14,7 +14,8 @@ import javax.inject.Singleton
|
||||
*/
|
||||
@Singleton
|
||||
class VideoTransport @Inject constructor(
|
||||
private val webRTCManager: com.smoa.modules.communications.domain.WebRTCManager
|
||||
private val webRTCManager: com.smoa.modules.communications.domain.WebRTCManager,
|
||||
private val smartRoutingService: com.smoa.modules.communications.domain.SmartRoutingService
|
||||
) {
|
||||
private val _connectionState = MutableStateFlow<MeetingConnectionState>(MeetingConnectionState.Disconnected)
|
||||
val connectionState: StateFlow<MeetingConnectionState> = _connectionState.asStateFlow()
|
||||
@@ -29,26 +30,30 @@ class VideoTransport @Inject constructor(
|
||||
*/
|
||||
suspend fun joinMeeting(meetingId: String, userId: String): Result<Unit> {
|
||||
return try {
|
||||
if (!smartRoutingService.tryStartSession()) {
|
||||
return Result.Error(IllegalStateException("Session cap reached"))
|
||||
}
|
||||
_connectionState.value = MeetingConnectionState.Connecting(meetingId)
|
||||
|
||||
// Initialize WebRTC peer connection (audio + video)
|
||||
val connectionResult = webRTCManager.initializePeerConnection(meetingId, isAudioOnly = false)
|
||||
|
||||
val routingState = smartRoutingService.getRoutingState()
|
||||
val recommendedForVideo = routingState.recommendedForVideo
|
||||
val isAudioOnly = !recommendedForVideo
|
||||
|
||||
val connectionResult = webRTCManager.initializePeerConnection(meetingId, isAudioOnly = isAudioOnly)
|
||||
|
||||
when (connectionResult) {
|
||||
is Result.Success -> {
|
||||
peerConnection = connectionResult.data
|
||||
currentMeetingId = meetingId
|
||||
|
||||
// Start audio and video transmission
|
||||
smartRoutingService.recordConnectionSuccess()
|
||||
peerConnection?.let { connection ->
|
||||
webRTCManager.startAudioTransmission(connection)
|
||||
webRTCManager.startVideoTransmission(connection)
|
||||
if (!isAudioOnly) webRTCManager.startVideoTransmission(connection)
|
||||
}
|
||||
|
||||
_connectionState.value = MeetingConnectionState.Connected(meetingId)
|
||||
Result.Success(Unit)
|
||||
}
|
||||
is Result.Error -> {
|
||||
smartRoutingService.recordConnectionFailure()
|
||||
_connectionState.value = MeetingConnectionState.Error(
|
||||
connectionResult.exception.message ?: "Failed to connect"
|
||||
)
|
||||
@@ -60,6 +65,7 @@ class VideoTransport @Inject constructor(
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
smartRoutingService.recordConnectionFailure()
|
||||
_connectionState.value = MeetingConnectionState.Error(e.message ?: "Unknown error")
|
||||
Result.Error(e)
|
||||
}
|
||||
@@ -83,6 +89,7 @@ class VideoTransport @Inject constructor(
|
||||
|
||||
peerConnection = null
|
||||
currentMeetingId = null
|
||||
smartRoutingService.notifySessionEnded()
|
||||
_connectionState.value = MeetingConnectionState.Disconnected
|
||||
Result.Success(Unit)
|
||||
} catch (e: Exception) {
|
||||
|
||||
Reference in New Issue
Block a user