twiliotwilio-conversationstwilio-taskrouter

"Failed to issue Dequeue" when using Twilio Task Router for non-phone related tasks


NOTE: Code snippets below are functional. The "dequeue" error mentioned in this post was based on an existing Assignment Callback external to these scripts. Once the URL was removed and the reservation.dequeue moved to this code, the error was resolved.

We are in the process of developing a chat application using Conversations between two people. I currently have it "wired" up with the following steps when a user initiates the chat:

  1. Conversation is created.
  2. User is created.
  3. User is added to the conversation.
  4. Task is created with conversation meta-data in attributes.

(followed by steps on the other user's session to accept the reservation, etc.)

These steps work as expected, but a "40140 - Failed to issue Dequeue instruction due to missing 'call_sid' property" is generated since the task isn't an incoming phone call. I tried putting the task into the "SMS" Task Channel, but that didn't stop the error.

I couldn't find any specific documentation on creating non-phone call-based tasks so I might be setting up the task routing incorrectly.

Here are code snippets showing how I create (in .NET) the conversation, user, and task, and how I accept (in TaskRouter.js) the reservation.

/***********************************************************************************************************
This code is server-side in .NET
***********************************************************************************************************/
public ConversationCredentials CreateConversation( string program, string name )
{
  var memberId = DateTime.Now.ToString( "yyyyMMdd" );  // Temporary
  TwilioClient.Init( _twilioAccountSid,_twilioAuthToken );

  // If we decide to keep conversations on Twilio, we should replace the memberid with phiid, since member id might change

  var conversation = ConversationResource.Create(
    friendlyName: memberId + "_" + DateTime.Now.ToString( "HHmmss" )
  );

  var conversationCredentials = JoinConversation( conversation.Sid, name );
  var taskSid = CreateTask( program, conversation.Sid, memberId );

  conversationCredentials.taskSid = taskSid;
  
  return conversationCredentials;
}

public ConversationCredentials JoinConversation( string conversationSid, string name )
{
  var identity = name + "_" + DateTime.Now.ToString( "HHmmss" ); // Makes sure the user is unique, in case it's an employee joining more than one chat session)
  TwilioClient.Init( _twilioAccountSid,_twilioAuthToken );

  var participant = ParticipantResource.Create(
    pathConversationSid: conversationSid,
    identity: identity
  );

  var user = UserResource.Update(
    pathSid: identity,
    friendlyName: name
  );

  var token = GetJWT( _twilioConversationServiceSid, name );  // Conversation Service Sid

  var conversationCredentials = new ConversationCredentials();
  
  conversationCredentials.token = token;
  conversationCredentials.conversationSid = conversationSid;
  conversationCredentials.participantSid = participant.Sid;
  conversationCredentials.participantName = name;
  conversationCredentials.participantIdentity = participant.Identity;

  return conversationCredentials;
}

public string CreateTask( string program, string conversationSid, string memberId )
{

  TwilioClient.Init( _twilioAccountSid, _twilioAuthToken );

  var attributes = JsonConvert.SerializeObject( new Dictionary<string,Object>()
  {
    {"conversationSid", conversationSid },
    {"memberId",        memberId        },
    {"program",         program         },
    {"call_sid",        "CHAT"          }
  }, Formatting.Indented);

  var task = TaskResource.Create(
    attributes: attributes,
    workflowSid: _twilioWorkflowSid,
    pathWorkspaceSid: _twilioWorkspaceSid_Nurses,
    taskChannel: "Default"
  );

  return task.Sid;

}
/***********************************************************************************************************
This code is browser-side using TaskRouter.js
NOTE: This handles both voice (works fine) and conversations (the part in question)
***********************************************************************************************************/
registerTaskRouterCallbacks( _this ) : void {
this.worker.on('ready', function(worker) {
  _this.updateButton( worker.activityName, "" );
});

this.worker.on("reservation.created", function(reservation) {
  if ( reservation.task.attributes.type != "CHAT" )
  {
    _this.updateButton( "Call", reservation.task.attributes.from.replace( "+1", "" ) );
    reservation.dequeue();
  } else {
    _this.updateButton( "Chat", reservation.task.attributes.memberId );
    confirm("You have an incoming chat!");
    reservation.accept();
    // This is where the chat window would pop-up
  }
});

this.worker.on("reservation.accepted", function(reservation) {
  _this.worker.update({"ActivitySid": _this.activitySids["Busy"][0].sid});
  _this.updateButton( "Busy", "" );
});

Solution

  • The "dequeue" error mentioned in this post was based on an existing Assignment Callback external to these scripts. Once the URL was removed and the reservation.dequeue moved to this code, the error was resolved.