Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I'm getting output 'Alarm Clock' and code refusing to do small loop #20

Open
StevenFlecha opened this issue May 23, 2021 · 12 comments
Open

Comments

@StevenFlecha
Copy link

StevenFlecha commented May 23, 2021

Hey,

Not an issue but more of a question.

I'm just testing a bit and currently have this code:

$binance->keysecret([
    'key' => $binanceConfig['key'],
    'secret' => $binanceConfig['secret'],
]);

$binance->subscribe([
    'btcusdt@markPrice'
]);

$x = 15;
while($x > 0){
    echo "<br />run $x";
    $data = $binance->getSubscribes();
    echo "<pre>";
    print_r(json_encode($data));
    echo "</pre>\n\n";
    sleep(3);
    $x = $x - 1;
}

$binance->unsubscribe([
    'btcusdt@markPrice'
]);

And this is the result: https://dl.dropbox.com/s/zxu4sfcjy7931h7/shot_210523_175315.png

I would expect it to run 15 times.. but it runs only once and it outputs this text 'Alarm Clock' it does not come from my code.. I searched your code based and the string 'Alarm Clock' is also nowhere to be found - so I have no idea where that is coming from.

Any ideas what is happening here?

Thanks!
Steven

@zhouaini528
Copy link
Owner

zhouaini528 commented May 24, 2021

Thank you for your feedback. I'll check it. The problem is to quote it workerman
You can try this way

//The third way is to guard the process
        $binance->getSubscribes(function($data){
            print_r(json_encode($data));
        },true);

@StevenFlecha
Copy link
Author

Yeah I found out it comes from pcntl_alarm
Haven't yet completely figured out why and how.

I keep getting it for either:
$binance->getSubscribes();
And for

$binance->getSubscribe([
'btcusdt@markPrice'
],function($data) use ($fundingRate) {
if(is_array($data)){
$fundingRate = $data['btcusdt@markPrice']['data']['r'];
}

    echo "Data: <pre>";
    print_r($data);
    echo "</pre>\n\n";
});

Will try and use the 'guard' version.

@zhouaini528
Copy link
Owner

zhouaini528 commented May 24, 2021

You try this 'symbol=btcusdt@depth' and comment out the code 'sleep(3)'.The main problem is sleep.

$binance->keysecret([
    'key' => $binanceConfig['key'],
    'secret' => $binanceConfig['secret'],
]);

$binance->subscribe([
    'btcusdt@depth'
]);

$x = 15;
while($x > 0){
    echo "<br />run $x";
    $data = $binance->getSubscribes();
    echo "<pre>";
    print_r(json_encode($data));
    echo "</pre>\n\n";
    //sleep(3);
    $x = $x - 1;
}

$binance->unsubscribe([
    'btcusdt@depth'
]);

You need to execute it twice, because the first time you need to subscribe, the second time you can get the data
So I suggest you use this method

//The third way is to guard the process
        $binance->getSubscribes(function($data){
            print_r(json_encode($data));
        },true);

@StevenFlecha
Copy link
Author

I read that pcntl_alarm gets triggered instantly when using sleep(..) indeed so removed that.

I then tried to use the 'guard' way to retrieve the data but then I get this problem:
https://dl.dropbox.com/s/730vuiyiaukczib/shot_210523_230907.png
When calling getSubscribes using the 'guard' method it gives that error each time.

When I use

    $binance->getSubscribe([
        'btcusdt@markPrice'
    ], function($data) use ($fundingRate){
        echo "Data: <pre>";
        print_r($data);
        echo "</pre>\n\n";

        if(is_array($data)){
            $fundingRate = $data['btcusdt@markPrice']['data']['r'];
        }
    }, true);

I also get the 'Usage: php yourfile [mode]' error.

When I use it without ', true' it runs.. but even then it sometimes works and sometimes doesn't.

Example when doesn't work:
https://dl.dropbox.com/s/9733m4jz585zlt3/shot_210523_231708.png
The callback function is never called. (I set it to 20 runs)

Then I tried again (this time with 50 run):
https://dl.dropbox.com/s/klzvqbo5o0je0s1/shot_210523_231814.png
This time it worked in first run.

BTW if I change btcusdt@markPrice to symbol=btcusdt@markPrice then it doesn't work at all anymore.

@StevenFlecha
Copy link
Author

ok so I have it working ... sometimes. When I run the script sometimes it works and sometimes I still get 'Alarm clock'

my code

function Finish($binance, $fundingRate){
    $fundingRate = sprintf('%f', $fundingRate*100);
    $fundingRate = rtrim($fundingRate,'0');
    echo "Funding rate for btcusdt is: ".$fundingRate."%";

    echo "\n going to unsub now \n";
    $binance->unsubscribe([
        'btcusdt@markPrice'
    ]);


    echo "<br />Stopping server:\n";
    $a = exec("php binanceSocketServer.php stop");
    if($a !== false){
        echo "<br /> server stopped\n";
    }
    else{
        echo "failed to stop Binance Socket server.. exitting\n";
        exit;
    }
}

$run = true;
while($run === true){
    $t = $binance->getSubscribe([
        'btcusdt@markPrice'
    ], function($data) use ($fundingRate, $run, $binance){

        //echo "\nData: <pre>";
        //print_r($data);
        //echo "</pre>\n\n";

        if(is_array($data)){
            $fundingRate = $data['btcusdt@markPrice']['data']['r'];
            echo "Fundingrate: $fundingRate% \n";
            Finish($binance, $fundingRate);
        }
    });

    if( isset($t['btcusdt@markPrice']['data']['r']) ) break;

}

I feel I'm doing something wrong conceptually - it can't be using sockets and Binance API are so unreliable that sometimes it works and sometimes it doesn't:
https://dl.dropbox.com/s/nsp8mudsz719mwv/shot_210524_003639.png

Thanks for the help!

@zhouaini528
Copy link
Owner

I'm sorry I just told you wrong. I subscribed to'btcusdt@markPrice' but the exchange did not push data, so the data cannot be obtained by'getSubscribe'. The code I gave is to let you subscribe to it'btcusdt@depth', so that you can better analyze the SDK problem or the exchange problem.You copy the code and run directly demo

For the stability and maintainability of websocket, I suggest that you should use a cache method for storage, such as redis. Then read the data from redis. Here is a use case to get the market quotation websocket-market (you need to translate it) You can see the source code.

@numairawan
Copy link
Contributor

numairawan commented Jun 6, 2021

@zhouaini528 and @StevenFlecha did you guys fixed the issue? Facing the same problem,

loop is not working when getting the data from websockets or subscribing the stream, i also tried the third way to guard the processor but no luck.



$getTickerPrice = '';
$binanceWSSpot->getSubscribe([$symbol],function($data){
    $getTickerPrice = $data;
},true);


//$getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);

 

if (empty($getTickerPrice)) {
     $binanceWSSpot->subscribe(["$symbol"]);
} else {
    $tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
    $tickerPrice = str_replace('"', "", $tickerPrice);


@zhouaini528
Copy link
Owner

zhouaini528 commented Jun 7, 2021

@numairawan
The 'Alarm Clock' problem occurred because I used the Workerman shared process component. To solve this problem, we need to adopt the daemon mode of the component (client_spot.php start -d).

The first and second methods I have given can only be executed once in the current process life cycle. If the loop mode is used, the "Alarm Clock" will appear, so the best method is to use the third method.

//The first way
$data=$binance->getSubscribe();
print_r(json_encode($data));

//The second way callback
$binance->getSubscribe(function($data){
    print_r(json_encode($data));
});

//****Recommended way
//The third way is to guard the process
$binance->getSubscribe(function($data){
    print_r(json_encode($data));
},true);

The third method uses the closure method. You cannot use variables in this way. The correct way is as follows.

$getTickerPrice = '';
$binanceWSSpot->getSubscribe([$symbol],function($data) use($getTickerPrice,$binanceWSSpot){
	$getTickerPrice = $data;
	//$getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);
	if (empty($getTickerPrice)) {
	$binanceWSSpot->subscribe(["$symbol"]);
	} else {
	$tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
	$tickerPrice = str_replace('"', "", $tickerPrice);
},true);

@numairawan
Copy link
Contributor

numairawan commented Jun 7, 2021

@zhouaini528 did you update something? It was working fine before like a months ago. I am using the loop to get and update the PnL of open trades. Tried your thirdway, yeah its working but its not working inside any loop. Also i need to start the processor with workerman.

$binanceWSSpot->getSubscribe([$symbol],function($data) use($getTickerPrice,$binanceWSSpot){
	$getTickerPrice = $data;
	//$getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);
	if (empty($getTickerPrice)) {
	$binanceWSSpot->subscribe(["$symbol"]);
	} else {
	$tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
	$tickerPrice = str_replace('"', "", $tickerPrice);
}
},true);

When i start the process, loop dont work. But if i remove "true" processor stopped and print alarm clock.

$binanceWSSpot->getSubscribe([$symbol],function($data) use($getTickerPrice,$binanceWSSpot){
	$getTickerPrice = $data;
	//$getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);
	if (empty($getTickerPrice)) {
	$binanceWSSpot->subscribe(["$symbol"]);
	} else {
	$tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
	$tickerPrice = str_replace('"', "", $tickerPrice);
}
});

image

here is the simple code that was working fine few months back. (sleep is not the issue, even if i dont use delay the loop will stop after 20 to 30 loops)

 while (true){
   $getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);
$tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
	$tickerPrice = str_replace('"', "", $tickerPrice);

    print $tickerPrice;
    sleep(1);
 }

Check this out.

$x = 10;
while($x > 0){

$symbol = 'btcusdt@miniTicker';
$binanceWSSpot->getSubscribe([$symbol],function($data) use ($binanceWSSpot, $symbol){
	$getTickerPrice = $data;
	//$getTickerPrice = $binanceWSSpot->getSubscribe(["$symbol"]);
	if (empty($getTickerPrice)) {
	$binanceWSSpot->subscribe(["$symbol"]);
	} else {
	$tickerPrice = json_encode($getTickerPrice["$symbol"]['data']['c']);
	$tickerPrice = str_replace('"', "", $tickerPrice);

    print $tickerPrice  . PHP_EOL;

	}
	sleep(1);
},true);


print 'This code never work' . PHP_EOL;

$x = $x - 1;
}

Result;

image

@zhouaini528
Copy link
Owner

zhouaini528 commented Jun 8, 2021

@numairawan
I use the Workerman sdk. The official documentation explains that there can be no infinite loop or sleep. "If you use GlobalData/Client in the Workerman environment, please instantiate the GlobalData/Client object in the onXXX callback, for example, instantiate it in onWorkerStart ."

The first and second methods of obtaining data are suitable for one-time access. If you want the current process to obtain data multiple times, you must use the "Timer" timer to obtain. You can see my source code (Here). The third method is "Timer".

Although the demo you gave is successful, its efficiency is not high, so this method is not recommended.

@zhouaini528
Copy link
Owner

zhouaini528 commented Jun 9, 2021

@numairawan @StevenFlecha
I have found the problem, because I use 'workerman', and it uses 'pcntl_alarm', it will alarm when using sleep, the correct solution is as follows

while(1){
    pcntl_alarm(0);
    sleep(1);
    $data=$binance->getSubscribes();
    print_r(json_encode($data));
}

@numairawan
Copy link
Contributor

@zhouaini528 Thank you very much now its working fine, but sometimes getSubscribe returning the same value for 10 to 30 minutes, to fix it in loop, subscribe to the same stream in each loop will fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants