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
start_background_task #462
Comments
Can you just start your background task(s) independently of the server? I don't understand why you want to associate those tasks with the starting of the server, just start the server and your task at the same time. |
Thank you for answering my question! The task have to continuously broadcast important messages to all Web clients by using Flask-SocketIO, if I start my tasks independently of the flask server , the task thread is independent from flask server thread, it seems that the message could not reach web clients by using the method socketio.emit(). The job of the task is listening a stream port and when it receives the stream from outside, it will send it to all web clients. In your examples, starting a task needs web user to connect firstly. Like this :
In my code, even though there is no web user connecting after staring server, the task thread have to run. |
Can you start the thread in the global scope, after the |
I use the flask-apscheduler to start the task thread add() like this:
But, the web clients cannot receive the message from add(). |
The problem is that apscheduler is going to start a thread, and you can't use threads when you work with eventlet. I have never used apshceduler with eventlet, but if you want to use both together, your only hope is that apscheduler is compatible with eventlet's monkey patching. See http://eventlet.net/doc/patching.html for info on monkey patching. |
I tried to add mokey_patch() ahead of manage.py like this:
then the server started |
Another approach could be to run the background task independently of the flask server, and to have the task access a HTTP endpoint on the flask server in order to emit a message to the clients. We wanted to do something like this and have other processes inject messages which would go to all the front end socketio clients. We quickly realized that it was much better to have Flask be the only thing which could emit, and have other processes hit an endpoint which calls emit() in the Flask code. |
If the Flask-SocketIO project can emit message to all clients by other processes, that's a very useful job. I have reviewed issuses of Flask-SOketIO project, I found many issuses are also talking about that emiting message by other processes or threads. When would the project update about that? |
@shitone emitting from an external process is covered in the docs: https://flask-socketio.readthedocs.io/en/latest/#emitting-from-an-external-process |
@miguelgrinberg As the docs, the socketio server send messages to Redis or RMQ, but I don't understand that web clients how to receive those messages from Redis or RMQ through websockets. |
@shitone No, that's not how it works. You have the Flask-SocketIO server and you have another process. The Redis or RabiitMQ queue is in between the two. When you call |
@miguelgrinberg Oh, got it, thanks! I have studied about Celery with Flask-SocketIO. I find an example code combining Celery and Flask-SocketIO like this:
In the example, the celery task(like as another process) and the Flask-IO server use the same instance |
There is one difference. In the Flask-SocketIO server, you initialize socket.io as follows:
while on the Celery worker, you have to do this instead:
When the |
In other words, if I want to use |
@shitone I think the way you are putting it is a bit confusing, at least to me. You have to have only one |
@miguelgrinberg Today I setup RabbitMQ add
But when I visit the website, the webpage is blocking. If I delete the parameter message_queue, the website recovery。Do you known what is the reason? The blocking webpages all contain websockets JS codes like |
Are you using eventlet or gevent? If you are, then you need to monkey patch the standard library for rabbitmq to work. |
@miguelgrinberg I have used eventlet like this:
But after I add monkey patch, even the login webpage is blocking firstly. |
Are you sure you have a RabbitMQ service at the address you are using? Do you see the connection from the Rabbit side? |
@miguelgrinberg Yes, I have. I cut some pictures of RMQ to you. |
Okay, so Rabbit is okay. Is the web server running? Does the |
@miguelgrinberg Now I add a print statement
But when I visited the login webpage, the console did not print it. |
I have to think there is something wrong in your setup, but I can't really tell you. If you have your complete application on GitHub or other public repository, I can take a closer look. |
@miguelgrinberg I have pushed my project on my GitHub, the project name is mdep. |
@shitone thanks. Can you give me the output of |
@miguelgrinberg Here is the output of
|
@miguelgrinberg Is there something wrong in my setup? I have debugged two days and searched information online, however, I had no progress. |
@shitone I think the problem is the mysql package that you are using, which is written in C. That is likely incompatible with eventlet. I recommend you switch to a pure python mysql driver, such as pymysql. |
@miguelgrinberg Thks! I have |
@miguelgrinberg I concluded four appearances about this problem:
|
@shitone the The RabbitMQ is another possible blocking problem, if you are using |
@miguelgrinberg I have tried pymysql with monkey patch in manage.py (without RMQ), but I still can't access login page. This problem makes me depressing. I don't use virtualenv now, and my python version is 2.7, and I use PyCharm to develop. I doesn't install librabbitmq. When I tried pymysql, I removed |
@shitone did you try switching to sqlite as I indicated above? That will tell us if the problem is still MySQL related or not. I was able to get to the login prompt after removing |
@miguelgrinberg I try switching to |
Your new version works fine for me. I only changed the database name, then I did:
And I can then connect and see the login prompt. |
@miguelgrinberg Thks!I find the cause of this problem just now. The debug model makes app block. After I remove |
Oh, interesting, I did not try to run the application with debug mode, so I never saw this. But now I do see the problem. It appears there is some sort of incompatibility between eventlet and watchdog, the package that the reloader uses to detect changes in files. Try removing watchdog, that forces Flask to use another method to detect changed files. That fixed the problem for me. |
@miguelgrinberg I have a similar issue. def initialize(self):
super(PubSubManager, self).initialize()
if not self.write_only:
self.thread = self.server.start_background_task(self._thread)
self.server.logger.info(self.name + ' backend initialized.') The issue only shows when using the queues obviously. I am using Python 3.5 not sure if that's the issue. |
@jpoutrin are you basing your assessment on what you see on your debugger, or is there something not working correctly? Debuggers tend to not work well when used with async frameworks, they need to have specific support for them, so I would not trust a thread list shown by the debugger, when in reality when using an async framework all the threads are "green" threads, which is not the same thing. |
@miguelgrinberg well, I cannot see the next logging statement: Not sure about green thread (my python background is not up to that level yet ;) ) - what does that mean? |
You are using a message queue, correct? The python package that talks to that queue could be incompatible with eventlet. To make it compatible, you have to "monkey-patch" the python standard library. My guess is that this is what's missing in your case. See http://eventlet.net/doc/patching.html for info on monkey patching. |
@miguelgrinberg I had the impression that your code was doing that under the hood. I limited to: as a side note, I only patched the web server. thanks for pin pointing me to the right direction. other question, which backends is recommended for performance vs scale? thanks again for the quick support! |
@miguelgrinberg I have a problem about Flask-SQLAlchemy and Kombu. I use Flask-APScheduler to start a background thread in order to receive records from RabbitMQ and insert those records to MySQL. The code likes this:
However, if it runs at |
@shitone do this:
|
@miguelgrinberg How could I add |
@shitone I'm not familiar with how you start a thread with APScheduler, but when you use plain threads, you can pass
|
Hi,@miguelgrinberg How to |
You have to use |
@miguelgrinberg Now I have a background thread to emit alerts to the specify User. The requirement mode of emit likes broadcast mode, but the alert is only broadcast to one specify User. I don't have |
This is something that your application needs to manage. Flask-Login does not really participate in this. For example, on the connect event you can write the |
@miguelgrinberg It seems that |
The |
@shitone did you find a solution? |
Hi Miguel,
really awesome project.
I have a problem when use the Flask-SocketIO. I wanna start a background task automatic when the socketio server begins to run. The background task can continuously broadcast the message to client by using emit(). But the socketio.start_background_task() is not a decorator, it seems cannot start the background task with the socketio server starting. Moreover, I have a requirement which is starting some background tasks in right time.
Are you planning to become the method start_background_task() to a decorator, and integrate a APScheduler compatibility?
Thanks!
Keep up the good work!
The text was updated successfully, but these errors were encountered: