Fix server synchronization
This commit is contained in:
parent
20d88852b1
commit
acde2a7db1
|
@ -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,57 +30,55 @@ 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]);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue