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

Running a task every few seconds #5098

Open
ghnp5 opened this issue Jul 7, 2023 · 4 comments
Open

Running a task every few seconds #5098

ghnp5 opened this issue Jul 7, 2023 · 4 comments

Comments

@ghnp5
Copy link

ghnp5 commented Jul 7, 2023

Hello,

I'm trying to have a task run every 5 seconds, to prevent the database connection from becoming stale.

$scheduler = new Scheduler();

$scheduler->add(function () : void {
	while (true) {
		try {
			write_log('Checking stale: '.(time() - Database::getLastAccessedTime()));
			if (time() - Database::getLastAccessedTime() > 60) {
				write_log('Reconnecting database...');
				Database::connect();
			}

			Coroutine::sleep(5);
		} catch (\Throwable $e) {
			write_log($e::class.': '.$e->getMessage());
		}
	}
});

$scheduler->start();

However, for some reason, this doesn't seem to run, or gets stuck, until I restart the docker container, where it appears to run and log at that point.

Is it because I'm running blocking operations here?


I also tried:

$timerId = Timer::tick(5000, function () : void {
	try {
		write_log('Checking stale: '.(time() - Database::getLastAccessedTime()));
		if (time() - Database::getLastAccessedTime() > 60) {
			write_log('Reconnecting database...');
			Database::connect();
		}
	} catch (\Throwable $e) {
		write_log($e::class.': '.$e->getMessage());
	}
});

but this doesn't seem to run at all.


I'm also confused how to run Coroutine, with create, run and resume.. :)


Can I run blocking operations in Scheduler and/or Coroutine ?

What's the best way to run a simple task every 5 seconds (or every minute), that accepts blocking operations, and has access to the variables in the global scope, such as the global database connection?

Thank you very much!

@NathanFreeman
Copy link
Member

NathanFreeman commented Jul 7, 2023

Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);

$connection = null;
$timerId = Timer::tick(5000, function () : void {
	try {
		write_log('Checking stale: '.(time() - Database::getLastAccessedTime()));
		if (time() - Database::getLastAccessedTime() > 60) {
		      global $connection;
                      write_log('Reconnecting database...');
		      $connection = Database::connect();
		}
	} catch (\Throwable $e) {
		write_log($e::class.': '.$e->getMessage());
	}
});
Swoole\Event::wait();

@NathanFreeman
Copy link
Member

You can not run blocking operations in the timer otherwise it will affect the next task execution if you have not enabled coroutine hook.

@ghnp5
Copy link
Author

ghnp5 commented Jul 7, 2023

Thank you very much.

What you are saying is that if I put Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);, then I can run blocking operations, is that correct?

I made the changes as suggested, but it is still not triggering, for some reason :(
(at least the log isn't writing)

@NathanFreeman
Copy link
Member

NathanFreeman commented Jul 7, 2023

The PHP blocking functions will turn to non-blocking function if you put Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);

You can execute your code in a non docker environment to find where the problem is.

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

2 participants