Created
September 20, 2022 16:08
-
-
Save mturoci/4c5d1e684896f689ad54caf59f22e19b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import time | |
import concurrent.futures | |
from threading import Event | |
from h2o_wave import main, app, Q, ui | |
# This takes a lot of time (compute heavy). | |
def blocking_function(q: Q, loop: asyncio.AbstractEventLoop): | |
count = 0 | |
total = 10 | |
future = None | |
while count < total: | |
# Check if cancelled. | |
if q.client.event.is_set(): | |
asyncio.ensure_future(show_cancel(q), loop=loop) | |
return | |
# This blocks the main thread and prevents any other execution. | |
# This would be the compute in the real world. | |
time.sleep(1) | |
count += 1 | |
# If future is not done yet, skip the update to keep the correct order. | |
if not future or future.done(): | |
# Assume you are able to emit some kind of progress. | |
future = asyncio.ensure_future(update_ui(q, count / total), loop=loop) | |
# Show a notification at the end. | |
asyncio.ensure_future(show_notification(q), loop=loop) | |
async def show_cancel(q: Q): | |
q.page['meta'].dialog.items[0].progress.caption = 'Cancelled' | |
q.page['meta'].dialog.closable = True | |
await q.page.save() | |
async def show_notification(q: Q): | |
q.page['meta'].dialog = None | |
q.page['meta'].notification_bar = ui.notification_bar( | |
name='success_notification', | |
text='Job done!', | |
type='success', | |
events=['dismissed'] | |
) | |
await q.page.save() | |
async def update_ui(q: Q, value: int): | |
q.page['meta'].dialog.items[0].progress.value = value | |
await q.page.save() | |
@app('/') | |
async def serve(q: Q): | |
# Unimportant, draw initial UI. | |
if not q.client.initialized: | |
q.page['meta'] = ui.meta_card(box='') | |
q.page['form'] = ui.form_card(box='1 1 1 1', items=[ | |
ui.button(name='start_job', label='Start job') | |
]) | |
q.client.initialized = True | |
# Handle start job button click. | |
if q.args.start_job: | |
q.page['meta'].dialog = ui.dialog(title='Blocking job', blocking=True, items=[ | |
ui.progress(label='Progress', value=0), | |
ui.button(name='cancel', label='Cancel') | |
]) | |
# Do not run like this - will block the whole thread - freeze the app. | |
# blocking_function(q, loop) | |
# Get the current event loop - will be used for | |
# running async functions within the blocking. | |
loop = asyncio.get_event_loop() | |
# Create an event to use for cancellation. | |
q.client.event = Event() | |
with concurrent.futures.ThreadPoolExecutor() as pool: | |
await q.exec(pool, blocking_function, q, loop) | |
if q.args.cancel: | |
q.client.event.set() | |
# Unimportant, just handle notification dismissal. | |
if q.events.success_notification and q.events.success_notification.dismissed: | |
q.page['meta'].notification_bar = None | |
await q.page.save() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment