diff --git a/client/src/hooks/use-server-sync.ts b/client/src/hooks/use-server-sync.ts index 022adaa..3034715 100644 --- a/client/src/hooks/use-server-sync.ts +++ b/client/src/hooks/use-server-sync.ts @@ -1,25 +1,28 @@ import { Project } from "../models/project"; import { usePrevious } from "./use-previous"; -import { useEffect, useState } from "preact/hooks"; +import { useEffect, useState, useRef } from "preact/hooks"; import { generate as diff } from "json-merge-patch"; import useDebounce from "./use-debounce"; export interface ServerSyncOptions { projectURL: string refreshInterval: number - syncDelay: number } export const defaultOptions = { - refreshInterval: 10000, + refreshInterval: 5000, projectURL: `//${window.location.host}/api/v1/projects`, - syncDelay: 5000, } export function useServerSync(project: Project, applyServerUpdate: (project: Project) => void, options: ServerSyncOptions = defaultOptions) { options = Object.assign({}, defaultOptions, options); - const [ version, setVersion ] = useState(0); + const [ serverState, setServerState ] = useState({ + version: 0, + project: project, + }); + + console.log('server state', serverState); const handleAPIResponse = (res: Response) => { // If the project does not yet exist, create it @@ -27,58 +30,56 @@ export function useServerSync(project: Project, applyServerUpdate: (project: Pro return createProject(project, options) .then(res => res.json()) .then(result => { - setVersion(result.version); + setServerState({ version: result.version, project }); }) ; } // In case of conflict, notify of new server version if (res.status === 409) { + console.log("server conflict detected"); return res.json().then((result: any) => { + console.log('received response', result); applyServerUpdate(result.project); - setVersion(result.version); + setServerState({ version: result.version, project: result.project }); }); } // If the server version is not modified, do nothing if (res.status === 304) { + console.log("no modification on server"); return; } return res.json().then((result: any) => { + console.log('received response', result); applyServerUpdate(result.project); - setVersion(result.version); + setServerState({ version: result.version, project: result.project }); }); }; // Force refresh periodically useEffect(() => { const intervalId = window.setInterval(() => { - refreshProject(project, version, options).then(handleAPIResponse); + console.time("server-sync"); + refreshProject(project, serverState.version, options).then(handleAPIResponse) + .then(() => { + console.timeEnd("server-sync"); + }); }, options.refreshInterval); return () => clearInterval(intervalId); - }, [version]); + }, [serverState]); + // Send delayed update useEffect(() => { - const timeoutId =window.setTimeout(() => { - console.log('executing debounced patch'); - - let previousProject: Project|any = usePrevious(project); - if (!previousProject) previousProject = {}; - - // Trigger patch if project has changed - - const patch = diff(previousProject, project); - - console.log('generated patch', patch); - + const timeoutId = window.setTimeout(() => { + const patch = diff(serverState.project, project); if (!patch) return; - - patchProject(project, patch, version, options).then(handleAPIResponse); - }, options.syncDelay); + patchProject(project, patch, serverState.version, options).then(handleAPIResponse); + }, 5000); return () => clearTimeout(timeoutId); - }); - + }, [project, serverState]); + } function refreshProject(project: Project, version: number, options: ServerSyncOptions): Promise {