Fix websocket race condition (#261)

This commit is contained in:
Nikhil Rao 2023-01-14 16:49:45 -08:00 committed by GitHub
parent c8936355f2
commit 1e64e62842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 23 additions and 10 deletions

View File

@ -1 +1 @@
0.1.12
0.1.13

View File

@ -96,12 +96,13 @@ export const applyEvent = async (event, router, socket) => {
/**
* Process an event off the event queue.
* @param state The state with the event queue.
* @param setState The function to set the state.
* @param result The current result
* @param setResult The function to set the result.
* @param router The router object.
* @param socket The socket object to send the event on.
*/
export const updateState = async (state, result, setResult, router, socket) => {
export const updateState = async (state, setState, result, setResult, router, socket) => {
// If we are already processing an event, or there are no events to process, return.
if (result.processing || state.events.length == 0) {
return;
@ -112,25 +113,34 @@ export const updateState = async (state, result, setResult, router, socket) => {
return;
}
// Process the next event in the queue.
// Set processing to true to block other events from being processed.
setResult({ ...result, processing: true });
await applyEvent(state.events.shift(), router, socket);
// Pop the next event off the queue and apply it.
const event = state.events.shift()
// Set new events to avoid reprocessing the same event.
setState({ ...state, events: state.events });
// Apply the event.
await applyEvent(event, router, socket);
};
/**
* Connect to a websocket and set the handlers.
* @param socket The socket object to connect.
* @param state The state object to apply the deltas to.
* @param setState The function to set the state.
* @param setResult The function to set the result.
* @param endpoint The endpoint to connect to.
*/
export const connect = async (socket, state, result, setResult, router, endpoint) => {
export const connect = async (socket, state, setState, result, setResult, router, endpoint) => {
// Create the socket.
socket.current = new WebSocket(endpoint);
// Once the socket is open, hydrate the page.
socket.current.onopen = () => {
updateState(state, result, setResult, router, socket.current)
updateState(state, setState, result, setResult, router, socket.current)
}
// On each received message, apply the delta and set the result.

View File

@ -162,10 +162,11 @@ READY = f"const {{ isReady }} = {ROUTER};"
USE_EFFECT = join(
[
"useEffect(() => {{",
" if(!isReady)",
" if(!isReady) {{",
f" return;",
" }}",
f" if (!{SOCKET}.current) {{{{",
f" connect({SOCKET}, {{state}}, {RESULT}, {SET_RESULT}, {ROUTER}, {EVENT_ENDPOINT})",
f" connect({SOCKET}, {{state}}, {{set_state}}, {RESULT}, {SET_RESULT}, {ROUTER}, {EVENT_ENDPOINT})",
" }}",
" const update = async () => {{",
f" if ({RESULT}.{STATE} != null) {{{{",
@ -179,7 +180,7 @@ USE_EFFECT = join(
f" {PROCESSING}: false,",
" }})",
" }}",
f" await updateState({{state}}, {RESULT}, {SET_RESULT}, {ROUTER}, {SOCKET}.current)",
f" await updateState({{state}}, {{set_state}}, {RESULT}, {SET_RESULT}, {ROUTER}, {SOCKET}.current)",
" }}",
" update()",
"}})",

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "pynecone-io"
version = "0.1.11"
version = "0.1.13"
description = "The easiest way to build web apps."
license = "Apache-2.0"
authors = [
@ -53,3 +53,5 @@ pc = "pynecone.pc:main"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.pyright]