Commit ae1ca233201c55a7c7fd6007964a9699192e7c42
1 parent
7f9b7abd
Exists in
dev
update running tornado to use asyncio event loop
Showing
2 changed files
with
55 additions
and
23 deletions
Show diff stats
aprendizations/main.py
| @@ -7,6 +7,7 @@ Setup configurations and then runs the application. | @@ -7,6 +7,7 @@ Setup configurations and then runs the application. | ||
| 7 | 7 | ||
| 8 | # python standard library | 8 | # python standard library |
| 9 | import argparse | 9 | import argparse |
| 10 | +import asyncio | ||
| 10 | import logging | 11 | import logging |
| 11 | import logging.config | 12 | import logging.config |
| 12 | from os import environ, path | 13 | from os import environ, path |
| @@ -16,7 +17,7 @@ from typing import Any, Dict | @@ -16,7 +17,7 @@ from typing import Any, Dict | ||
| 16 | 17 | ||
| 17 | # this project | 18 | # this project |
| 18 | from .learnapp import LearnApp, LearnException | 19 | from .learnapp import LearnApp, LearnException |
| 19 | -from .serve import run_webserver | 20 | +from .serve import webserver |
| 20 | from .tools import load_yaml | 21 | from .tools import load_yaml |
| 21 | from . import APP_NAME, APP_VERSION | 22 | from . import APP_NAME, APP_VERSION |
| 22 | 23 | ||
| @@ -179,17 +180,19 @@ def main(): | @@ -179,17 +180,19 @@ def main(): | ||
| 179 | 180 | ||
| 180 | # --- start application -------------------------------------------------- | 181 | # --- start application -------------------------------------------------- |
| 181 | try: | 182 | try: |
| 182 | - learnapp = LearnApp(courses=arg.courses, | ||
| 183 | - prefix=arg.prefix, | ||
| 184 | - dbase=arg.db, | ||
| 185 | - check=arg.check) | 183 | + app = LearnApp(courses=arg.courses, |
| 184 | + prefix=arg.prefix, | ||
| 185 | + dbase=arg.db, | ||
| 186 | + check=arg.check) | ||
| 186 | except LearnException: | 187 | except LearnException: |
| 187 | logging.critical('Failed to start application') | 188 | logging.critical('Failed to start application') |
| 188 | sys.exit(1) | 189 | sys.exit(1) |
| 189 | logging.info('LearnApp started') | 190 | logging.info('LearnApp started') |
| 190 | 191 | ||
| 191 | # --- run webserver forever ---------------------------------------------- | 192 | # --- run webserver forever ---------------------------------------------- |
| 192 | - run_webserver(app=learnapp, ssl=ssl_ctx, port=arg.port, debug=arg.debug) | 193 | + asyncio.run(webserver(app=app, ssl=ssl_ctx, port=arg.port, debug=arg.debug)) |
| 194 | + | ||
| 195 | + logging.critical('Webserver stopped.') | ||
| 193 | 196 | ||
| 194 | 197 | ||
| 195 | # ---------------------------------------------------------------------------- | 198 | # ---------------------------------------------------------------------------- |
aprendizations/serve.py
| @@ -4,6 +4,7 @@ Webserver | @@ -4,6 +4,7 @@ Webserver | ||
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | # python standard library | 6 | # python standard library |
| 7 | +import asyncio | ||
| 7 | import base64 | 8 | import base64 |
| 8 | import functools | 9 | import functools |
| 9 | from logging import getLogger | 10 | from logging import getLogger |
| @@ -58,8 +59,9 @@ class WebApplication(tornado.web.Application): | @@ -58,8 +59,9 @@ class WebApplication(tornado.web.Application): | ||
| 58 | (r'/rankings', RankingsHandler), # rankings table | 59 | (r'/rankings', RankingsHandler), # rankings table |
| 59 | (r'/topic/(.+)', TopicHandler), # start topic | 60 | (r'/topic/(.+)', TopicHandler), # start topic |
| 60 | (r'/file/(.+)', FileHandler), # serve file | 61 | (r'/file/(.+)', FileHandler), # serve file |
| 61 | - (r'/courses', CoursesHandler), # show list of courses | ||
| 62 | - (r'/course/(.*)', CourseHandler), # show course topics | 62 | + (r'/courses', CoursesHandler), # show available courses |
| 63 | + (r'/course/(.*)', CourseHandler), # show topics from course | ||
| 64 | + (r'/course2/(.*)', CourseHandler2), # show topics from course FIXME | ||
| 63 | (r'/', RootHandler), # redirects | 65 | (r'/', RootHandler), # redirects |
| 64 | ] | 66 | ] |
| 65 | settings = { | 67 | settings = { |
| @@ -241,9 +243,38 @@ class CoursesHandler(BaseHandler): | @@ -241,9 +243,38 @@ class CoursesHandler(BaseHandler): | ||
| 241 | 243 | ||
| 242 | 244 | ||
| 243 | # ============================================================================ | 245 | # ============================================================================ |
| 246 | +class CourseHandler2(BaseHandler): | ||
| 247 | + @tornado.web.authenticated | ||
| 248 | + def get(self, course_id) -> None: | ||
| 249 | + ''' | ||
| 250 | + Handles get /course/... | ||
| 251 | + Starts a given course and show list of topics | ||
| 252 | + ''' | ||
| 253 | + uid = self.current_user | ||
| 254 | + logger.debug('[CourseHandler2] uid="%s", course_id="%s"', uid, course_id) | ||
| 255 | + | ||
| 256 | + if course_id == '': | ||
| 257 | + course_id = self.learn.get_current_course_id(uid) | ||
| 258 | + | ||
| 259 | + try: | ||
| 260 | + self.learn.start_course(uid, course_id) | ||
| 261 | + except LearnException: | ||
| 262 | + self.redirect('/courses') | ||
| 263 | + | ||
| 264 | + # print(self.learn.get_course(course_id)) | ||
| 265 | + self.render('maintopics-table2.html', | ||
| 266 | + appname=APP_NAME, | ||
| 267 | + uid=uid, | ||
| 268 | + name=self.learn.get_student_name(uid), | ||
| 269 | + state=self.learn.get_student_state(uid), | ||
| 270 | + course_id=course_id, | ||
| 271 | + course=self.learn.get_course(course_id) | ||
| 272 | + ) | ||
| 273 | + | ||
| 274 | +# ============================================================================ | ||
| 244 | class CourseHandler(BaseHandler): | 275 | class CourseHandler(BaseHandler): |
| 245 | ''' | 276 | ''' |
| 246 | - Handles a particular course to show the topics table | 277 | + Show topics for a particular course |
| 247 | ''' | 278 | ''' |
| 248 | 279 | ||
| 249 | @tornado.web.authenticated | 280 | @tornado.web.authenticated |
| @@ -253,6 +284,8 @@ class CourseHandler(BaseHandler): | @@ -253,6 +284,8 @@ class CourseHandler(BaseHandler): | ||
| 253 | Starts a given course and show list of topics | 284 | Starts a given course and show list of topics |
| 254 | ''' | 285 | ''' |
| 255 | uid = self.current_user | 286 | uid = self.current_user |
| 287 | + logger.debug('[CourseHandler] uid="%s", course_id="%s"', uid, course_id) | ||
| 288 | + | ||
| 256 | if course_id == '': | 289 | if course_id == '': |
| 257 | course_id = self.learn.get_current_course_id(uid) | 290 | course_id = self.learn.get_current_course_id(uid) |
| 258 | 291 | ||
| @@ -286,7 +319,7 @@ class TopicHandler(BaseHandler): | @@ -286,7 +319,7 @@ class TopicHandler(BaseHandler): | ||
| 286 | Starts a given topic | 319 | Starts a given topic |
| 287 | ''' | 320 | ''' |
| 288 | uid = self.current_user | 321 | uid = self.current_user |
| 289 | - logger.debug('[TopicHandler.get] %s', topic) | 322 | + logger.debug('[TopicHandler] %s', topic) |
| 290 | try: | 323 | try: |
| 291 | await self.learn.start_topic(uid, topic) # FIXME GET should not modify state... | 324 | await self.learn.start_topic(uid, topic) # FIXME GET should not modify state... |
| 292 | except KeyError: | 325 | except KeyError: |
| @@ -315,8 +348,8 @@ class FileHandler(BaseHandler): | @@ -315,8 +348,8 @@ class FileHandler(BaseHandler): | ||
| 315 | public_dir = self.learn.get_current_public_dir(uid) | 348 | public_dir = self.learn.get_current_public_dir(uid) |
| 316 | filepath = expanduser(join(public_dir, filename)) | 349 | filepath = expanduser(join(public_dir, filename)) |
| 317 | 350 | ||
| 318 | - logger.debug('uid=%s, public_dir=%s, filepath=%s', uid, public_dir, | ||
| 319 | - filepath) | 351 | + logger.debug('[FileHandler] uid=%s, public_dir=%s, filepath=%s', |
| 352 | + uid, public_dir, filepath) | ||
| 320 | try: | 353 | try: |
| 321 | with open(filepath, 'rb') as file: | 354 | with open(filepath, 'rb') as file: |
| 322 | data = file.read() | 355 | data = file.read() |
| @@ -356,7 +389,7 @@ class QuestionHandler(BaseHandler): | @@ -356,7 +389,7 @@ class QuestionHandler(BaseHandler): | ||
| 356 | ''' | 389 | ''' |
| 357 | Get question to render or an animated trophy if no more questions. | 390 | Get question to render or an animated trophy if no more questions. |
| 358 | ''' | 391 | ''' |
| 359 | - logger.debug('[QuestionHandler.get]') | 392 | + logger.debug('[QuestionHandler]') |
| 360 | user = self.current_user | 393 | user = self.current_user |
| 361 | question = await self.learn.get_question(user) | 394 | question = await self.learn.get_question(user) |
| 362 | 395 | ||
| @@ -396,7 +429,7 @@ class QuestionHandler(BaseHandler): | @@ -396,7 +429,7 @@ class QuestionHandler(BaseHandler): | ||
| 396 | user = self.current_user | 429 | user = self.current_user |
| 397 | answer = self.get_body_arguments('answer') # list | 430 | answer = self.get_body_arguments('answer') # list |
| 398 | qid = self.get_body_arguments('qid')[0] | 431 | qid = self.get_body_arguments('qid')[0] |
| 399 | - # logger.debug('[QuestionHandler] answer=%s', answer) | 432 | + logger.debug('[QuestionHandler] answer=%s', answer) |
| 400 | 433 | ||
| 401 | # --- check if browser opened different questions simultaneously | 434 | # --- check if browser opened different questions simultaneously |
| 402 | if qid != self.learn.get_current_question_id(user): | 435 | if qid != self.learn.get_current_question_id(user): |
| @@ -486,9 +519,9 @@ def signal_handler(*_) -> None: | @@ -486,9 +519,9 @@ def signal_handler(*_) -> None: | ||
| 486 | 519 | ||
| 487 | 520 | ||
| 488 | # ---------------------------------------------------------------------------- | 521 | # ---------------------------------------------------------------------------- |
| 489 | -def run_webserver(app, ssl, port: int = 8443, debug: bool = False) -> None: | 522 | +async def webserver(app, ssl, port: int = 8443, debug: bool = False) -> None: |
| 490 | ''' | 523 | ''' |
| 491 | - Starts and runs webserver until a SIGINT signal (Ctrl-C) is received. | 524 | + Runs webserver until a SIGINT signal (Ctrl-C) is received. |
| 492 | ''' | 525 | ''' |
| 493 | 526 | ||
| 494 | # --- create web application | 527 | # --- create web application |
| @@ -517,10 +550,6 @@ def run_webserver(app, ssl, port: int = 8443, debug: bool = False) -> None: | @@ -517,10 +550,6 @@ def run_webserver(app, ssl, port: int = 8443, debug: bool = False) -> None: | ||
| 517 | # --- set signal handler for Control-C | 550 | # --- set signal handler for Control-C |
| 518 | signal.signal(signal.SIGINT, signal_handler) | 551 | signal.signal(signal.SIGINT, signal_handler) |
| 519 | 552 | ||
| 520 | - # --- run tornado webserver | ||
| 521 | - try: | ||
| 522 | - tornado.ioloop.IOLoop.current().start() # running... | ||
| 523 | - except Exception: | ||
| 524 | - logger.critical('Webserver stopped.') | ||
| 525 | - tornado.ioloop.IOLoop.current().stop() | ||
| 526 | - raise | 553 | + # --- run event loop (and tornado webserver) |
| 554 | + await asyncio.Event().wait() | ||
| 555 | + |