more fixes
This commit is contained in:
parent
8ce33541a3
commit
7a8c497462
6 changed files with 94 additions and 38 deletions
|
|
@ -38,8 +38,16 @@ export class SyncEventQueue {
|
|||
// It maps pending changes onto the local filesystem.
|
||||
private readonly events: SyncEvent[] = [];
|
||||
|
||||
// file creations for paths matching any of these patterns will be ignored
|
||||
private ignorePatterns: RegExp[];
|
||||
// file creations for paths matching any of these patterns are ignored
|
||||
// because the user explicitly told us to ignore them.
|
||||
private userIgnorePatterns: RegExp[];
|
||||
|
||||
// Whether `CONFLICT_PATH_REGEX` is applied at enqueue time. Conflict files
|
||||
// exist because the syncer set them aside; ignoring them at runtime
|
||||
// prevents resync churn. During an offline scan we DO want to surface them
|
||||
// so a stranded conflict file (e.g. one this client previously displaced
|
||||
// and was unable to re-sync) gets picked up as a normal new file.
|
||||
private ignoreConflictPaths = true;
|
||||
|
||||
public constructor(
|
||||
private readonly settings: Settings,
|
||||
|
|
@ -47,19 +55,16 @@ export class SyncEventQueue {
|
|||
initialState: Partial<StoredSyncState> | undefined,
|
||||
private readonly saveData: (data: StoredSyncState) => Promise<void>
|
||||
) {
|
||||
this.ignorePatterns = [
|
||||
CONFLICT_PATH_REGEX, // conflict paths need to be resolved before they can be synced again
|
||||
...globsToRegexes(
|
||||
this.settings.getSettings().ignorePatterns,
|
||||
this.logger
|
||||
)
|
||||
];
|
||||
this.userIgnorePatterns = globsToRegexes(
|
||||
this.settings.getSettings().ignorePatterns,
|
||||
this.logger
|
||||
);
|
||||
|
||||
this.settings.onSettingsChanged.add((newSettings) => {
|
||||
this.ignorePatterns = [
|
||||
CONFLICT_PATH_REGEX,
|
||||
...globsToRegexes(newSettings.ignorePatterns, this.logger)
|
||||
];
|
||||
this.userIgnorePatterns = globsToRegexes(
|
||||
newSettings.ignorePatterns,
|
||||
this.logger
|
||||
);
|
||||
});
|
||||
|
||||
initialState ??= {};
|
||||
|
|
@ -94,19 +99,35 @@ export class SyncEventQueue {
|
|||
this._lastSeenUpdateId.add(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle whether `CONFLICT_PATH_REGEX` filters incoming events. The
|
||||
* offline scan flips this off so a stranded conflict file gets surfaced
|
||||
* as a regular create; everywhere else conflict files stay ignored.
|
||||
*/
|
||||
public setIgnoreConflictPaths(ignore: boolean): void {
|
||||
this.ignoreConflictPaths = ignore;
|
||||
}
|
||||
|
||||
public async enqueue(input: FileSyncEvent): Promise<void> {
|
||||
const path =
|
||||
input.type === SyncEventType.RemoteChange
|
||||
? input.remoteVersion.relativePath
|
||||
: input.path;
|
||||
|
||||
if (this.ignorePatterns.some((pattern) => pattern.test(path))) {
|
||||
if (this.userIgnorePatterns.some((pattern) => pattern.test(path))) {
|
||||
this.logger.info(
|
||||
`Ignoring ${input.type} for ${path} as it matches ignore patterns`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.ignoreConflictPaths && CONFLICT_PATH_REGEX.test(path)) {
|
||||
this.logger.info(
|
||||
`Ignoring ${input.type} for ${path} as it is a conflict path`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (input.type === SyncEventType.RemoteChange) {
|
||||
this.events.push(input);
|
||||
return;
|
||||
|
|
@ -198,11 +219,23 @@ export class SyncEventQueue {
|
|||
|
||||
/**
|
||||
* Update the settled document map and persist the new document version.
|
||||
*
|
||||
* If the document is already tracked under a different path (e.g. after a
|
||||
* rename) the old entry is removed so the map stays keyed by the latest
|
||||
* disk path and `getDocumentByDocumentId` can't return a stale match.
|
||||
*/
|
||||
public async setDocument(
|
||||
path: RelativePath,
|
||||
record: DocumentRecord
|
||||
): Promise<void> {
|
||||
for (const [existingPath, existingRecord] of this.documents) {
|
||||
if (
|
||||
existingPath !== path &&
|
||||
existingRecord.documentId === record.documentId
|
||||
) {
|
||||
this.documents.delete(existingPath);
|
||||
}
|
||||
}
|
||||
this.documents.set(path, record);
|
||||
return this.save();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ export class Syncer {
|
|||
|
||||
private readonly queue: SyncEventQueue;
|
||||
|
||||
private _isFirstSyncStarted = false;
|
||||
private runningScheduleSyncForOfflineChanges: Promise<void> | undefined;
|
||||
private drainPromise: Promise<void> | undefined;
|
||||
private isScanning = false;
|
||||
|
|
@ -75,10 +74,6 @@ export class Syncer {
|
|||
);
|
||||
}
|
||||
|
||||
public get isFirstSyncStarted(): boolean {
|
||||
return this._isFirstSyncStarted;
|
||||
}
|
||||
|
||||
public syncLocallyCreatedFile(relativePath: RelativePath): void {
|
||||
void this.queue.enqueue({
|
||||
type: SyncEventType.LocalCreate,
|
||||
|
|
@ -121,8 +116,6 @@ export class Syncer {
|
|||
});
|
||||
|
||||
this.ensureDraining();
|
||||
|
||||
this._isFirstSyncStarted = true;
|
||||
}
|
||||
|
||||
public async scheduleSyncForOfflineChanges(): Promise<void> {
|
||||
|
|
@ -160,7 +153,6 @@ export class Syncer {
|
|||
}
|
||||
|
||||
public reset(): void {
|
||||
this._isFirstSyncStarted = false;
|
||||
this.queue.clearPending();
|
||||
const current = this.runningScheduleSyncForOfflineChanges;
|
||||
if (current !== undefined) {
|
||||
|
|
@ -184,6 +176,10 @@ export class Syncer {
|
|||
|
||||
private async internalScheduleSyncForOfflineChanges(): Promise<void> {
|
||||
this.isScanning = true;
|
||||
// Surface stranded conflict files (e.g. ones we displaced in a prior
|
||||
// session and never resynced) as regular creates during the scan; the
|
||||
// queue re-enables conflict filtering when we're done.
|
||||
this.queue.setIgnoreConflictPaths(false);
|
||||
try {
|
||||
while (this.drainPromise !== undefined) {
|
||||
await this.drainPromise;
|
||||
|
|
@ -203,6 +199,7 @@ export class Syncer {
|
|||
}
|
||||
);
|
||||
} finally {
|
||||
this.queue.setIgnoreConflictPaths(true);
|
||||
this.isScanning = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue