XMPP: Performance Degradation List of Chats - ios

We are facing performance degradation in iOS mobile app, which uses XMPPFramework
So literally after authentication we have 2 screens: (list of chats, and if chat from list is pressed - just real chat ).
After user authorised we starts chats’s sync process.
During sync process if I open any chat and trying to send some message or if I am at top of the chart and retrieve previous history page from archive then such requests are executed for a long time.
If syntonisation has finished the requests in such case execute in a short period of time.
But if there are some “scheduled” requests (IQs) for XMPP then on chat screen there is a big gap in receiving previous pages from MAM, or sending messages to the XMPP server.
Not sure what causes XMPP’s slow responsiveness: seems that XMPP executes sequentially requests from input stream.
How can we accelerate XMPP’s responsiveness in such case? Kind of request priority is needed :)
If number of chats is low (less than 10), then we don't see big delay, but if # is around 50 then we observe described above issue.
Should we use extra stream, when an user opens chat? Can it be easily done?
Stream authorisation can't be eliminated if I am not mistaken.
Technical details:
Stream has the following Info:
<stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" id="5454829587182882369" version="1.0" stream1:lang="en" from="xx.com"/>
RECV:
<stream:features xmlns:stream="http://etherx.jabber.org/streams">
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
<session xmlns="urn:ietf:params:xml:ns:xmpp-session">
<optional/>
</session>
<c xmlns="http://jabber.org/protocol/caps" ver="Sd=" node="http://www.process-one.net/en/ejabberd/" hash="sha-1"/>
<sm xmlns="urn:xmpp:sm:2"/>
<sm xmlns="urn:xmpp:sm:3"/>
<csi xmlns="urn:xmpp:csi:0"/>
</stream:features>
Session’s configuration: (2 duration minutes, keepAlive - 120 seconds)
<iq type="set" id="302D4903-9EA7-4AF1-A070-0362B18D69BE">
<push xmlns="p1:push" apns-sandbox="true">
<appid>xxt</appid>
<keepalive max="120"/>
<session duration="2"/>
<body send="all" groupchat="true" from="none"/>
<status type="xa">Text Message when in push mode</status>
<offline>true</offline>
<notification>
<type>applepush</type>
<id>fafa</id>
</notification>
</push>
</iq>
Sync process:
From our backend we get list of conversations, & contacts.
For each chat if it’s MUC we subscribe to it (muc PubSub).
<iq type="set" to="439f1818257dc7eda13a#muc.staging.chat.fitgrid.com" id="BFA024EB-0291-4207-84CC-BD3469568FFE">
<subscribe xmlns="urn:xmpp:mucsub:0" nick="1686a817de5fc4240270#sxx.com">
<event node="urn:xmpp:mucsub:nodes:messages"/>
</subscribe>
</iq>
To get the latest message for each chat we retrieve the latest message from MAM (archive):
<iq type="set" id="6EEB490A-D421-4007-9DA8-E9D2E54DC268" to="ca65cc04b8b8995961f3#muc.xx.com">
<query xmlns="urn:xmpp:mam:2" queryid="15E9F8CC-1FBE-4DCD-982C-8440E0597BFF">
<x xmlns="jabber:x:data" type="submit">
<field var="FORM_TYPE" type="hidden">
<value>urn:xmpp:mam:2</value>
</field>
</x>
<set xmlns="http://jabber.org/protocol/rsm">
<max>1</max>
<before/>
</set>
</query>
</iq>
After messages are received we store them to our local DBs.
We are tracking status of message (sent, read and so on), by using chart markers.
Also there is a small number of Group Rosters’ subscription - it shouldn’t be critical point…
Apparently, we use different threads for processing, we don’t block UI (main) thread.
Any ideas?
P.S. attempt to establish extra stream on selected chat led to the following error (RECV):
<stream:error xmlns:stream="http://etherx.jabber.org/streams">
<conflict xmlns="urn:ietf:params:xml:ns:xmpp-streams" />
<text xmlns="urn:ietf:params:xml:ns:xmpp-streams" lang="en">Replaced by new connection</text>
</stream:error>
But this because of server configuration (in-order processing) https://xmpp.org/rfcs/rfc6120.html#rules-order
Default port is 5222 for TCP connection, seems that extra port should be enabled.

Related

Sending call to multiple clients via conference participants REST API

I am trying to switch our old call flow to the conference and I have ported most of the features to the conference. I am trying to handle incoming calls in cases where I have to ring to multiple agents and disconnect the call after one of them.
Right now I am doing something along the lines of::
Cutomer calls :: call is sent to webhook -> Get list of all active agents and send the twiml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<Dial>
<Client>
<Identity>jane</Identity>
<Parameter name="FirstName" value ="Jane"/>
<Parameter name="LastName" value ="Doe" />
</Client>
<Client>
<IdentityHarry</Identity>
<Parameter name="FirstName" value ="Jane"/>
<Parameter name="LastName" value ="Doe" />
</Client>
</Dial>
</Response>
This way I can ring both ( or more) clients and call drops after the first agent answers.
How I achieve something like this with conference?
What I want is:: ->
Customer calls:: call is captured into webhook =>
customer is dropped into the conference call with some music.
- Dial to clients :: (harry, jane) and connect them to the call.
Is there a way I can do this with via rest api to conference participants api?
Yes, you can do this with the REST API. Your webhook should respond with:
<Response>
<Dial>
<Conference waitUrl="YOUR_HOLDING_MUSIC">YOUR_ROOM_NAME</Conference>
</Dial>
</Response>
The only thing about using the REST API is that it doesn't perform the same as multiple <Client> elements. That is, when someone answers the phone, you have to cancel all the other calls. To do this, you will need to store the call SIDs that are created when you call the API, use status callbacks to know when a participant has connected, and then when you get the first status callback, cancel the other calls. So, something like this to make the calls and get the call sids:
def call_conference(client_name):
client = Client(account_sid, auth_token)
participant = client.conferences('YOUR_ROOM_NAME') \
.participants \
.create(
status_callback='https://myapp.com/events',
status_callback_event=['answered'],
from_='YOUR_TWILIO_NUMBER',
to='client:' + client_name
)
return participant.sid
clients = ["jane", "harry"]
participants = map(call_conference, clients)
Then, when that status callback event fires, filter the call sid from the list of sids you have and cancel the other calls.

Recurly Webhook ID

I am trying to prevent Recurly Webhooks from being executed multiple times if they are retried incorrectly (i.e.: when builds go out and servers time out occasionally). I see in the dashboard that webhooks have unique IDs, but these don't seem to be accessible in the message hash, am I missing something? I'm using Rails for what it's worth.
<?xml version="1.0" encoding="UTF-8"?>
<updated_subscription_notification>
<account>
<account_code>1</account_code>
<username nil="true"></username>
<email>verena#example.com</email>
<first_name>Verena</first_name>
<last_name>Example</last_name>
<company_name nil="true"></company_name>
</account>
<subscription>
<plan>
<plan_code>1dpt</plan_code>
<name>Subscription One</name>
</plan>
<uuid>292332928954ca62fa48048be5ac98ec</uuid>
<state>active</state>
<quantity type="integer">1</quantity>
<total_amount_in_cents type="integer">200</total_amount_in_cents>
<activated_at type="datetime">2010-09-23T22:12:39Z</activated_at>
<canceled_at nil="true" type="datetime"></canceled_at>
<expires_at nil="true" type="datetime"></expires_at>
<current_period_started_at type="datetime">2010-09-23T22:03:30Z</current_period_started_at>
<current_period_ends_at type="datetime">2010-09-24T22:03:30Z</current_period_ends_at>
<trial_started_at nil="true" type="datetime">
</trial_started_at>
<trial_ends_at nil="true" type="datetime">
</trial_ends_at>
<collection_method>automatic</collection_method>
</subscription>
</updated_subscription_notification>
Unfortunately the only way to stop webhooks from being resent is to reply with a 200 status code with 5 seconds.(https://docs.recurly.com/docs/webhooks)
It was 30 seconds but that got changed November 2015 I think.
Anyway I solved it by throwing the message off to a queue and immediately responding with 200 response.
A webhook may be retired several times, however once a successful status code is received by your server, Recurly will stop attempting to resend that notification. Hence, only one webhook will be delivered per event. Also, webhook IDs aren't included in the message hash, they're only found in the UI.

Make the server not send me same messages when i enter a chat room many times?

If I enter into a chat room, I will receive some messages.Then I sign out my account.Of course, I exit the chat room too.But I enter into the same chat room next time, I receive the same messages also.I mean, when I enter into a chat room many times, the server should not send me the same messages,the server should send me messages which I have never received.What should I do??
There is an option in ejabberd.cfg,"history_size",but it does not meet my needs.
Section 7.2.15 of XEP-0045 specifies how you can ask to limit the amount of message history you get when entering the room. When reentering the room, your client could note the timestamp of the last message it got, and ask to get only messages after that time:
<presence
from='hag66#shakespeare.lit/pda'
id='n13mt3l'
to='coven#chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history since='1970-01-01T00:00:00Z'/>
</x>
</presence>

How reliable is yahoo finance?

How reliable is yahoo finance ?
For example the below request :
http://developer.yahoo.com/yql/console/?q=show%20tables&env=store://datatables.org/alltableswithkeys#h=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20%28%22YHOO%22%2C%22AAPL%22%2C%22GOOG%22%2C%22MSFT%22%29
intermittently returns the response : "The current table 'yahoo.finance.quotes' has been blocked. It exceeded the allotted quotas of either time or instructions"
Here is the complete response :
<?xml version="1.0" encoding="UTF-8"?>
<query xmlns:yahoo="http://www.yahooapis.com/v1/base.rng"
yahoo:count="0" yahoo:created="2013-04-08T11:16:18Z" yahoo:lang="en-US">
<diagnostics>
<publiclyCallable>true</publiclyCallable>
<url execution-start-time="24" execution-stop-time="25"
execution-time="1" proxy="DEFAULT"><![CDATA[http://www.datatables.org/yahoo/finance/yahoo.finance.quotes.xml]]></url>
<cache execution-start-time="27" execution-stop-time="27"
execution-time="0" method="GET" type="MEMCACHED"><![CDATA[13c4f8eac77ad886bade5a711c8c1ef5]]></cache>
<javascript name="yahoo.finance.quotes" verb="select"><![CDATA[The current table 'yahoo.finance.quotes' has been blocked. It exceeded the allotted quotas of either time or instructions]]></javascript>
<user-time>28</user-time>
<service-time>1</service-time>
<build-version>35405</build-version>
</diagnostics>
<results/>
</query>
To get a reliable service do I need to sign up and pay ?
To get a reliable service do I need to sign up and pay ?
Here are the limits:
Public OAuth with API Key
Hourly Cap 2,000 20,000
Daily Cap None 100,000
To better understand the rate limits in the above table, let's use the following example. Suppose you create an application that generates around 3,000 requests from each user per hour. You notice though that users are capped at a maximum of 2,000 calls using the public endpoint, so you register an API Key with Yahoo! to use the authenticated/authorized endpoint. Now your users can make 20,000 requests per hour and up to a total of 100,000 requests per day.
oAuth is free.
References
YQL Overview - Yahoo Developer Network
Public API Down Detector

MUC in iOS using robbiehanson XMPPframework

What is the step by step procedure to implement MUC in iOS using robbiehanson XMPPframework?
I tried allocating the room, then activating the stream and joining the room.
But I got a response as follows:
<iq xmlns="jabber:client" from="room#XXXXX.com" to="user#XXXXX.com/34633017701337944885586135" type="error" id="4DD4A6E2-E24F-4D38-AD87-15070B6AD90E"><query xmlns="http://jabber.org/protocol/muc#owner"><x xmlns="jabber:x:data" type="submit"/></query><error code="503" type="cancel"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>
Also received an iq : xmppStream:didReceiveIQ: - 4DD4A6E2-E24F-4D38-AD87-15070B6AD90E
Finally I figured it out. It may help someone. While creating or joining the room, the format should be yourRoomName#conference.YourDomainName.com. The conference is the keyword here.

Resources