[bug]: Chokidar + reading projects spams multiple times (#6558)

fix: do not double or triple load reading folders from disk due to file system watcher when deleting
This commit is contained in:
Kevin Nadro
2025-04-28 18:15:20 -05:00
committed by GitHub
parent 1bd570ceb9
commit f6cb725268
3 changed files with 51 additions and 24 deletions

View File

@ -9,7 +9,7 @@ import {
useRequestedTextToCadGeneration, useRequestedTextToCadGeneration,
useFolders, useFolders,
} from '@src/machines/systemIO/hooks' } from '@src/machines/systemIO/hooks'
import { SystemIOMachineEvents } from '@src/machines/systemIO/utils' import { NO_PROJECT_DIRECTORY, SystemIOMachineEvents } from '@src/machines/systemIO/utils'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { useEffect } from 'react' import { useEffect } from 'react'
import { submitAndAwaitTextToKclSystemIO } from '@src/lib/textToCad' import { submitAndAwaitTextToKclSystemIO } from '@src/lib/textToCad'
@ -85,7 +85,7 @@ export function SystemIOMachineLogicListenerDesktop() {
const useWatchingApplicationProjectDirectory = () => { const useWatchingApplicationProjectDirectory = () => {
useFileSystemWatcher( useFileSystemWatcher(
async () => { async (eventType, path) => {
// Gotcha: Chokidar is buggy. It will emit addDir or add on files that did not get created. // Gotcha: Chokidar is buggy. It will emit addDir or add on files that did not get created.
// This means while the application initialize and Chokidar initializes you cannot tell if // This means while the application initialize and Chokidar initializes you cannot tell if
// a directory or file is actually created or they are buggy signals. This means you must // a directory or file is actually created or they are buggy signals. This means you must
@ -95,9 +95,18 @@ export function SystemIOMachineLogicListenerDesktop() {
if (!hasListedProjects) { if (!hasListedProjects) {
return return
} }
systemIOActor.send({
type: SystemIOMachineEvents.readFoldersFromProjectDirectory, const folderName = systemIOActor.getSnapshot().context.lastProjectDeleteRequest.project
}) const folderPath = `${projectDirectoryPath}${window.electron.sep}${folderName}`
if (folderName !== NO_PROJECT_DIRECTORY && (eventType === 'unlinkDir' || eventType === 'unlink') && path.includes(folderPath)) {
// NO OP: The systemIOMachine will be triggering the read in the state transition, don't spam it again
// once this event is processed after the deletion.
} else {
// Prevents spamming reading from disk twice on deletion due to files and folders being deleted async
systemIOActor.send({
type: SystemIOMachineEvents.readFoldersFromProjectDirectory,
})
}
}, },
settings.app.projectDirectory.current settings.app.projectDirectory.current
? [settings.app.projectDirectory.current] ? [settings.app.projectDirectory.current]

View File

@ -32,30 +32,34 @@ export const systemIOMachine = setup({
| { | {
type: SystemIOMachineEvents.done_checkReadWrite type: SystemIOMachineEvents.done_checkReadWrite
output: { value: boolean; error: unknown } output: { value: boolean; error: unknown }
} }
| { | {
type: SystemIOMachineEvents.setProjectDirectoryPath type: SystemIOMachineEvents.setProjectDirectoryPath
data: { requestedProjectDirectoryPath: string } data: { requestedProjectDirectoryPath: string }
} }
| { | {
type: SystemIOMachineEvents.navigateToProject type: SystemIOMachineEvents.navigateToProject
data: { requestedProjectName: string } data: { requestedProjectName: string }
} }
| { | {
type: SystemIOMachineEvents.navigateToFile type: SystemIOMachineEvents.navigateToFile
data: { requestedProjectName: string; requestedFileName: string } data: { requestedProjectName: string; requestedFileName: string }
} }
| { | {
type: SystemIOMachineEvents.createProject type: SystemIOMachineEvents.createProject
data: { requestedProjectName: string } data: { requestedProjectName: string }
} }
| { | {
type: SystemIOMachineEvents.renameProject type: SystemIOMachineEvents.renameProject
data: { requestedProjectName: string; projectName: string } data: { requestedProjectName: string; projectName: string }
} }
| { | {
type: SystemIOMachineEvents.deleteProject type: SystemIOMachineEvents.deleteProject
data: { requestedProjectName: string } data: { requestedProjectName: string }
}
| {
type: SystemIOMachineEvents.done_deleteProject
output: { message: string; name: string }
} }
| { | {
type: SystemIOMachineEvents.createKCLFile type: SystemIOMachineEvents.createKCLFile
@ -165,6 +169,12 @@ export const systemIOMachine = setup({
return event.data return event.data
}, },
}), }),
[SystemIOMachineActions.setLastProjectDeleteRequest]: assign({
lastProjectDeleteRequest: ({ event }) => {
assertEvent(event, SystemIOMachineEvents.done_deleteProject)
return {project: event.output.name}
},
}),
}, },
actors: { actors: {
[SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise( [SystemIOMachineActors.readFoldersFromProjectDirectory]: fromPromise(
@ -275,6 +285,9 @@ export const systemIOMachine = setup({
requestedProjectName: NO_PROJECT_DIRECTORY, requestedProjectName: NO_PROJECT_DIRECTORY,
isProjectNew: true, isProjectNew: true,
}, },
lastProjectDeleteRequest: {
project: NO_PROJECT_DIRECTORY
}
}), }),
states: { states: {
[SystemIOMachineStates.idle]: { [SystemIOMachineStates.idle]: {
@ -401,7 +414,7 @@ export const systemIOMachine = setup({
}, },
onDone: { onDone: {
target: SystemIOMachineStates.readingFolders, target: SystemIOMachineStates.readingFolders,
actions: [SystemIOMachineActions.toastSuccess], actions: [SystemIOMachineActions.toastSuccess, SystemIOMachineActions.setLastProjectDeleteRequest]
}, },
onError: { onError: {
target: SystemIOMachineStates.idle, target: SystemIOMachineStates.idle,

View File

@ -37,6 +37,7 @@ export enum SystemIOMachineEvents {
createProject = 'create project', createProject = 'create project',
renameProject = 'rename project', renameProject = 'rename project',
deleteProject = 'delete project', deleteProject = 'delete project',
done_deleteProject = donePrefix + 'delete project',
createKCLFile = 'create kcl file', createKCLFile = 'create kcl file',
setDefaultProjectFolderName = 'set default project folder name', setDefaultProjectFolderName = 'set default project folder name',
done_checkReadWrite = donePrefix + 'check read write', done_checkReadWrite = donePrefix + 'check read write',
@ -56,6 +57,7 @@ export enum SystemIOMachineActions {
toastError = 'toastError', toastError = 'toastError',
setReadWriteProjectDirectory = 'set read write project directory', setReadWriteProjectDirectory = 'set read write project directory',
setRequestedTextToCadGeneration = 'set requested text to cad generation', setRequestedTextToCadGeneration = 'set requested text to cad generation',
setLastProjectDeleteRequest = 'set last project delete request'
} }
export const NO_PROJECT_DIRECTORY = '' export const NO_PROJECT_DIRECTORY = ''
@ -80,4 +82,7 @@ export type SystemIOContext = {
requestedProjectName: string requestedProjectName: string
isProjectNew: boolean isProjectNew: boolean
} }
lastProjectDeleteRequest: {
project: string
}
} }