How to reuse HTTP connection and share it between Sidekiq background jobs? - ruby-on-rails

My app sends multiple API requests and get responses in background jobs to third party server. For now every job opens new Http connection and closes it after receiving a response.
If it's possible to share this connection between all my app's jobs?
How to keep it alive while a pool of jobs is in progress?
How to close it at the end?
Thanks.

This is what a connection pool is designed for.
https://github.com/mperham/sidekiq/wiki/Advanced-Options#connection-pooling

Related

First http request in iOS networking is slow, subsequent requests are much faster

I'm experiencing slow response times for my first http POST request to my server.
This happens both in Android and iOS networking libraries. (Volley on Android, and Alamofire in iOS).
First response is roughly 0.7s-0.9s, whereas subsequent requests are 0.2s.
I'm guessing this is due to the session being kept-alive by the server, therefore eliminating the need for establishing a new session on each request.
I figure I can make a dummy request when the app starts to start the session, but it doesn't seem very elegant.
I also control the server side (Node.js) so if any configuration needs to be done there I can also try it.
Investigating a little further, I tried sending an https CONNECT request before issuing the first "real" POST request, and the behavior replicates.
After 30 seconds or so, the connection is dropped (probably at the iOS URLSession level, the load balancer is configured to keep connections as 60 seconds).
In theory this makes sense because setting up an https connection takes up several (12 total) packets and I'm on an inter continental connection.
So my solution is to send a CONNECT request when I expect the user to send a regular request.

iOS Networking - HTTP Connections & running in background

I have an app that lets the user send messages with images. A user might hit send, then immediately close their phone or switch to another app.
We were running into an issue that if there's temporarily a bad network connection the message would fail to send. We switched to using NSURLSession backgroundConfigurationWithIdentifier so that backgrounding the app doesn't immediately time out the running request. We switched to using this for all our api requests, thinking that it wouldn't hurt for every request to able to continue in the background if the app were closed at the wrong time.
Fast forward a couple weeks we're noticing all requests seem slow. Using wireshark I just discovered that this background session seems to use a new http connection per request, meaning it requires setting up a TCP connection and new TLS handshake for every request, which was adding a ~500ms latency on every request in our app. This is a pretty big deal but I can't find this behavior documented anywhere, including the link above or Apple's background transfer considerations.
So my question is, is this behavior expected, or am I doing something wrong somewhere? Is there an easy way with NSURLSession to make an HTTP request that will use an existing keep-alive connection if there is one, but can fall back to the backgroundConfiguration if the app gets moved to the background?
NSURLSession is the recommended way to fulfill your use case. Have you tried setting backgroundSessionConfig.discretionary = true
iOS Reference
A Boolean value that determines whether background tasks can be
scheduled at the discretion of the system for optimal performance.
If that doesn't help, I recommend filing a bug with iOS.

iOS Methodology: should I listen to a socket?

I know almost nothing about server/sockets programming. Pardon my ignorance.
I'm making an iOS app that needs to integrate with my web server. The function is analogous to a chat room - multiple clients will be 'connected' and 'listening' to a server session, any one client can send a 'bit', and all clients will receive the 'bit'.
Should I use low-level socket listening and callbacks for this? Is there a better, more power-efficient way? A cool framework I should use?
There are many options for this:
Use a socket to your server and roll your own protocol
Use web sockets and long polling from your app. This means you will fire a HTTP request and your server will keep it open for, let's say, one minute waiting for messages. Take a look here to start: What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?
Use a chat server like Openfire or Ejabberd, which use XMPP, and on your client use XMPPFramework (https://github.com/robbiehanson/XMPPFramework)
Depending on the complexity of your app (authentication? blocking contacts? one-to-many and one-to-one chat?) you can decide on any of the above options. With more details I may be able to help you more.
If you want to be able to receive data while the app is not in the foreground, you will need to use Apple's push notification feature, which is implemented in hardware and the only way to make network connections to a device that is in power saving mode.
There's plenty of documentation how it works, basically the device registers with your server (after asking the user for permission), you use the token it gives you to send a ping to Apple's server, which forwards the ping on to the device. The device can then contact your server and download the actual data you want to send to it.
If you're OK with the server only communicating with your app while the app is running, you have a few options. The easiest is "long polling" where the app sends a HTTP request to the server, using something like this:
NSURL *serverUrl = [NSURL URLWithString:#"http://example.com/"];
NSString *response = [NSString stringWithContentsOfURL:serverUrl usedEncoding:NULL error:NULL];
NSLog(#"%#", response);
Instead of the server responding instantly, it can wait around for a long time (for example 45 seconds) until it has something to send to the device, then it responds with the information.
If 45 seconds are reached without having anything to send, it just sends a nothing response and the phone immediately opens up a new URL request to the same URL. This keeps the server from having a bunch of old/abandoned connections open. Typically connections are dropped after 60 seconds, so you want to respond before that time limit is reached. Obviously you'll want to do the request on a background queue with NSOperationQueue.
There are other options, you could use sockets, you could start a web server on a custom HTTP port on the phone (eg: https://github.com/robbiehanson/CocoaHTTPServer). But long polling is often the easiest choice.
Most apps use a combination of push notifications and something else.

Kill off connections that are not consuming Rabbitmq

I am having a bit of an issue where if the client crashes or if it loses connectivity it does not properly close the connection. This results in several idle connections that keep adding up. The client I am using rabbitmq-c does not support heartbeats yet therefore I cannot use that as a possible solution.
Is there anyway to kill off any connections that are not at the same time consuming a queue?
I found out the client was not setting a timeout time to the server therefore the connections were always being kept open. I also updated the client to support Heartbeats so there is now two ways the connections can be killed instead of being kept open.

socket connection in iOS and background tasks

I am designing an app that needs to exchange data in real time over network and I am planning to use socket connection to achieve this. To keep the socket connection open in background I plan to declare my app as a VOIP app (I already know apple's rule prohibiting this and willing to take the risk), and use keepAliveTimeout to keep connections alive.
Now can I declare and own a socket which will listen to any incoming data or I have to use an existing/specific socket given by Apple? Also is the port unique per app or per phone? Means if my app is continuing in background and also a call comes over Skype would they interfere with each other?
Thanks in advance for response. Help would be appreciated.

Resources