Notes2/static/js/sync.mjs
Magnus Åhall 1c3116d9dc More sync
2025-01-12 16:06:28 +01:00

106 lines
3.1 KiB
JavaScript

import { API } from 'api'
import { Node } from 'node'
export class Sync {
constructor() {
this.foo = ''
}
static async nodesFromServer() {//{{{
let duration = 0
const syncStart = Date.now()
try {
// The latest sync node value is used to retrieve the changes
// from the backend.
const state = await nodeStore.getAppState('latest_sync_node')
const clientUUID = await nodeStore.getAppState('client_uuid')
const oldMax = (state?.value ? state.value : 0)
let currMax = oldMax
let offset = 0
let res = { Continue: false }
let batch = 0
do {
batch++
res = await API.query('POST', `/sync/from_server/${oldMax}/${offset}`, { ClientUUID: clientUUID.value })
if (res.Nodes.length > 0)
console.log(`Node sync batch #${batch}`)
offset += res.Nodes.length
currMax = Math.max(currMax, res.MaxSeq)
/* Go through each node and determine if they are older than
* the node in IndexedDB. If they are, they are just history
* and can be ignored since history is currently not stored
* in the browser.
*
* If the backed node is newer, the local node is stored in
* a separate table in IndexedDB to at a later stage in the
* sync be preserved in the backend. */
let backendNode = null
for (const i in res.Nodes) {
backendNode = new Node(res.Nodes[i], -1)
await Sync.handleNode(backendNode)
}
} while (res.Continue)
nodeStore.setAppState('latest_sync_node', currMax)
} catch (e) {
console.log('sync node tree', e)
} finally {
const syncEnd = Date.now()
duration = (syncEnd - syncStart) / 1000
const count = await nodeStore.nodeCount()
console.log(`Node sync took ${duration}s`, count)
}
return duration
}//}}}
static async handleNode(backendNode) {//{{{
try {
/* Retrieving the local copy of this node from IndexedDB.
* The backend node can be discarded if it is older than
* the local copy since it is considered history preserved
* in the backend. */
return nodeStore.get(backendNode.UUID)
.then(async localNode => {
if (localNode.updated() >= backendNode.updated()) {
console.log(`History from backend: ${backendNode.UUID}`)
return
}
/* If the local node hasn't seen unsynchronized change,
* it can be replaced without anything else being done
* since it is already on the backend server.
*
* If the local node has seen change, the change is already
* placed into the send_queue anyway. */
return nodeStore.add([backendNode])
})
.catch(async () => {
// Not found in IndexedDB - OK to just insert since it only exists in backend.
return nodeStore.add([backendNode])
})
} catch (e) {
console.error(e)
}
}//}}}
static async nodesToServer() {//{{{
try {
const nodesToSend = await nodeStore.sendQueue.retrieve(100)
const clientUUID = await nodeStore.getAppState('client_uuid')
const request = {
NodeData: JSON.stringify(nodesToSend),
ClientUUID: clientUUID.value,
}
res = await API.query('POST', `/sync/to_server/${oldMax}/${offset}`, request)
console.log(res)
} catch (e) {
console.log(e)
alert(e)
}
}//}}}
}