Commit ae1ca233201c55a7c7fd6007964a9699192e7c42

Authored by Miguel Barão
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 +