Event listeners

This commit is contained in:
Manav Rathi 2024-04-19 10:16:46 +05:30
parent 500bac0b32
commit 0e9703f770
No known key found for this signature in database

View file

@ -39,8 +39,16 @@ class FolderWatcher {
private currentEvent: WatchEvent;
// TODO(MR): dedup if possible
private isEventRunning: boolean = false;
/**
* If the file system directory corresponding to the (root) folder path of a
* folder watch is deleted on disk, we note down that in this queue so that
* we can ignore any file system events that come for it next.
*
* TODO (MR): is this really even coming into play? the mappings are
* pre-checked first.
*/
private deletedFolderPaths: string[] = [];
private currentlySyncedMapping: FolderWatch;
private trashingDirQueue: string[] = [];
private filePathToUploadedFileIDMap = new Map<string, EncryptedEnteFile>();
private unUploadableFilePaths = new Set<string>();
private setElectronFiles: (files: ElectronFile[]) => void;
@ -139,12 +147,11 @@ class FolderWatcher {
private async syncWithDisk() {
try {
const electron = ensureElectron();
const mappings = await electron.getWatchMappings();
if (!mappings) return;
const watches = await this.getWatches();
if (!watches) return;
this.eventQueue = [];
const { events } = await deduceEvents(mappings);
const events = await deduceEvents(watches);
log.info(`Folder watch deduced ${events.length} events`);
this.eventQueue = this.eventQueue.concat(events);
@ -160,22 +167,40 @@ class FolderWatcher {
this.debouncedRunNextEvent();
}
async pushTrashedDir(path: string) {
this.trashingDirQueue.push(path);
}
private registerListeners() {
const watch = ensureElectron().watcher;
const watch = ensureElectron().watch;
// [Note: File renames during folder watch]
//
// Renames come as two file system events - an `onAddFile` + an
// `onRemoveFile` - in an arbitrary order.
watch.onAddFile(
diskFileAddedCallback,
diskFileRemovedCallback,
diskFolderRemovedCallback,
);
watch.onAddFile((path: string, watch: FolderWatch) => {
this.pushEvent({
action: "upload",
collectionName: collectionNameForPath(path, watch),
folderPath: watch.folderPath,
filePath: path,
});
});
watch.onRemoveFile((path: string, watch: FolderWatch) => {
this.pushEvent({
action: "trash",
collectionName: collectionNameForPath(path, watch),
folderPath: watch.folderPath,
filePath: path,
});
});
watch.onRemoveDir((path: string, watch: FolderWatch) => {
if (path == watch.folderPath) {
log.info(
`Received file system delete event for a watched folder at ${path}`,
);
this.deletedFolderPaths.push(path);
}
});
}
private async runNextEvent() {
@ -446,7 +471,7 @@ class FolderWatcher {
private async processTrashEvent() {
try {
if (this.checkAndIgnoreIfFileEventsFromTrashedDir()) {
if (this.pruneFileEventsFromDeletedFolderPaths()) {
return;
}
@ -502,19 +527,14 @@ class FolderWatcher {
}
}
private checkAndIgnoreIfFileEventsFromTrashedDir() {
if (this.trashingDirQueue.length !== 0) {
this.ignoreFileEventsFromTrashedDir(this.trashingDirQueue[0]);
this.trashingDirQueue.shift();
return true;
}
return false;
}
private pruneFileEventsFromDeletedFolderPaths() {
const deletedFolderPath = this.deletedFolderPaths.shift();
if (!deletedFolderPath) return false;
private ignoreFileEventsFromTrashedDir(trashingDir: string) {
this.eventQueue = this.eventQueue.filter((event) =>
event.paths.every((path) => !path.startsWith(trashingDir)),
this.eventQueue = this.eventQueue.filter(
(event) => !event.filePath.startsWith(deletedFolderPath),
);
return true;
}
async getCollectionNameAndFolderPath(filePath: string) {
@ -594,60 +614,6 @@ interface WatchEvent {
filePath: string;
}
const onAddFile = async (path: string) => {
const collectionNameAndFolderPath =
await watcher.getCollectionNameAndFolderPath(path);
if (!collectionNameAndFolderPath) {
return;
}
const { collectionName, folderPath } = collectionNameAndFolderPath;
watcher.pushEvent({
action: "upload",
collectionName,
folderPath,
path: file.path,
});
};
async function diskFileRemovedCallback(filePath: string) {
const collectionNameAndFolderPath =
await watcher.getCollectionNameAndFolderPath(filePath);
if (!collectionNameAndFolderPath) {
return;
}
const { collectionName, folderPath } = collectionNameAndFolderPath;
const event: EventQueueItem = {
type: "trash",
collectionName,
folderPath,
path: filePath,
};
watcher.pushEvent(event);
}
async function diskFolderRemovedCallback(folderPath: string) {
try {
const mappings = await watcher.getWatchMappings();
const mapping = mappings.find(
(mapping) => mapping.folderPath === folderPath,
);
if (!mapping) {
log.info(`folder not found in mappings, ${folderPath}`);
throw Error(`Watch mapping not found`);
}
watcher.pushTrashedDir(folderPath);
log.info(`added trashedDir, ${folderPath}`);
} catch (e) {
log.error("error while calling diskFolderRemovedCallback", e);
}
}
export function getValidFilesToUpload(
files: ElectronFile[],
mapping: FolderWatch,