schmidtfederico / apscheduler-ui

MIT License
6 stars 2 forks source link

How to run this UI? #2

Closed pratik-dani closed 3 years ago

pratik-dani commented 3 years ago

Can you add a little documentation on how to run this repo.

schmidtfederico commented 3 years ago

Hi there! I've purposely left the repo description blank so far as I'm still testing the UI on my projects.

However, I've seen the other ticket you opened, #3, and here's a working example:

from apschedulerui.web import SchedulerUI

scheduler = BlockingScheduler()
ui = SchedulerUI(scheduler)
ui.start()  # Server is now running in a *background* thread.

scheduler.start()  # We need to call the BlockingScheduler start method to prevent the script from exiting.
pratik-dani commented 3 years ago

[2020-09-09 11:56:19,232] WARNING in __init__: WebSocket transport not available. Install gevent-websocket for improved performance.

Even after starting the scheduler, I am facing the same issue. I was using Blockingscheduler this time.

schmidtfederico commented 3 years ago

Yes, that's a warning from Flask-SocketIO, not from apschedulerui. You can read here about it.

You can pip install gevent-websocket and that warning will go away.

pratik-dani commented 3 years ago

I did install it but even after installing the localhost:5000 says Not Found (404). I am using Blockingscheduler.

schmidtfederico commented 3 years ago

Please try running the following snippet and paste the output here:

import logging
from datetime import datetime

from apscheduler.schedulers.background import BlockingScheduler
from apschedulerui.web import SchedulerUI

logging.basicConfig(level=logging.DEBUG)

scheduler = BlockingScheduler()
ui = SchedulerUI(scheduler)
ui.start()  # Server is now running in a *background* thread.

scheduler.add_job(print, 'interval', args=['Job executed'], minutes=60, next_run_time=datetime.now())

scheduler.start()  # We need to call the blocking scheduler start method to prevent the script from exiting.

print('This should never be printed!')
pratik-dani commented 3 years ago

INFO:engineio.server:Server initialized for gevent. INFO:apscheduler.scheduler:Adding job tentatively -- it will be properly scheduled when the scheduler starts INFO:socketio.server:emitting event "executor_event" to all [/] INFO:socketio.server:emitting event "job_event" to all [/] INFO:socketio.server:emitting event "jobstore_event" to all [/] INFO:apscheduler.scheduler:Added job "print" to job store "default" INFO:apscheduler.scheduler:Scheduler started INFO:socketio.server:emitting event "scheduler_event" to all [/] DEBUG:apscheduler.scheduler:Looking for jobs to run INFO:apscheduler.executors.default:Running job "print (trigger: interval[1:00:00], next run at: 2020-09-09 18:05:40 IST)" (scheduled at 2020-09-09 18:05:40.634170+05:30) INFO:apscheduler.executors.default:Job "print (trigger: interval[1:00:00], next run at: 2020-09-09 18:05:40 IST)" executed successfully INFO:socketio.server:emitting event "job_event" to all [/] INFO:socketio.server:emitting event "job_event" to all [/] DEBUG:apscheduler.scheduler:Next wakeup is due at 2020-09-09 19:05:40.634170+05:30 (in 3599.934272 seconds) Job executed

The output

pratik-dani commented 3 years ago

But I am not able to access the UI. How to do that?

schmidtfederico commented 3 years ago

Can you try running the following snippet and navigating to localhost:5000 in the same machine you're running it?

import logging
import flask
import flask_socketio

logging.basicConfig(level=logging.DEBUG)

web_server = flask.Flask(__name__)
socket_io = flask_socketio.SocketIO(web_server, async_mode='threading')

web_server.add_url_rule('/', 'index', lambda: 'It works!')

socket_io.run(web_server, host='0.0.0.0', port=5000)

Do you see a blank webpage with "It works!" in it?

pratik-dani commented 3 years ago

Do you see a blank webpage with "It works!" in it?

Yes, it shows. But this code will show "It works!" independent of the fact that we have started the scheduler or not. I was in the impression that there will be a UI kind of thing that will have all the list of the jobs which I will be able to manage using the UI as the name was little confusing to me (apschedulerui).

schmidtfederico commented 3 years ago

That was just a test to see if you had a problem with the Flask/SocketIO server, it's not serving the Scheduler UI.

I don't understand what you mean with "independent of the fact that we have started the scheduler or not", were you running a scheduler in a different process? There wasn't any scheduler involved in the last snippet I passed to you.

pratik-dani commented 3 years ago

Yeah, there wasn't any scheduler involved and the script worked. I was a little confused my bad, sorry about that. I just want to know how to access the apscheduler UI. Why the Flask/SocketIO server, is not serving the Scheduler UI?

schmidtfederico commented 3 years ago

The Scheduler UI will be served on *:5000 using code that's very similar to the last snippet you tested. So I'm not sure why you aren't seeing the UI in your browser in localhost:5000 after running the snippet in my previous comment.

Please try running the following snippet and paste the output here:

import logging
from datetime import datetime

from apscheduler.schedulers.background import BlockingScheduler
from apschedulerui.web import SchedulerUI

logging.basicConfig(level=logging.DEBUG)

scheduler = BlockingScheduler()
ui = SchedulerUI(scheduler)
ui.start()  # Server is now running in a *background* thread.

scheduler.add_job(print, 'interval', args=['Job executed'], minutes=60, next_run_time=datetime.now())

scheduler.start()  # We need to call the blocking scheduler start method to prevent the script from exiting.

print('This should never be printed!')

Just for reference, this is what you should be seeing in your browser at localhost:5000 after running that snippet: image

Which OS are you using?

pratik-dani commented 3 years ago

I am not able to see this UI. Let me try on another machine.

pratik-dani commented 3 years ago

I am using windows 10.

schmidtfederico commented 3 years ago

I don't have a Windows machine to test with, but can you run the following snippet to see if navigating to localhost:5000 in your browser also show the "It works" message? Please also provide the output of the script.

import logging
import threading
import time
import requests

import flask
import flask_socketio

logging.basicConfig(level=logging.DEBUG)

class TestWebServer:
    def __init__(self):
        self._web_server = flask.Flask(__name__)
        self._socket_io = None

        try:
            self._socket_io = flask_socketio.SocketIO(self._web_server, async_mode='gevent')
        except ValueError:
            self._socket_io = flask_socketio.SocketIO(self._web_server, async_mode='threading')

        self._init_endpoints()
        self._web_server_thread = None

    def start(self, host='0.0.0.0', port=5000, daemon=True):
        self._web_server_thread = threading.Thread(target=self._start, name='apscheduler-ui', args=(host, port))
        self._web_server_thread.daemon = daemon
        self._web_server_thread.start()

    def _init_endpoints(self):
        self._web_server.add_url_rule('/', 'index', self._index, defaults={'path': ''})
        self._web_server.add_url_rule('/<path:path>', 'index', self._index)

    def _index(self, path):
        return 'It works!'

    def _start(self, host, port):
        self._socket_io.run(self._web_server, host=host, port=port)

server = TestWebServer()
server.start()

time.sleep(1)

check_request = requests.get('http://localhost:5000')
check_request.raise_for_status()

print(check_request.text)

time.sleep(1e6)
pratik-dani commented 3 years ago

Tested it now on localhost:5000 it shows "It works!"

schmidtfederico commented 3 years ago

Can you also provide the output for the script?

That last snippet has the exact same structure I'm using to serve the Scheduler UI, so I'm unsure why the "It works" example is working for you and the Scheduler UI isn't. I may need to try to find a Windows machine to test this during the weekend.

Can you paste the output of pip freeze here?

pratik-dani commented 3 years ago

DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:5000
DEBUG:geventwebsocket.handler:Initializing WebSocket
DEBUG:geventwebsocket.handler:Validating WebSocket request
DEBUG:urllib3.connectionpool:http://localhost:5000 "GET / HTTP/1.1" 200 9
INFO:geventwebsocket.handler:127.0.0.1 - - [2020-09-09 20:58:54] "GET / HTTP/1.1" 200 124 0.003428
It works!

The output of the above code.

I have an Ubuntu wsl on my system if you want I can try running on that machine.
pratik-dani commented 3 years ago

aiohttp==3.6.2
alabaster==0.7.12
altair==4.1.0
anaconda-client==1.7.2
anaconda-navigator==1.9.7
anaconda-project==0.8.3
APScheduler==3.6.3
asn1crypto==1.0.1
aspose-pdf-java-for-jython==1.0.0
astor==0.8.1
astroid==2.3.1
astropy==3.2.1
astunparse==1.6.3
async-timeout==3.0.1
atomicwrites==1.3.0
attrs==19.2.0
autopep8==1.5.2
Babel==2.7.0
backcall==0.1.0
backports.functools-lru-cache==1.5
backports.os==0.1.1
backports.shutil-get-terminal-size==1.0.0
backports.tempfile==1.0
backports.weakref==1.0.post1
beautifulsoup4==4.8.0
bitarray==1.0.1
bkcharts==0.2
bleach==3.1.0
blis==0.4.1
bokeh==1.3.4
boto==2.49.0
boto3==1.14.47
botocore==1.17.47
Bottleneck==1.2.1
cachetools==4.1.0
catalogue==2.0.0
certifi==2019.9.11
cffi==1.12.3
chardet==3.0.4
Click==7.0
cloudpickle==1.2.2
clyent==1.2.2
colorama==0.4.1
comtypes==1.1.7
conda==4.8.3
conda-build==3.18.9
conda-package-handling==1.6.0
conda-verify==3.4.2
contextlib2==0.6.0
convertdate==2.2.1
cryptography==2.7
cycler==0.10.0
cymem==2.0.3
Cython==0.29.13
cytoolz==0.10.0
dask==2.5.2
dateparser==0.7.6
decorator==4.4.0
defusedxml==0.6.0
distributed==2.5.2
dnspython==1.16.0
docutils==0.15.2
email-validator==1.1.1
entrypoints==0.3
ephem==3.7.7.1
et-xmlfile==1.0.1
extract-msg==0.23.3
Faker==4.1.1
fastapi==0.59.0
fastcache==1.1.0
faster-than-requests==0.9.9
fbprophet==0.6
filelock==3.0.12
flake8==3.8.2
Flask==1.1.1
Flask-Limiter==1.4
Flask-Login==0.5.0
Flask-SocketIO==4.3.1
Flask-SQLAlchemy==2.4.4
Flask-WTF==0.14.3
fsspec==0.5.2
future==0.17.1
fuzzywuzzy==0.18.0
gast==0.3.3
getmac==0.8.2
gevent==1.4.0
gevent-websocket==0.10.1
glob2==0.7
google-api-core==1.17.0
google-api-python-client==1.8.3
google-auth==1.15.0
google-auth-httplib2==0.0.3
google-auth-oauthlib==0.4.1
google-pasta==0.2.0
googleapis-common-protos==1.51.0
greenlet==0.4.15
grpcio==1.29.0
gspread==3.6.0
h5py==2.10.0
HeapDict==1.0.1
holidays==0.10.2
html5lib==1.0.1
httplib2==0.18.1
idna==2.8
imageio==2.6.0
imagesize==1.1.0
IMAPClient==2.1.0
implicit==0.4.2
import-java==0.6
importlib-metadata==0.23
ipykernel==5.1.2
ipython==7.8.0
ipython-genutils==0.2.0
ipywidgets==7.5.1
isort==4.3.21
itsdangerous==1.1.0
jdcal==1.4.1
jedi==0.17.0
Jinja2==2.10.3
jmespath==0.10.0
joblib==0.13.2
json5==0.8.5
jsonschema==3.0.2
jupyter==1.0.0
jupyter-client==5.3.3
jupyter-console==6.0.0
jupyter-core==4.5.0
jupyterlab==1.1.4
jupyterlab-server==1.0.6
Keras==2.4.3
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.0
keyring==18.0.0
kiwisolver==1.1.0
korean-lunar-calendar==0.2.1
lazy-object-proxy==1.4.2
libarchive-c==2.8
limits==1.5.1
linkedin-api==1.1.0
llvmlite==0.29.0
locket==0.2.0
lockfile==0.12.2
luigi==3.0.1
LunarCalendar==0.0.9
lxml==4.4.1
Markdown==3.2.2
MarkupSafe==1.1.1
matplotlib==3.2.1
mccabe==0.6.1
menuinst==1.4.16
mistune==0.8.4
mkl-fft==1.0.14
mkl-random==1.1.0
mkl-service==2.3.0
mock==3.0.5
more-itertools==7.2.0
mpmath==1.1.0
msgpack==0.6.1
multidict==4.7.6
multipledispatch==0.6.0
murmurhash==1.0.2
navigator-updater==0.2.1
nbconvert==5.6.0
nbformat==4.4.0
networkx==2.3
nimporter==1.0.2
nltk==3.4.5
nose==1.3.7
notebook==6.0.1
numba==0.45.1
numexpr==2.7.0
numpy==1.18.1
numpydoc==0.9.1
oauth2client==4.1.3
oauthclient==1.0.3
oauthlib==3.1.0
olefile==0.46
opencv-python==4.2.0.34
openpyxl==3.0.0
opt-einsum==3.2.1
packaging==19.2
pandas==0.25.1
pandocfilters==1.4.2
parso==0.7.0
partd==1.0.0
passlib==1.7.2
path.py==12.0.1
pathlib2==2.3.5
patsy==0.5.1
pdf2image==1.13.1
pep8==1.7.1
pickleshare==0.7.5
pikepdf==1.14.0
Pillow==6.2.0
pkginfo==1.5.0.1
plac==1.1.3
plotly==4.7.1
pluggy==0.13.0
ply==3.11
preshed==3.0.2
pretty-html-table==0.9.dev0
probableparsing==0.0.1
prometheus-client==0.7.1
prompt-toolkit==2.0.10
protobuf==3.12.0
psutil==5.6.3
psycopg2==2.8.5
py==1.8.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycodestyle==2.6.0
pycosat==0.6.3
pycparser==2.19
pycrypto==2.6.1
pycurl==7.43.0.3
pydantic==1.6
pydocstyle==5.0.2
pyflakes==2.2.0
pygame==1.9.6
Pygments==2.4.2
pyjnius==1.3.0
pylint==2.4.2
PyMeeus==0.3.7
pymongo==3.10.1
pyodbc==4.0.27
pyOpenSSL==19.0.0
pyparsing==2.4.2
PyPDF2==1.26.0
pyquery==1.4.1
pyreadline==2.1
pyrsistent==0.15.4
PySocks==1.7.1
pyspider==0.3.10
pystan==2.19.0.0
pytest==5.2.1
pytest-arraydiff==0.3
pytest-astropy==0.5.0
pytest-doctestplus==0.4.0
pytest-openfiles==0.4.0
pytest-remotedata==0.3.2
python-crfsuite==0.9.7
python-daemon==2.2.4
python-dateutil==2.8.1
python-engineio==3.13.2
python-http-client==3.2.7
python-jsonrpc-server==0.3.4
python-language-server==0.33.0
python-memcached==1.59
python-slugify==3.0.2
python-socketio==4.6.0
pytz==2019.3
PyWavelets==1.0.3
pywin32==223
pywinpty==0.5.5
PyYAML==5.3
pyzmq==18.1.0
QtAwesome==0.6.0
qtconsole==4.5.5
QtPy==1.9.0
redis==3.5.3
regex==2020.7.14
requests==2.22.0
requests-oauthlib==1.3.0
retry==0.9.2
retrying==1.3.3
rope==0.14.0
rq==1.4.3
rsa==4.0
ruamel-yaml==0.15.46
s3transfer==0.3.3
scikit-image==0.15.0
scikit-learn==0.21.3
scipy==1.4.1
seaborn==0.9.0
selenium==3.141.0
Send2Trash==1.5.0
sendgrid==6.4.1
sentry-sdk==0.14.4
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.12.0
slacker==0.14.0
snowballstemmer==2.0.0
sortedcollections==1.1.2
sortedcontainers==2.1.0
soupsieve==1.9.3
spacy==2.2.4
Sphinx==2.2.0
sphinxcontrib-applehelp==1.0.1
sphinxcontrib-devhelp==1.0.1
sphinxcontrib-htmlhelp==1.0.2
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.2
sphinxcontrib-serializinghtml==1.1.3
sphinxcontrib-websupport==1.1.2
spyder==3.3.6
spyder-kernels==0.5.2
SQLAlchemy==1.3.9
srsly==1.0.2
starkbank-ecdsa==1.0.0
starlette==0.13.4
statsmodels==0.10.1
sympy==1.4
tables==3.5.2
tabula-py==2.1.0
tblib==1.4.0
tensorboard==2.2.2
tensorboard-plugin-wit==1.6.0.post3
tensorflow==2.2.0
tensorflow-estimator==2.2.0
termcolor==1.1.0
terminado==0.8.2
testpath==0.4.2
text-unidecode==1.3
thinc==7.4.0
tika==1.24
toolz==0.10.0
tornado==5.1.1
tqdm==4.36.1
traitlets==4.3.3
typed-ast==1.4.1
tzlocal==1.5.1
unicodecsv==0.14.1
unique-id==1.0.1
uritemplate==3.0.1
urllib3==1.24.2
usaddress==0.5.10
wasabi==0.6.0
wcwidth==0.1.7
webencodings==0.5.1
Werkzeug==0.16.0
widgetsnbextension==3.5.1
win-inet-pton==1.1.0
win-unicode-console==0.5
wincertstore==0.2
wrapt==1.11.2
WTForms==2.3.1
xgboost==0.90
xlrd==1.2.0
XlsxWriter==1.2.1
xlwings==0.15.10
xlwt==1.3.0
yapf==0.30.0
yarl==1.4.2
zict==1.0.0
zipp==0.6.0```
schmidtfederico commented 3 years ago

I don't see apschedulerui as one of the packages you have installed, from the output of pip freeze. Did you check out this repo and you're using the "apschedulerui" folder as the package?

If that's the case, you need to install the package from pip, with pip install apschedulerui and you can safely remove any folder you checked out from GitHub.

That would explain why you're seeing a 404 error when navigating to localhost:5000, the Scheduler UI is trying to serve the index.html file with a path relative to the package structure that will never be found if the package is not properly installed.

pratik-dani commented 3 years ago

Ok. Now I understand the issue. Now it's working. Thanks a lot. The UI looks amazing.

schmidtfederico commented 3 years ago

You're welcome! Glad that we figured it out.

Just bear in mind it's still in an early stage of development and a few issues may still arise!

pratik-dani commented 3 years ago

I would be happy to help if you need any. I am going to implement this in my tool. I saw the image of this UI on dribbble. The UI is perfect.

pratik-dani commented 3 years ago

Thanks for the help!

pratik-dani commented 3 years ago

One last question the UI on dribbble has Executers, Jobstores and Stop scheduler buttons in them. Are they part of this version? If yes, then I am not able to utilize them.

schmidtfederico commented 3 years ago

Executors and Jobstores tab isn't yet implemented, but it'll be a simple list of the executors and job stores the scheduler has, which almost every time is only 1 of each and doesn't mean much.

Stopping the scheduler may never be implemented, because when I tested it the re-start method didn't work (i.e. the scheduler would say "Running", yet jobs wouldn't execute again). So unless I find a way of making the re-start work, I won't be implementing it. Pausing and resuming the scheduler has a similar effect, though, and you can stop it from running jobs by pausing it.