1

I'm making multiple requests to Amazon Web Services. I'm getting the 503 error because I'm making too many request too quickly. I want to know how to set the time-out between different requests, not the same ones. I am not looking to set the retry policy. I am also not looking to time-trigger individual requests. I want to time the interval between requests. The reason is that I am looping so quickly and making so many requests, that timing-triggering them is equivalent to submitting them all that the same time. The whole point is to space the requests out evenly.

the_prole
  • 8,275
  • 16
  • 78
  • 163

4 Answers4

1

assuming you have Request object , before adding the request to the queue you can do this

request.setRetryPolicy(new DefaultRetryPolicy(5000, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

the 5000 indicates the time between each request in ms the 5 is the number of times you want to send the request before it gives you timeout

for the sake of someone seeing this, this is how to use timers to manually seclude a task

 Timer timer = new Timer();
    final Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            // Update UI here if u need
        }
    };
    TimerTask task = new TimerTask () {
        @Override
        public void run () {
           //send requests according to your logic here
        }
    };
    timer.schedule(task, 0, 60000); // 60000 = 1 min
Hassan Khallouf
  • 1,170
  • 1
  • 13
  • 30
  • I tried this. I will try again, but this is a "retry" policy, meaning this is the timeout between "retry" requests, not separate requests. – the_prole Dec 21 '15 at 02:17
  • so let me get this straight, you are sending DIFFERENT requests but you want to time them so they are not sent one after another directly? if that's the case you should have said so, but I guess you need to handle this manually from your code, you decide according to YOUR criteria when to send or not – Hassan Khallouf Dec 21 '15 at 02:20
  • That is what I said. Yes, I will decide from my own criteria if that is possible. – the_prole Dec 21 '15 at 02:21
  • I don't think this is volley related, there are so many ways to do this, but what is your criteria exactly, you can run them on another thread and sleep between requests, do then in a Timer and handlers , the timer is basically a class that executes something every x of time and the handler to to something on your UI thread after that, for example I'm using timers in my app to send a refresh every 10 seconds, if this is what you want I can show u the code – Hassan Khallouf Dec 21 '15 at 02:25
  • I have been trying to use the sleeper method for the last 30 minutes. I'm not sure it's working that way I expected. I can look into the timer method on my own. Thanks. – the_prole Dec 21 '15 at 02:27
1

Since you don't show how you made multiple requests, so I suggest you refer to the following sample, then try applying to your code. Hope it helps!

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);            

        final RequestQueue queue = Volley.newRequestQueue(this);
        final String url = "http://google.com";
        final Handler handler = new Handler();
        for (int i = 0; i <= 5; i++) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    StringRequest request = new StringRequest(url, new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            Log.i("onResponse", response);                                
                        }
                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            Log.e("onErrorResponse", error.toString());
                        }
                    });    
                    queue.add(request);
                }
            }, 2000); // 2000 miliseconds
        }
    }
BNK
  • 23,994
  • 8
  • 77
  • 87
  • Thanks BNK. But your method didn't work, assuming I used it correctly. I posted my code in an edit. I tried using the sleep method, but it makes the whole application sleep, although it does work. – the_prole Dec 21 '15 at 02:57
  • If you want to send the same request (I mean `StringRequest request`) many times, my code works, I checked it before posting here :) – BNK Dec 21 '15 at 03:36
  • I think I see what my problem is. I am looping and making requests very quickly. By the time a timed request is triggered, so is the next one, and the one after that, etc. I can time a request from point it is submitted to the queue, but I can't set the time between requests. – the_prole Dec 21 '15 at 03:56
  • I edited my question. Do you still think your solution addresses the question? – the_prole Dec 21 '15 at 04:03
  • I am afraid it's not. For many different requests, IMO, inside `onResponse` of 1st request, you put `handler.postDelayed` in which the 2nd request will be called, then inside `onResponse` of 2nd request, you put `handler.postDelayed` in which the 3rd request will be called, so on... however, perhaps it's not beautiful or not good code :) – BNK Dec 21 '15 at 04:38
  • Your method is good! I would prefer to use `Thread.sleep(1000);` etc. What I realized eventually, was that I need to make an array list of type request objects with a loop, and then submit requests individually. I can't do what I'm trying to do inside the loop itself. If I did, I would be submitting the requests all the same time whether I used `handler` or `sleeper`. Thanks anyways. – the_prole Dec 21 '15 at 04:42
  • I am not sure which one is better, however, you can read http://stackoverflow.com/questions/18712992/handler-postdelayed-and-thread-sleep for more info – BNK Dec 21 '15 at 04:50
0

Was struggling with this too, til I got some help from another developer. Try something like this:

public class HTTP {
    String getUrl;
    Context context;
    YTVisualizer ytv;
    int numberOfCurrentRequests = 0;

    public HTTP(Context context, YTVisualizer ytv){
        this.context = context;
        this.ytv = ytv;
    }

    public void get(final String url) {
        numberOfCurrentRequests++;

        new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.sleep(250 * numberOfCurrentRequests);
                } catch(InterruptedException e) {
                    e.printStackTrace();
                }

                // Instantiate the RequestQueue.
                RequestQueue queue = Volley.newRequestQueue(context);

                String[] parts = url.split("=");
                final String key = parts[1];

                // Request a string response from the provided URL.
                StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
                        new Response.Listener<String>() {
                            @Override
                            //runs in thread main
                            public void onResponse(String response) {
                                Log.i("Response", response);

                                String title = new String();

                                try {
                                    JSONObject obj = new JSONObject(response);
                                    Iterator<String> str = obj.keys();
                                    String key = str.next();
                                    title = obj.getString(key);

                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }

                                ytv.SetVideosFromHTTPClass(key, title, response);

                                numberOfCurrentRequests--;
                            }
                        }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(context, "Error: are you connected to the internet?", Toast.LENGTH_SHORT).show();
                        numberOfCurrentRequests--;
                    }
                });

                // Add the request to the RequestQueue.
                queue.add(stringRequest);
            }
        }).start();
    }
}

It pauses inbetween proportional to the amount of current requests. The 1st one sleeps .25 s, the 2nd one .5s, the third one .75s, and so on. Theyre all scheduled in order.

0

I know this is an old question, but here is a solution written in Kotlin:

Inside your class with the RequestQueue, you can add

val throttleTimeout : Long = 100L
private val throttleQueue : ArrayBlockingQueue<Request<*>> = ArrayBlockingQueue(100);
private val throttleThread = Thread {
    while(true){
        val rqst = throttleQueue.take()
        requestQueue?.add(rqst)
        Thread.sleep(throttleTimeout)
    }
}

fun <T> addToThrottledRequestQueue(request: Request<T>, tag: String){
    request.tag = if (TextUtils.isEmpty(tag)) TAG else tag
    throttleQueue.put(request)
}

And just make sure to start the thread in your class initialization. You can also mix this with a function to create non-throttled request and mix them together.

fun <T> addToRequestQueue(request: Request<T>, tag: String) {
    request.tag = if (TextUtils.isEmpty(tag)) TAG else tag
    requestQueue?.add(request)
}

The addToThrottledRequestQueue function will make sure those requests are throttled while other requests can flow freely.