修复潜在同步问题

pull/1583/head
lyswhut 2023-09-06 21:50:58 +08:00
parent fcffcb5b59
commit 3685cb8868
12 changed files with 51 additions and 32 deletions

View File

@ -189,12 +189,12 @@ export const connect = (urlInfo: LX.Sync.Client.UrlInfo, keyInfo: LX.Sync.Client
onError(error, path, groupName) { onError(error, path, groupName) {
const name = groupName ?? '' const name = groupName ?? ''
log.error(`sync call ${name} ${path.join('.')} error:`, error) log.error(`sync call ${name} ${path.join('.')} error:`, error)
if (groupName == null) return // if (groupName == null) return
client?.close(SYNC_CLOSE_CODE.failed) // client?.close(SYNC_CLOSE_CODE.failed)
sendSyncStatus({ // sendSyncStatus({
status: false, // status: false,
message: error.message, // message: error.message,
}) // })
}, },
}) })

View File

@ -1,6 +1,7 @@
import fs from 'node:fs' import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { File } from '../../../../common/constants_sync' import { File } from '../../../../common/constants_sync'
import { exists } from '../utils'
let syncAuthKeys: Record<string, LX.Sync.ClientKeyInfo> let syncAuthKeys: Record<string, LX.Sync.ClientKeyInfo>
@ -11,7 +12,6 @@ const saveSyncAuthKeys = async() => {
return fs.promises.writeFile(syncAuthKeysFilePath, JSON.stringify(syncAuthKeys), 'utf8') return fs.promises.writeFile(syncAuthKeysFilePath, JSON.stringify(syncAuthKeys), 'utf8')
} }
const exists = async(path: string) => fs.promises.stat(path).then(() => true).catch(() => false)
export const initClientInfo = async() => { export const initClientInfo = async() => {
if (syncAuthKeys != null) return if (syncAuthKeys != null) return
const syncAuthKeysFilePath = path.join(global.lxDataPath, File.clientDataPath, File.syncAuthKeysJSON) const syncAuthKeysFilePath = path.join(global.lxDataPath, File.clientDataPath, File.syncAuthKeysJSON)

View File

@ -1,3 +1,4 @@
import { SYNC_CLOSE_CODE } from '@common/constants_sync'
import { registerDislikeActionEvent } from '@main/modules/sync/dislikeEvent' import { registerDislikeActionEvent } from '@main/modules/sync/dislikeEvent'
let unregisterLocalListAction: (() => void) | null let unregisterLocalListAction: (() => void) | null
@ -11,7 +12,12 @@ export const registerEvent = (socket: LX.Sync.Client.Socket) => {
unregisterEvent() unregisterEvent()
unregisterLocalListAction = registerDislikeActionEvent((action) => { unregisterLocalListAction = registerDislikeActionEvent((action) => {
if (!socket.moduleReadys?.dislike) return if (!socket.moduleReadys?.dislike) return
void socket.remoteQueueDislike.onDislikeSyncAction(action) void socket.remoteQueueDislike.onDislikeSyncAction(action).catch(err => {
// TODO send status
socket.moduleReadys.dislike = false
socket.close(SYNC_CLOSE_CODE.failed)
console.log(err.message)
})
}) })
} }

View File

@ -1,3 +1,4 @@
import { SYNC_CLOSE_CODE } from '@common/constants_sync'
import { registerListActionEvent } from '@main/modules/sync/listEvent' import { registerListActionEvent } from '@main/modules/sync/listEvent'
let unregisterLocalListAction: (() => void) | null let unregisterLocalListAction: (() => void) | null
@ -11,7 +12,12 @@ export const registerEvent = (socket: LX.Sync.Client.Socket) => {
unregisterEvent() unregisterEvent()
unregisterLocalListAction = registerListActionEvent((action) => { unregisterLocalListAction = registerListActionEvent((action) => {
if (!socket.moduleReadys?.list) return if (!socket.moduleReadys?.list) return
void socket.remoteQueueList.onListSyncAction(action) void socket.remoteQueueList.onListSyncAction(action).catch(err => {
// TODO send status
socket.moduleReadys.list = false
socket.close(SYNC_CLOSE_CODE.failed)
console.log(err.message)
})
}) })
} }

View File

@ -1,6 +1,7 @@
import { File } from '../../../common/constants_sync' import { File } from '../../../common/constants_sync'
import fs from 'node:fs' import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import { exists } from './utils'
interface ServerKeyInfo { interface ServerKeyInfo {
clientId: string clientId: string
@ -13,8 +14,6 @@ interface ServerKeyInfo {
} }
const exists = async(path: string) => fs.promises.stat(path).then(() => true).catch(() => false)
// 迁移 v2 sync 数据 // 迁移 v2 sync 数据
export default async(dataPath: string) => { export default async(dataPath: string) => {
const syncDataPath = path.join(dataPath, 'sync') const syncDataPath = path.join(dataPath, 'sync')

View File

@ -27,13 +27,14 @@ export class DislikeManage {
} }
getCurrentListInfoKey = async() => { getCurrentListInfoKey = async() => {
const snapshotInfo = await this.snapshotDataManage.getSnapshotInfo() // const snapshotInfo = await this.snapshotDataManage.getSnapshotInfo()
if (snapshotInfo.latest) { // if (snapshotInfo.latest) {
return snapshotInfo.latest // return snapshotInfo.latest
} // }
snapshotInfo.latest = toMD5((await this.getDislikeRules()).trim()) // snapshotInfo.latest = toMD5((await this.getDislikeRules()).trim())
this.snapshotDataManage.saveSnapshotInfo(snapshotInfo) // this.snapshotDataManage.saveSnapshotInfo(snapshotInfo)
return snapshotInfo.latest // return snapshotInfo.latest
return this.createSnapshot()
} }
getDeviceCurrentSnapshotKey = async(clientId: string) => { getDeviceCurrentSnapshotKey = async(clientId: string) => {

View File

@ -23,7 +23,7 @@ const getRemoteDataMD5 = async(socket: LX.Sync.Server.Socket): Promise<string> =
} }
// const getLocalDislikeData async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.Dislike.ListData> => { // const getLocalDislikeData async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.Dislike.ListData> => {
// return getUserSpace(socket.userInfo.name).listManage.getListData() // return getUserSpace(socket.userInfo.name).dislikeManage.getListData()
// } // }
const getSyncMode = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.Dislike.SyncMode> => new Promise((resolve, reject) => { const getSyncMode = async(socket: LX.Sync.Server.Socket): Promise<LX.Sync.Dislike.SyncMode> => new Promise((resolve, reject) => {
const handleDisconnect = (err: Error) => { const handleDisconnect = (err: Error) => {
@ -54,7 +54,7 @@ const finishedSync = async(socket: LX.Sync.Server.Socket) => {
const setLocalList = async(socket: LX.Sync.Server.Socket, listData: LX.Dislike.DislikeRules) => { const setLocalList = async(socket: LX.Sync.Server.Socket, listData: LX.Dislike.DislikeRules) => {
await setLocalDislikeData(listData) await setLocalDislikeData(listData)
const userSpace = getUserSpace(socket.userInfo.name) const userSpace = getUserSpace(socket.userInfo.name)
return userSpace.listManage.createSnapshot() return userSpace.dislikeManage.createSnapshot()
} }
const overwriteRemoteListData = async(socket: LX.Sync.Server.Socket, listData: LX.Dislike.DislikeRules, key: string, excludeIds: string[] = []) => { const overwriteRemoteListData = async(socket: LX.Sync.Server.Socket, listData: LX.Dislike.DislikeRules, key: string, excludeIds: string[] = []) => {
@ -196,7 +196,8 @@ const handleMergeListDataFromSnapshot = async(socket: LX.Sync.Server.Socket, sna
const syncDislike = async(socket: LX.Sync.Server.Socket) => { const syncDislike = async(socket: LX.Sync.Server.Socket) => {
// socket.data.snapshotFilePath = getSnapshotFilePath(socket.keyInfo) // socket.data.snapshotFilePath = getSnapshotFilePath(socket.keyInfo)
// console.log(socket.keyInfo) // console.log(socket.keyInfo)
if (!(socket.feature.dislike as LX.Sync.DislikeConfig).skipSnapshot) { if (!socket.feature.dislike) throw new Error('dislike feature options not available')
if (!socket.feature.dislike.skipSnapshot) {
const user = getUserSpace(socket.userInfo.name) const user = getUserSpace(socket.userInfo.name)
const userCurrentDislikeInfoKey = await user.dislikeManage.getDeviceCurrentSnapshotKey(socket.keyInfo.clientId) const userCurrentDislikeInfoKey = await user.dislikeManage.getDeviceCurrentSnapshotKey(socket.keyInfo.clientId)
if (userCurrentDislikeInfoKey) { if (userCurrentDislikeInfoKey) {

View File

@ -27,13 +27,14 @@ export class ListManage {
} }
getCurrentListInfoKey = async() => { getCurrentListInfoKey = async() => {
const snapshotInfo = await this.snapshotDataManage.getSnapshotInfo() // const snapshotInfo = await this.snapshotDataManage.getSnapshotInfo()
if (snapshotInfo.latest) { // if (snapshotInfo.latest) {
return snapshotInfo.latest // return snapshotInfo.latest
} // }
snapshotInfo.latest = toMD5(JSON.stringify(await this.getListData())) // snapshotInfo.latest = toMD5(JSON.stringify(await this.getListData()))
this.snapshotDataManage.saveSnapshotInfo(snapshotInfo) // this.snapshotDataManage.saveSnapshotInfo(snapshotInfo)
return snapshotInfo.latest // return snapshotInfo.latest
return this.createSnapshot()
} }
getDeviceCurrentSnapshotKey = async(clientId: string) => { getDeviceCurrentSnapshotKey = async(clientId: string) => {

View File

@ -398,7 +398,8 @@ const handleMergeListDataFromSnapshot = async(socket: LX.Sync.Server.Socket, sna
const syncList = async(socket: LX.Sync.Server.Socket) => { const syncList = async(socket: LX.Sync.Server.Socket) => {
// socket.data.snapshotFilePath = getSnapshotFilePath(socket.keyInfo) // socket.data.snapshotFilePath = getSnapshotFilePath(socket.keyInfo)
// console.log(socket.keyInfo) // console.log(socket.keyInfo)
if (!(socket.feature.list as LX.Sync.ListConfig).skipSnapshot) { if (!socket.feature.list) throw new Error('list feature options not available')
if (!socket.feature.list.skipSnapshot) {
const user = getUserSpace(socket.userInfo.name) const user = getUserSpace(socket.userInfo.name)
const userCurrentListInfoKey = await user.listManage.getDeviceCurrentSnapshotKey(socket.keyInfo.clientId) const userCurrentListInfoKey = await user.listManage.getDeviceCurrentSnapshotKey(socket.keyInfo.clientId)
if (userCurrentListInfoKey) { if (userCurrentListInfoKey) {

View File

@ -192,8 +192,8 @@ const handleStartServer = async(port = 9527, ip = '0.0.0.0') => await new Promis
const name = groupName ?? '' const name = groupName ?? ''
const deviceName = socket.keyInfo?.deviceName ?? '' const deviceName = socket.keyInfo?.deviceName ?? ''
log.error(`sync call ${deviceName} ${name} ${path.join('.')} error:`, error) log.error(`sync call ${deviceName} ${name} ${path.join('.')} error:`, error)
if (groupName == null) return // if (groupName == null) return
socket.close(SYNC_CLOSE_CODE.failed) // socket.close(SYNC_CLOSE_CODE.failed)
}, },
}) })
socket.remote = msg2call.remote socket.remote = msg2call.remote

View File

@ -4,6 +4,7 @@ import { randomBytes } from 'node:crypto'
import { throttle } from '@common/utils/common' import { throttle } from '@common/utils/common'
import { filterFileName, toMD5 } from '../utils' import { filterFileName, toMD5 } from '../utils'
import { File } from '@common/constants_sync' import { File } from '@common/constants_sync'
import { exists } from '../../utils'
interface ServerInfo { interface ServerInfo {
@ -20,7 +21,6 @@ const saveServerInfoThrottle = throttle(() => {
}) })
}) })
let serverInfo: ServerInfo let serverInfo: ServerInfo
const exists = async(path: string) => fs.promises.stat(path).then(() => true).catch(() => false)
export const initServerInfo = async() => { export const initServerInfo = async() => {
if (serverInfo != null) return if (serverInfo != null) return
const serverInfoFilePath = path.join(global.lxDataPath, File.serverDataPath, File.serverInfoJSON) const serverInfoFilePath = path.join(global.lxDataPath, File.serverDataPath, File.serverInfoJSON)

View File

@ -1,5 +1,6 @@
import { createCipheriv, createDecipheriv, publicEncrypt, privateDecrypt, constants } from 'node:crypto' import { createCipheriv, createDecipheriv, publicEncrypt, privateDecrypt, constants } from 'node:crypto'
import os, { networkInterfaces } from 'node:os' import os, { networkInterfaces } from 'node:os'
import fs from 'node:fs'
import zlib from 'node:zlib' import zlib from 'node:zlib'
import cp from 'node:child_process' import cp from 'node:child_process'
@ -88,3 +89,6 @@ export const rsaEncrypt = (buffer: Buffer, key: string): string => {
export const rsaDecrypt = (buffer: Buffer, key: string): Buffer => { export const rsaDecrypt = (buffer: Buffer, key: string): Buffer => {
return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer) return privateDecrypt({ key, padding: constants.RSA_PKCS1_OAEP_PADDING }, buffer)
} }
export const exists = async(path: string) => fs.promises.stat(path).then(() => true).catch(() => false)