Combining a multi-message incoming SMS message from Twilio - twilio

I'm building an SMS-enabled app that allows the user to communicate with an external contact. As incoming messages arrive, I save them to my database so that they can be displayed in the app.
In testing, everything is working great for one-off messages, but I'm having trouble with messages longer than 160 characters, which are actually broken up into multiple messages.
When an incoming message comes in via SMS, I'm checking whether we already got a message from that number within the past few seconds. If we have, I append to the existing record in my DB, rather than saving a new record.
// First message arrives:
record == "This is the first message."
// Second message arrives:
record == "This is the first message. This is the second message."
My problem is that sometimes the two messages arrive so quickly that the first record hasn't finished saving yet. When the second process queries for an existing record, it doesn't find one and creates a new one.
// First message arrives:
record1 == "This is the first message."
// Second message arrives, first isn't saved yet:
record1 == "This is the first message."
record2 == "This is the second message."
This makes a particularly bad user experience when there's a message with three or more segments, when the following happens:
// First message arrives:
record1 == "This is the first message."
// Second message arrives, first isn't saved yet.
record1 == "This is the first message."
record2 == "This is the second message."
// Third message arrives, first has now been saved.
record1 == "This is the first message. This is the third message."
record2 == "This is the second message."
Without abandoning my plan to re-combine these messages, how can I get the messages to appear in the right order?
*Note: * Ideally, I'd like to know when saving a message whether it is a first (new) message or a follow-up message. Receiving a new message triggers an email notification to the user, but I don't want to send multiple notifications if they're receiving one long message.

Related

How to send a message from Helix controller to participant?

I want to send a message to all Participant nodes of my Helix cluster from Controller node. I tried following piece of code to send message to all registered participants of my cluster but their registered Participant message listeners are not receiving the message notification from Helix.
Message msg = new Message(factory.getMessageTypes().get(0), msgId);
msg.setMsgId(msgId);
msg.setSrcName(hostSrc);
msg.setTgtSessionId("*");
msg.setMsgState(MessageState.NEW);
msg.getRecord().setSimpleField("TestMessage", "Message from controller");
Criteria recipientCriteria = new Criteria();
recipientCriteria.setRecipientInstanceType(InstanceType.PARTICIPANT);
recipientCriteria.setInstanceName("%"); // To all recipients
recipientCriteria.setSessionSpecific(true); // To deliver only live participants
recipientCriteria.setSessionSpecific("DEV_CLUSTER"); // To only participants of this cluster
messagingService.send(recipientCriteria,msg);
Note that, when I am sending this message there is no resource exists in the cluster.
After debugging further what I have observed is CriteriaEvaluator.evaluateCriteria(....) operation is returning an empty list which further results into 0 messages to be sent to Participants nodes.
Kindly let me know if I am missing anything here while defining my criteria for Participants.
Thanks !
Update-1: our observation on this issue is as follows:
The received message at the participant side is read by both the Participant message listener(Say L1) and the handler created through MessageHandlerFactory(Which internally creating a listener HelixtaskExecutor (Say L2)).
In case if the message is read by HelixTaskExecutor(L2) first, it then immediately deletes the Znode in Zookeeper and the additionally configured message listener(L1) doesn't receive this message.
In case if the message is first read my additional message listener i.e. L1 then in such scenarios we don't face this problem as this additionally added listener doesn't delete the Znode from ZooKeeper.
We are still not sure how can we handle this problem as we want to use both the listener and MessageHandlers but facing the same problem I stated above.
Any inputs are appreciated.

Raid doesn't receive C_ChatInfo.SendAddonMessage

I'm making this addons that have to send to the raid my interrupt cooldown.
The problem is that whenever i send a message to the raid i am the only one that receive it.
This is the code that send the message:
C_ChatInfo.SendAddonMessage("KickRotation",string.format( "%0.2f",remainingCd ), "RAID")
This is the event handler:
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("CHAT_MSG_ADDON")
frame:SetScript("OnEvent", function(self, event, ...)
local prefix, msg, msgType, sender = ...;
if event == "CHAT_MSG_ADDON" then
if prefix == "KickRotation" then
print("[KickRotation]" ..tostring(sender) .." potrĂ  interrompere tra: " ..msg);
end
end
if event == "PLAYER_ENTERING_WORLD" then
print("[KickRotation] v0.1 by Galfrad")
end
end)
Basically when the message is sended it is printed only to me.
Network messages are handled and transferred to the recipient channel (in this case, Raid Group) by the server. The reason that you are seeing the message locally, but the other people do not see it is that the message will be handled on the local system (sender) to reduce the repetition of data transmit.
Server however, only accepts and sends messages that are registered to it.
Therefore, you must first register your add-on messages to the server so the other players in the requested channel be able to receive it.
First, register your add-on messages with the name you have given already (But be sure to call the registration method only once per client):
local success = C_ChatInfo.RegisterAddonMessagePrefix("KickRotation") -- Addon name.
Next, check if your message was accepted and registered to the server. In case success is set to false (failure), you may want to handle proper warning messages and notifications to the user. The case of failure means that either server has disabled add-on messages or you have reached the limit of add-on message registrations.
Finally, send your message again check if it did not fail.
if not C_ChatInfo.SendAddonMessage("KickRotation",string.format( "%0.2f",remainingCd ), "RAID") then
print("[KickRotation] Failed to send add-on message, message rejected by the server.")
end

Does Firebase always guarantee added events in order?

I am developing messenger IOS app based on Firebase Realtime Database.
I want that all messages to be ordered based on timestamp.
There is a scenario as like below.
There are 3 clients. A, B and C.
1)
All clients register 'figure-1' listener to receive messages from others.
<figure-1>
ref.queryOrdered(byChild: "timestamp").queryStarting(atValue: startTime).observe(.childAdded, with:
{
....
// do work for the messages, print, save to storage, etc.
....
// save startTime to storage for next open.
startTime = max(timeOfSnapshot, startTime)
saveToStorage(startTime)
}
2)
Client A write message 1 to server with ServerValue.timestamp().
Client B write message 2 to server with ServerValue.timestamp().
Client C write message 3 to server with ServerValue.timestamp().
They sent messages extremely the same moment.
All clients have good speed wifi.
So, finally. Server data saved like 'figure-2'
<figure-2>
text : "Message 1", timestamp : 100000001
text : "Message 2", timestamp : 100000002
text : "Message 3", timestamp : 100000003
As my listener's code, i keep messages on storage and next listening timestamp for preventing downloading duplicated messages.
In this case.
Does Firebase always guarantee to trigger callback in order as like below?
Message 1
Message 2
Message 3
If it is not guaranteed, my strategy is absolutely wrong.
For example, some client received messages as like below.
Message 3 // the highest timestamp.
// app crash or out of storage
Message 1
Message 2
The client do not have chance to get message 1, 2 anymore.
I think if there are some nodes already, Firebase might trigger in order for those. Because, that is role of 'queryOrdered' functionality.
However, there are no node before register the listener and added new nodes additionally after then. What is will happen?
I suppose Firebase might send 3 packets to clients. (No matter how quickly the message arrives, Firebase has to send it out as soon as it arrives.)
Packet1 for message1
Packet2 for message2
Packet3 for message3
ClientA fail to receive for packet 1,2
ClientA success to receive for packet 3
Firebase re-send packet 1,2 again.
ClientA success to receive for packet 1,2
Eventually, all datas are consistent. But ordering is corrupted.
Does Firebase guarantee to occur events in order?
I have searched stack overflow and google and read official documents many times. However, i could not find the clear answer.
I have almost spent one week for this. Please give me piece of advice.
The order in which the data for a query is returns is consistent, and determined by the server. So all clients are guaranteed to get the results in the same order.
For new data that is sent to the database after the listeners are attached, all remote clients will receive it in the same order. The local client will see events for it's write operation right away though, before the data even reaches the database server.
In figure 2, it is actually quite simple: since each node has a unique timestamp, and they will be returned in the order of that timestamp. But even if they'd have the same timestamp, they'd be returned in the same order (timestamp first, then key) for each client.

Subscription not created despite 201 message with correct body

I used to received the notification after receiving a new mail after making a subscription. However, since I accidently spammed my own mail box (create an event that make it so that each time there is a new message, a new draft message was created (and draft message count as new message), each time I create a subscription, I got the answer that everything is fine, but no new subscription is created. What should I do to have a functionnal subscription ?
Annex:
the post call which ask to call a ws each times a new message is received
https://graph.microsoft.com/post/subscriptions
with those params
{
changeType: 'created',
notificationUrl: 'the adresse of the webservice',
resource: 'me/messages',
expirationDateTime: '2018-10-23T17:46:08Z',
clientState: 'Message Created'
}
the answer (I also got a log indicating that the webservice got the notification token and answer it with a plain/text with statut 200 message containing the notification token.
{
changeType: 'created',
notificationUrl: 'the adresse of the webservice',
resource: 'me/messages',
expirationDateTime: '2018-10-22T17:37:21Z',
clientState: 'Message Created'
}
A few things to check:
The results returned by the list subscriptions API varies depending on the permissions (the linked article explains that). Make sure that when you check for the existence of the sub, you have the right permissions for the subscription you are looking for. Best, test with the same app and identity.
You mentioned you did receive a notification from the subscription? If so, the notification contains the ID of the subscription that generated it. That in itself is proof that the subscription was indeed created. Are you able to do a GET on that subscription?

sidekiq workers sending twilio calls in wrong order

I have an SMS app that sends the SMS message to be sent to a sidekiq worker, which then pings twilio to actually send the message. The problem I'm running into is that by sending the messages to a worker, sometimes messages above 160 characters get sent in the wrong order. I assume this is because sidekiq is running the jobs concurrently. How do I solve this problem?
Previously, I would cycle through each 160 characters of a message and send each 160 character string to a worker to be sent. This caused issues because the workers would get setup and run concurrently to the messages were out of order. To solve this, I moved the 160 character logic into the worker, which I believe solved the issue of a single message.
However, if multiple messages come through within 1-2 seconds, they get sent concurrently so it's possible it will be out of order again. How do I make sure sidekiq processes the messages in the order I call the perform_async method? Here's my code:
//messages_controller.rb
SendSMSWorker.new.perform(customer.id, message_text, 'sent', false, true)
//send_sms_worker.rb
def perform(customer_id, message_text, direction, viewed, via_api)
customer = Customer.find(customer_id)
company = customer.company
texts = message_text.scan(/.{1,160}/) # split the messages up into 160 char pieces
texts.each do |text|
message = customer.messages.new(
user_id: company.admin.id, # set the user_id to the admin's ID when using the api
company_id: company.id,
text: text,
direction: 'sent',
viewed: false,
via_api: true
)
# send_sms returns nil if successful
if error = message.send_sms
customer.mark_as_invalid! if error.code == 21211
else
# only save the message if the SMS was successfully sent
puts "API_SEND_MESSAGE company_id: #{company.id}, customer_id: #{customer.id}, message_id: #{message.id}, texts_count: #{texts.count}"
message.save
Helper.publish(company.admin, message.create_json_with_extra_attributes(true))
end
end
end
to be clear, the message.send_sms is the method on the message model that actually sends the sms via twilio. thanks!
If you're sending multiple messages, each message takes it's own route to the destination carrier. Even if they're sent in the correct sequence there isn't a guarantee they'll be received at the handset in the correct order. A way to overcome this is using concatenated messages up to 1600 characters (in the US). If you send a long message via the Messages resource it will be received as a single long message. Just make sure you're using the Messages resource:
#client.account.messages.create()
instead of
client.account.sms.messages.create()
You can read more here:
https://www.twilio.com/help/faq/sms/does-twilio-support-concatenated-sms-messages-or-messages-over-160-characters
http://twilio-ruby.readthedocs.org/en/latest/usage/messages.html

Resources