Skip to content

Commit

Permalink
feat: requireConfirmationOnLargeDeletion
Browse files Browse the repository at this point in the history
  • Loading branch information
Dwynr committed Nov 28, 2024
1 parent 53c1885 commit 1c02a3f
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 147 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@filen/sync",
"version": "0.1.86",
"version": "0.1.87",
"description": "Filen Sync",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
297 changes: 151 additions & 146 deletions src/lib/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ export class Sync {

const confirmLocalDeletion = this.previousLocalTree.size > 0 && currentLocalTree.result.size === 0
const confirmRemoteDeletion = this.previousRemoteTree.size > 0 && currentRemoteTree.result.size === 0
let skipSyncDueToConfirmDeletionRestart = false

// If the previous tree has nodes and the current one is empty, we should prompt the user to confirm deletion
if (
Expand All @@ -429,190 +430,194 @@ export class Sync {
) {
this.deletionConfirmationResult = "waiting"

const result = await new Promise<"delete" | "restart">(resolve => {
const sendConfirmationMessage = () => {
postMessageToMain({
type: "confirmDeletion",
syncPair: this.syncPair,
data: {
where:
confirmLocalDeletion && confirmRemoteDeletion ? "both" : confirmLocalDeletion ? "local" : "remote",
previous:
confirmLocalDeletion && confirmRemoteDeletion
? this.previousLocalTree.size + this.previousRemoteTree.size
: confirmLocalDeletion
? this.previousLocalTree.size
: this.previousRemoteTree.size,
current:
confirmLocalDeletion && confirmRemoteDeletion
? currentLocalTree.result.size + currentRemoteTree.result.size
: confirmLocalDeletion
? currentLocalTree.result.size
: currentRemoteTree.result.size
}
})
}

sendConfirmationMessage()

await new Promise<void>(resolve => {
const interval = setInterval(() => {
if (this.deletionConfirmationResult !== "waiting") {
clearInterval(interval)

resolve(this.deletionConfirmationResult)
resolve()
} else {
postMessageToMain({
type: "confirmDeletion",
syncPair: this.syncPair,
data: {
where:
confirmLocalDeletion && confirmRemoteDeletion
? "both"
: confirmLocalDeletion
? "local"
: "remote",
previous:
confirmLocalDeletion && confirmRemoteDeletion
? this.previousLocalTree.size + this.previousRemoteTree.size
: confirmLocalDeletion
? this.previousLocalTree.size
: this.previousRemoteTree.size,
current:
confirmLocalDeletion && confirmRemoteDeletion
? currentLocalTree.result.size + currentRemoteTree.result.size
: confirmLocalDeletion
? currentLocalTree.result.size
: currentRemoteTree.result.size
}
})
sendConfirmationMessage()
}
}, 1000)
})

if (result === "restart") {
return
if (this.deletionConfirmationResult === "waiting" || this.deletionConfirmationResult === "restart") {
skipSyncDueToConfirmDeletionRestart = true
}
}

postMessageToMain({
type: "cycleProcessingDeltasStarted",
syncPair: this.syncPair
})

const deltas = await this.deltas.process({
currentLocalTree: currentLocalTree.result,
currentRemoteTree: currentRemoteTree.result,
previousLocalTree: this.previousLocalTree,
previousRemoteTree: this.previousRemoteTree,
currentLocalTreeErrors: currentLocalTree.errors
})

postMessageToMain({
type: "deltasCount",
syncPair: this.syncPair,
data: {
count: deltas.length
}
})
if (!skipSyncDueToConfirmDeletionRestart) {
postMessageToMain({
type: "cycleProcessingDeltasStarted",
syncPair: this.syncPair
})

postMessageToMain({
type: "deltasSize",
syncPair: this.syncPair,
data: {
size: deltas.reduce(
(prev, delta) => prev + (delta.type === "uploadFile" || delta.type === "downloadFile" ? delta.size : 0),
0
)
}
})
const deltas = await this.deltas.process({
currentLocalTree: currentLocalTree.result,
currentRemoteTree: currentRemoteTree.result,
previousLocalTree: this.previousLocalTree,
previousRemoteTree: this.previousRemoteTree,
currentLocalTreeErrors: currentLocalTree.errors
})

postMessageToMain({
type: "cycleProcessingDeltasDone",
syncPair: this.syncPair
})
postMessageToMain({
type: "deltasCount",
syncPair: this.syncPair,
data: {
count: deltas.length
}
})

postMessageToMain({
type: "cycleProcessingTasksStarted",
syncPair: this.syncPair
})
postMessageToMain({
type: "deltasSize",
syncPair: this.syncPair,
data: {
size: deltas.reduce(
(prev, delta) => prev + (delta.type === "uploadFile" || delta.type === "downloadFile" ? delta.size : 0),
0
)
}
})

const { doneTasks, errors } = await this.tasks.process({ deltasSorted: deltas })
postMessageToMain({
type: "cycleProcessingDeltasDone",
syncPair: this.syncPair
})

postMessageToMain({
type: "cycleProcessingTasksDone",
syncPair: this.syncPair
})
postMessageToMain({
type: "cycleProcessingTasksStarted",
syncPair: this.syncPair
})

postMessageToMain({
type: "taskErrors",
syncPair: this.syncPair,
data: {
errors: errors.map(e => ({
...e,
error: serializeError(e.error)
}))
}
})
const { doneTasks, errors } = await this.tasks.process({ deltasSorted: deltas })

this.taskErrors = errors
postMessageToMain({
type: "cycleProcessingTasksDone",
syncPair: this.syncPair
})

if (this.taskErrors.length === 0) {
if (doneTasks.length > 0) {
postMessageToMain({
type: "cycleApplyingStateStarted",
syncPair: this.syncPair
})
postMessageToMain({
type: "taskErrors",
syncPair: this.syncPair,
data: {
errors: errors.map(e => ({
...e,
error: serializeError(e.error)
}))
}
})

const didLocalChanges = doneTasks.some(
task =>
task.type === "createLocalDirectory" ||
task.type === "deleteLocalDirectory" ||
task.type === "deleteLocalFile" ||
task.type === "renameLocalDirectory" ||
task.type === "renameLocalFile"
)
const didRemoteChanges = doneTasks.some(
task =>
task.type === "renameRemoteDirectory" ||
task.type === "renameRemoteFile" ||
task.type === "createRemoteDirectory" ||
task.type === "deleteRemoteDirectory" ||
task.type === "deleteRemoteFile"
)

// Here we reset the internal local/remote tree changed times so we rescan after we did changes for consistency
if (didLocalChanges) {
this.localFileSystem.lastDirectoryChangeTimestamp = Date.now() - SYNC_INTERVAL * 2
this.localFileSystem.getDirectoryTreeCache = {
timestamp: 0,
tree: {},
inodes: {},
ignored: [],
errors: [],
size: 0
this.taskErrors = errors

if (this.taskErrors.length === 0) {
if (doneTasks.length > 0) {
postMessageToMain({
type: "cycleApplyingStateStarted",
syncPair: this.syncPair
})

const didLocalChanges = doneTasks.some(
task =>
task.type === "createLocalDirectory" ||
task.type === "deleteLocalDirectory" ||
task.type === "deleteLocalFile" ||
task.type === "renameLocalDirectory" ||
task.type === "renameLocalFile"
)
const didRemoteChanges = doneTasks.some(
task =>
task.type === "renameRemoteDirectory" ||
task.type === "renameRemoteFile" ||
task.type === "createRemoteDirectory" ||
task.type === "deleteRemoteDirectory" ||
task.type === "deleteRemoteFile"
)

// Here we reset the internal local/remote tree changed times so we rescan after we did changes for consistency
if (didLocalChanges) {
this.localFileSystem.lastDirectoryChangeTimestamp = Date.now() - SYNC_INTERVAL * 2
this.localFileSystem.getDirectoryTreeCache = {
timestamp: 0,
tree: {},
inodes: {},
ignored: [],
errors: [],
size: 0
}
}
}

if (didRemoteChanges) {
this.remoteFileSystem.getDirectoryTreeCache = {
timestamp: 0,
tree: {},
uuids: {},
ignored: [],
size: 0
if (didRemoteChanges) {
this.remoteFileSystem.getDirectoryTreeCache = {
timestamp: 0,
tree: {},
uuids: {},
ignored: [],
size: 0
}
}
}

const applied = this.state.applyDoneTasksToState({
doneTasks,
currentLocalTree: currentLocalTree.result,
currentRemoteTree: currentRemoteTree.result
})
const applied = this.state.applyDoneTasksToState({
doneTasks,
currentLocalTree: currentLocalTree.result,
currentRemoteTree: currentRemoteTree.result
})

currentLocalTree.result = applied.currentLocalTree
currentRemoteTree.result = applied.currentRemoteTree

currentLocalTree.result = applied.currentLocalTree
currentRemoteTree.result = applied.currentRemoteTree
postMessageToMain({
type: "cycleApplyingStateDone",
syncPair: this.syncPair
})
}

postMessageToMain({
type: "cycleApplyingStateDone",
type: "cycleSavingStateStarted",
syncPair: this.syncPair
})
}

postMessageToMain({
type: "cycleSavingStateStarted",
syncPair: this.syncPair
})
this.previousLocalTree = currentLocalTree.result
this.previousRemoteTree = currentRemoteTree.result

this.previousLocalTree = currentLocalTree.result
this.previousRemoteTree = currentRemoteTree.result
await this.state.save()

await this.state.save()
postMessageToMain({
type: "cycleSavingStateDone",
syncPair: this.syncPair
})
}

postMessageToMain({
type: "cycleSavingStateDone",
type: "cycleSuccess",
syncPair: this.syncPair
})
}

postMessageToMain({
type: "cycleSuccess",
syncPair: this.syncPair
})
}
} finally {
postMessageToMain({
Expand Down

0 comments on commit 1c02a3f

Please sign in to comment.