Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean workflow to stop OutgoingMessage #201

Open
Skizu opened this issue Aug 25, 2022 · 0 comments
Open

Clean workflow to stop OutgoingMessage #201

Skizu opened this issue Aug 25, 2022 · 0 comments

Comments

@Skizu
Copy link

Skizu commented Aug 25, 2022

When using Zello Channels JS SDK for PTT a user may start and end a stream before getting a response from the start_stream event from either Session.startVoiceMessage() or direct calls to OutgoingMessage.start() in the case of autoStart: false. This sequences of events results in a less than desirable clean up task in the current implementation.

Consider the below snippet.

const outgoingMessage = session.startVoiceMessage();
await outgoingMessage.stop();

Due to the race condition with receiving the stream id, the clients socket traffic may look like so.

-> {"type":"audio","codec":"opus","codec_header":"gD4BPA==","packet_duration":60,"seq":3,"command":"start_stream"}
-> {"stream_id":null,"seq":3,"command":"stop_stream"}
<- {"stream_id":38793,"success":true,"seq":2}
<- {"error":"not enough params","seq":3}

A work around using a callback for startVoiceMessage also does not appear to be a viable option.

const callbacks = new WeakMap();

const outgoingMessage = session.startVoiceMessage((error, data) => {
  // on error, no action needed. Clean up handled by
  // `Session.sendCommandWithCallback()` rejecting the promise
  // referenced by `OutgoingMessage.start()` and calling
  // `this.stopRecording()`.
  if (error === null) {
    callbacks.delete(outgoingMessage);
    return;
  }

  const callback = callbacks.get(outgoingMessage);
  callback(error, data);
});

try {
  await outgoingMessage.stop();
} catch(error) {
  callbacks.set(outgoingMessage, (error, data) => {
    // `OutgoingMessage.currentMessageId` is set after the resolution
    // of this callback, as such we can not make use of
    // `OutgoingMessage.stop()`.
    session.stopStream({ stream_id: data.stream_id });
    
    // After callback `OutgoingMessage.start()` will then set
    // `currentMessageId` and call `OutgoingMessage.startRecording()`.
    // This is not desired as the call has been requested to stop.
    // An `Error` could be thrown to prevent this, ensuring recorder
    // is not started and left running, and sending data. However, this
    // leaves the `Session.sendCommandWithCallback()` Promise
    // unresolved.
    throw new Error();
  })
}

An alternate method is to add a listener for the recorder or encoder, and placing clean up code there, which is still not ideal solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant