I have a case where some users end up in a loop of requesting #GET API call too often.
Too often = 10-20x every second.
Currently, I've not located the problem and it seems that it's not going to be an easy fix, but I was wondering, is there a possibility to set some kind of limitations on Retrofit2, where if the app goes into some kind of loop where single API request is called so many times, it actually ignores these requests, for instance, do 1-5x same requests in a second max. or something similar?
How could this be done (from a networking library settings perspective)? (Till I find the root cause, I'd like to protect backend)
According the this answer you can use dispatcher as below:
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(dispatcher)
.build()
After then you will be able to send one request on a time.
Related
Is there a solution to create a one second delay between the quests we send with Okhttp3?
This means, for example, if the user sent 10 requests, check if the previous request interval was one second by now, otherwise the app will wait for one second, then do the sending work.
I checked this link but it did not work:
How can I queue up and delay retrofit requests to avoid hitting an api rate limit?
The shown examples in linked question didn't work for me too. So I made a research and found this OkHttp Delay Interceptor library. You can just call .addInterceptor(DelayInterceptor(Long, TimeUnit)) method on your's OkHttp client builder object to set a specific delay for requests.
Apologies if this is too simple of a question, I am new to using remote data sources.
I assume Enqueue is running on background threads instead of main thread, but which is faster and better for optimization? As I understand using Runnables will take up more code, but I have seen multiple apps built with such a method, is it better than the simpler Enqueue method?
Retrofit will use underlying OkHttp to make calls to the server. Enqueue is tested and it is always better to use the globally recognized by developers with performance testing and lots of other aspects around it. It also covers your ExecutorService without you having to write the implementation for it. I'll add few points for readers new to OkHttp.
new Request.Builder().url(endpoint).build() creates the request but
doesn't send anything.
client.newCall(request).execute() sends the request and waits for
the response, but doesn't download the response, only its headers so
you can check things like response.isSuccessful() immediately.
response.body().string() downloads the body of the response and
returns a string.
You can push your own implementation of ExecutorService like this
OkHttpClient.Builder().dispatcher(Dispatcher(executorService)).build()
I want to upload some objects to a server. I'm using work manager and uniqueWork to avoid uploading duplicate objects. There is a constraint on the work so that they only operate when there is internet connectivity. The problem is I want each of these objects to upload one at a time, but all the work happens at once.
I know that I can use beginWith and workContinuations to perform work in sequence, but unfortunately multiple objects can be created at different times, so I do not have access to all the work at the time of creating the work.
val workRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(networkConstraint)
.build()
WorkManager.getInstance()
.enqueueUniqueWork(uniqueName, ExistingWorkPolicy.KEEP, workRequest)
I assumed enqueue meant that all the work would happen one at a time like a queue. Is there a way to make it work that way?
You can use WorkManager's UniqueWork construct to be able to enqueue work so that it is executed only once. The Unique work is identified by the uniqueName.
In your case you should use a different ExistingWorkPollicy, as explained in the documentation: ExistingWorkPollicy.APPEND. This ensure that your new request is appended after other requests using the same uniqueName (this actually creates a chain of work).
val workRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setConstraints(networkConstraint)
.build()
WorkManager.getInstance()
.enqueueUniqueWork(uniqueName, ExistingWorkPolicy.APPEND, workRequest)
What is the best way to make a deferred simple okhttp3 web request like:
Request request = Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
that gets executed as soon as a client goes online and only then to handle result?
For example, client makes change to the data locally and this change should be posted on server. But there are cases when user does it offline, but we still have to handle it.
You can use a broadcast receiver which listen for internet connectivity changes, and Deferred library for deferring the request Jdeferred.
If use of deferred is too much work and overkill, You can use a conutdownlatch and
wait on separate thread until, the connectivity change, but the wait time can be huge, so chose wisely.
You can also consider CompletableFuture. But this is available from api 24 only
Let me know if you need more clarification.
I'm using OkHttp at the first time. I see the tutorial said that If wanna use Response Caching, I must call new OkHttpClient() exactly once (a singleton instance). OkhttpClient is thread-safe by synchronized methods. But in my application, there are many threads connects to the network to get remote data simultaneously, some threads must wait for a thread have done getting data to execute its operation.
So Is it's performance not better than normal?
If yes, If I don't enable Reponse Caching, should I call new OkHttpClient() many times for better performance?
Thanks
For the best performance, share a single OkHttpClient instance. This allows your cache to be shared, and in the future when we implement fancy joining & cancelling it’ll allow outgoing requests to be merged.