Skip to content

Instantly share code, notes, and snippets.

@mturoci
Created September 20, 2022 16:17
Show Gist options
  • Save mturoci/f4511e0cf6b9a70e5c5a5e9d0f14884d to your computer and use it in GitHub Desktop.
Save mturoci/f4511e0cf6b9a70e5c5a5e9d0f14884d to your computer and use it in GitHub Desktop.
import concurrent.futures
from threading import Event
import time
from h2o_wave import main, app, Q, ui
# This takes a lot of time (compute heavy).
async def blocking_function(q: Q):
count = 0
total = 10
while count < total:
# Check if cancelled.
if q.client.event.is_set():
await show_cancel(q)
return
# This blocks the main thread and prevents any other execution.
# This would be a heavy compute job in the real world.
time.sleep(1)
count += 1
# Assume you are able to emit some kind of progress.
await update_ui(q, count / total)
# Show a notification at the end.
await show_notification(q)
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)
q.client.event = Event()
with concurrent.futures.ProcessPoolExecutor() as pool:
await q.exec(pool, blocking_function, q)
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