NuBotTrading / src / main / java / com / nubits / nubot / tasks / ALPTask.java

/*
 * Copyright (c) 2015. Nu Development Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package com.nubits.nubot.tasks;

import com.nubits.nubot.ALPClient.ALPService;
import com.nubits.nubot.bot.Global;
import com.nubits.nubot.global.Settings;
import com.nubits.nubot.models.ApiResponse;
import com.nubits.nubot.models.SignedRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.TimerTask;

/*
    Submit an order request to ALP server - only in pool mode
 */
public class ALPTask extends TimerTask {
    private static final Logger LOG = LoggerFactory.getLogger(ALPTask.class.getName());

    public ALPTask() {
        LOG.debug("ALPTask initialized");
    }

    @Override
    public void run() {

        //Try to submit prepare getOrder HTTP request
        LOG.debug("ALPTask : preparing getOrder HTTP request and submitting it to ALP server");
        lockExchangeAndPrepareGetorderHTTPrequest();

        //Update user stats
        //TODO

    }

    private void lockExchangeAndPrepareGetorderHTTPrequest() {
        if (Global.trade.isFree()) {
            Global.trade.setBusy();
            executeGenerateAndSubmitRequest(Global.alpManager);
            Global.trade.setFree();
        } else {
            String method = "ALP createRequest";
            //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 + " has been 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 (Global.trade.isFree()) {
                    LOG.debug("ALPTask : Finally the exchange is free, executing query after " + counter + " attempt. Method=" + method);
                    Global.trade.setBusy();
                    executeGenerateAndSubmitRequest(Global.alpManager);
                    Global.trade.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);
        }

    }

    private void executeGenerateAndSubmitRequest(ALPService alpService) {
        SignedRequest openOrdersRequest = Global.trade.getOpenOrdersRequest(Global.options.getPair());
        LOG.debug("req:" + openOrdersRequest.getReqJSON() + " \n sign (trunkated):" + openOrdersRequest.getSign().substring(0, 10) + "***...");
        ApiResponse signedOrderResponse = alpService.submitOpenOrdersRequest(
                Global.options.apiKey,
                openOrdersRequest.getReqJSON(),
                openOrdersRequest.getSign(),
                "test_exchange",  //TODO change to a real exchange name opt.exchangeName
                Global.options.getPair().getPaymentCurrency().getCode().toLowerCase()
        );

        if (signedOrderResponse.isPositive()) {
            LOG.debug("Positive answer from alpManager.submitOpenOrdersRequest: " + signedOrderResponse.getResponseObject().toString());

            LOG.debug("Sleeping for a " + Settings.ALP_SLEEP_AFTER_PREPARE_HTTPREQUEST + " ms before setting exchange free to give ALP server the time");
            try {
                Thread.sleep(Settings.ALP_SLEEP_AFTER_PREPARE_HTTPREQUEST);
            } catch (InterruptedException e) {
                LOG.error(e.getMessage());
            }
        } else {
            LOG.error("Error from alpManager.submitOpenOrdersRequest: " + signedOrderResponse.getError().toString());
        }
    }

}