def unlocked(): """ Context manager which unlocks a Document and dispatches ModelChangedEvents triggered in the context body to all sockets on current sessions. """ curdoc = state.curdoc if curdoc is None or curdoc.session_context is None or curdoc.session_context.session is None: yield return from tornado.websocket import WebSocketHandler connections = curdoc.session_context.session._subscribed_connections hold = curdoc.callbacks.hold_value if hold: old_events = list(curdoc.callbacks._held_events) else: old_events = [] curdoc.hold() try: yield locked = False for conn in connections: socket = conn._socket if hasattr(socket, 'write_lock') and socket.write_lock._block._value == 0: locked = True break events = [] for event in curdoc.callbacks._held_events: if not isinstance( event, ModelChangedEvent) or event in old_events or locked: events.append(event) continue for conn in connections: socket = conn._socket ws_conn = getattr(socket, 'ws_connection', False) if (not hasattr(socket, 'write_message') or ws_conn is None or (ws_conn and ws_conn.is_closing())): continue msg = conn.protocol.create('PATCH-DOC', [event]) WebSocketHandler.write_message(socket, msg.header_json) WebSocketHandler.write_message(socket, msg.metadata_json) WebSocketHandler.write_message(socket, msg.content_json) for header, payload in msg._buffers: WebSocketHandler.write_message(socket, header) WebSocketHandler.write_message(socket, payload, binary=True) curdoc.callbacks._held_events = events finally: if hold: return try: curdoc.unhold() except RuntimeError: curdoc.add_next_tick_callback( partial(_dispatch_events, curdoc, events))
def unlocked(): """ Context manager which unlocks a Document and dispatches ModelChangedEvents triggered in the context body to all sockets on current sessions. """ curdoc = state.curdoc if curdoc is None or curdoc.session_context is None or curdoc.session_context.session is None: yield return connections = curdoc.session_context.session._subscribed_connections hold = curdoc._hold if hold: old_events = list(curdoc._held_events) else: old_events = [] curdoc.hold() try: yield events = [] for conn in connections: socket = conn._socket if hasattr(socket, 'write_lock') and socket.write_lock._block._value == 0: state._locks.add(socket) locked = socket in state._locks for event in curdoc._held_events: if (isinstance(event, ModelChangedEvent) and event not in old_events and hasattr(socket, 'write_message') and not locked): msg = conn.protocol.create('PATCH-DOC', [event]) WebSocketHandler.write_message(socket, msg.header_json) WebSocketHandler.write_message(socket, msg.metadata_json) WebSocketHandler.write_message(socket, msg.content_json) for header, payload in msg._buffers: WebSocketHandler.write_message(socket, header) WebSocketHandler.write_message(socket, payload, binary=True) elif event not in events: events.append(event) curdoc._held_events = events finally: if not hold: curdoc.unhold()