Handle concurrent requests correctly

Issue #627 resolved
Desrever Nu created an issue

We have been postponing this for long now, but it is time today I crack down on it. We have one Global TradeInterface object, and multiple threads access to it. with GUI number of threads increased, so we are ending up with a lot of situation where

[main] ERROR - ApiError [5 : Nonce must be greater than 1430207994618. You provided 1430207994390.] [c.n.n.t.WrapperTestUtils:238]

because another thread completed the request...

This is what can happen (and it is happning) currently , two threads A and B, unaware of each other existance :

A creates a nonce=1B creates a nonce=2Server receives B first and sets the upper limit to 2B succeeds, A fails

I am looking for a solid solution to the problem above. There are many possible ways but each one is delicate

The solution requires an external object, global, that is aware of all requests that are being submitted. So let's call this object 'oracle'

oracle has a method requestNonce() and a boolean flag :isSomeoneElseDoingAnAPIRequest so now we could leverage the method that all wrappers uses to make calls :

getQuery()

the question is : how?

Comments (5)

  1. Desrever Nu reporter

    new query() method

      public String query(String base, String method, AbstractMap<String, String> args, boolean needAuth, boolean isGet) {
            String queryResult = TOKEN_BAD_RETURN; //Will return this string in case it fails
            if (exchange.getLiveData().isConnected()) {
                if (exchange.isFree()) {
                    exchange.setBusy();
                    queryResult = service.executeQuery(base, method, args, needAuth, isGet);
                    exchange.setFree();
                } else {
                    //Another thread is probably executing a query. Init the retry procedure
                    long sleeptime = Settings.RETRY_SLEEP_INCREMENT * 1;
                    int counter = 0;
                    long startTimeStamp = System.currentTimeMillis();
                    LOG.debug(method + " blocked, another call is being processed ");
                    boolean exit = false;
                    do {
                        counter++;
                        sleeptime = counter * Settings.RETRY_SLEEP_INCREMENT; //Increase sleep time
                        sleeptime += (int) (Math.random() * 200) - 100;// Add +- 100 ms random to facilitate competition
                        LOG.debug("Retrying for the " + counter + " time. Sleep for " + sleeptime + "; Method=" + method);
                        try {
                            Thread.sleep(sleeptime);
                        } catch (InterruptedException e) {
                            LOG.error(e.toString());
                        }
    
                        //Try executing the call
                        if (exchange.isFree()) {
                            LOG.debug("Finally the exchange is free, executing query after " + counter + " attempt. Method=" + method);
                            exchange.setBusy();
                            queryResult = service.executeQuery(base, method, args, needAuth, isGet);
                            exchange.setFree();
                            break; //Exit loop
                        } else {
                            LOG.debug("Exchange still busy : " + counter + " .Will retry soon; Method=" + method);
                            exit = false;
                        }
                        if (System.currentTimeMillis() - startTimeStamp >= Settings.TIMEOUT_QUERY_RETRY) {
                            exit = true;
                            LOG.error("Method=" + method + " failed too many times and timed out. attempts = " + counter);
                        }
                    } while (!exit);
                }
            } else {
                LOG.error("The bot will not execute the query, there is no connection to BitcoinCoId");
                queryResult = TOKEN_BAD_RETURN;
            }
            return queryResult;
        }
    
  2. Log in to comment