@signalwire/js
Version:
101 lines (88 loc) • 2.91 kB
text/typescript
import {
SDKWorker,
SagaIterator,
getLogger,
sagaEffects,
SDKWorkerParams,
SDKActions,
FabricAction,
} from '@signalwire/core'
import { FabricRoomSessionConnection } from '../FabricRoomSession'
import { createFabricRoomSessionMemberObject } from '../FabricRoomSessionMember'
import { callSegmentWorker } from './callSegmentWorker'
import { MapToPubSubShape } from 'packages/core/dist/core/src'
export type FabricWorkerParams<T> =
SDKWorkerParams<FabricRoomSessionConnection> & {
action: MapToPubSubShape<T>
}
export const fabricWorker: SDKWorker<FabricRoomSessionConnection> = function* (
options
): SagaIterator {
getLogger().trace('fabricWorker started')
const {
channels: { swEventChannel },
instance: cfRoomSession,
} = options
function* worker(action: FabricAction) {
const { type, payload } = action
switch (type) {
case 'call.joined': {
// since we depend on `cfRoomSession.selfMember` on the take logic
// we need to make sure we update the `cfRoomSession.selfMember`
// in this worker or have a race condition.
if (!cfRoomSession.selfMember) {
const memberInstance = createFabricRoomSessionMemberObject({
store: cfRoomSession.store,
payload: {
member: action.payload.room_session.members.find(
(m) => m.member_id === action.payload.member_id
)!,
room_id: action.payload.room_id,
room_session_id: action.payload.room_session_id,
},
})
cfRoomSession.selfMember = memberInstance
}
// Segment worker for each call_id
yield sagaEffects.fork(callSegmentWorker, {
...options,
instance: cfRoomSession,
action,
})
break
}
case 'call.state':
cfRoomSession.emit(type, payload)
break
}
}
let firstCallJoinedReceived = false
const isFirstCallJoinedorCallStateEvent = (action: SDKActions) => {
if (action.type === 'call.state') {
return true
}
if (action.type !== 'call.joined') {
return false
}
// If this is the first call.joined event, verify the call origin ID
if (!firstCallJoinedReceived) {
const callId = action.payload.call_id
const originCallId = action.payload.origin_call_id
if (callId === originCallId) {
firstCallJoinedReceived = true
return true
}
return false // Discard all the call.joined event until the first call.joined is received
}
// If first call.joined event already received, only check the action type
return true
}
while (true) {
const action: FabricAction = yield sagaEffects.take(
swEventChannel,
isFirstCallJoinedorCallStateEvent
)
yield sagaEffects.fork(worker, action)
}
getLogger().trace('fabricWorker ended')
}