asch/fix-everything #188
2 changed files with 28 additions and 77 deletions
Fix mock client event triggering
commit
7c203bc5c9
|
|
@ -307,7 +307,7 @@ export class MockAgent extends MockClient {
|
||||||
);
|
);
|
||||||
if (fileContent.split(content).length > 2) {
|
if (fileContent.split(content).length > 2) {
|
||||||
if (this.useSlowFileEvents) {
|
if (this.useSlowFileEvents) {
|
||||||
logger.warn(
|
this.client.logger.warn(
|
||||||
`Content ${content} (of ${this.name}) found more than once in '${file}'. File content:\n${fileContent}`
|
`Content ${content} (of ${this.name}) found more than once in '${file}'. File content:\n${fileContent}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -369,9 +369,8 @@ export class MockAgent extends MockClient {
|
||||||
`Decided to create file ${file} with content ${content}`
|
`Decided to create file ${file} with content ${content}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.create(file, new TextEncoder().encode(` ${content} `), {
|
|
||||||
ignoreSlowFileEvents: true
|
return this.write(file, new TextEncoder().encode(` ${content} `),);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary file creation — exercises the putBinary server path (not in mergeable_file_extensions)
|
// Binary file creation — exercises the putBinary server path (not in mergeable_file_extensions)
|
||||||
|
|
@ -388,12 +387,10 @@ export class MockAgent extends MockClient {
|
||||||
|
|
||||||
const { uuid, bytes } = this.getBinaryContent();
|
const { uuid, bytes } = this.getBinaryContent();
|
||||||
this.client.logger.info(
|
this.client.logger.info(
|
||||||
`Decided to create binary file ${file}`
|
`Decided to create binary file ${file}: ${uuid}`
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.create(file, bytes, {
|
return this.write(file, bytes,);
|
||||||
ignoreSlowFileEvents: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async disableSyncAction(): Promise<void> {
|
private async disableSyncAction(): Promise<void> {
|
||||||
|
|
@ -450,14 +447,6 @@ export class MockAgent extends MockClient {
|
||||||
|
|
||||||
this.client.logger.info(`Renamed file: ${file} -> ${newName}`);
|
this.client.logger.info(`Renamed file: ${file} -> ${newName}`);
|
||||||
await this.rename(file, newName);
|
await this.rename(file, newName);
|
||||||
this.executeFileOperation(
|
|
||||||
async () =>
|
|
||||||
this.client.syncLocallyUpdatedFile({
|
|
||||||
oldPath: file,
|
|
||||||
relativePath: newName
|
|
||||||
}),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateFileAction(): Promise<void> {
|
private async updateFileAction(): Promise<void> {
|
||||||
|
|
@ -495,13 +484,6 @@ export class MockAgent extends MockClient {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.executeFileOperation(
|
|
||||||
async () =>
|
|
||||||
this.client.syncLocallyUpdatedFile({
|
|
||||||
relativePath: file
|
|
||||||
}),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateBinaryFileAction(): Promise<void> {
|
private async updateBinaryFileAction(): Promise<void> {
|
||||||
|
|
@ -530,13 +512,7 @@ export class MockAgent extends MockClient {
|
||||||
this.doNotTouchWhileOffline.push(file);
|
this.doNotTouchWhileOffline.push(file);
|
||||||
this.files.set(file, bytes);
|
this.files.set(file, bytes);
|
||||||
|
|
||||||
this.executeFileOperation(
|
|
||||||
async () =>
|
|
||||||
this.client.syncLocallyUpdatedFile({
|
|
||||||
relativePath: file
|
|
||||||
}),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async deleteFileAction(): Promise<void> {
|
private async deleteFileAction(): Promise<void> {
|
||||||
|
|
@ -554,10 +530,7 @@ export class MockAgent extends MockClient {
|
||||||
`Deleting file: ${file} with:\n content '${new TextDecoder().decode(this.files.get(file))}'`
|
`Deleting file: ${file} with:\n content '${new TextDecoder().decode(this.files.get(file))}'`
|
||||||
);
|
);
|
||||||
await this.delete(file);
|
await this.delete(file);
|
||||||
this.executeFileOperation(
|
|
||||||
async () => this.client.syncLocallyDeletedFile(file),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getContent(): string {
|
private getContent(): string {
|
||||||
|
|
|
||||||
|
|
@ -40,37 +40,22 @@ export class MockClient extends debugging.InMemoryFileSystem {
|
||||||
await this.client.start();
|
await this.client.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async create(
|
|
||||||
path: RelativePath,
|
|
||||||
newContent: Uint8Array,
|
|
||||||
{ ignoreSlowFileEvents }: { ignoreSlowFileEvents: boolean } = {
|
|
||||||
ignoreSlowFileEvents: false
|
|
||||||
}
|
|
||||||
): Promise<void> {
|
|
||||||
if (this.files.has(path)) {
|
|
||||||
throw new Error(`File ${path} already exists`);
|
|
||||||
}
|
|
||||||
this.client.logger.info(
|
|
||||||
`Creating file ${path} with content ${new TextDecoder().decode(newContent)}`
|
|
||||||
);
|
|
||||||
this.files.set(path, newContent);
|
|
||||||
|
|
||||||
|
public override async write(
|
||||||
|
path: RelativePath,
|
||||||
|
content: Uint8Array
|
||||||
|
): Promise<void> {
|
||||||
|
this.files.set(path, content);
|
||||||
this.executeFileOperation(
|
this.executeFileOperation(
|
||||||
async () => this.client.syncLocallyCreatedFile(path),
|
async () => this.client.syncLocallyUpdatedFile({ relativePath: path }),
|
||||||
ignoreSlowFileEvents
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async atomicUpdateText(
|
public override async atomicUpdateText(
|
||||||
path: RelativePath,
|
path: RelativePath,
|
||||||
updater: (currentContent: TextWithCursors) => TextWithCursors
|
updater: (currentContent: TextWithCursors) => TextWithCursors
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
// This method is called by BOTH the sync client (for remote text
|
|
||||||
// merges) and the test agent (for user updates). We must NOT call
|
|
||||||
// executeFileOperation here because the sync-client path would
|
|
||||||
// echo remote writes back as local modifications, creating an
|
|
||||||
// infinite sync loop. The test agent calls executeFileOperation
|
|
||||||
// separately after this method returns.
|
|
||||||
const file = this.files.get(path);
|
const file = this.files.get(path);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw new Error(`File ${path} does not exist`);
|
throw new Error(`File ${path} does not exist`);
|
||||||
|
|
@ -80,38 +65,26 @@ export class MockClient extends debugging.InMemoryFileSystem {
|
||||||
const newContentUint8Array = new TextEncoder().encode(newContent);
|
const newContentUint8Array = new TextEncoder().encode(newContent);
|
||||||
this.files.set(path, newContentUint8Array);
|
this.files.set(path, newContentUint8Array);
|
||||||
|
|
||||||
|
this.executeFileOperation(
|
||||||
|
async () => this.client.syncLocallyUpdatedFile({ relativePath: path }),
|
||||||
|
);
|
||||||
|
|
||||||
return newContent;
|
return newContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async write(
|
|
||||||
path: RelativePath,
|
|
||||||
content: Uint8Array
|
|
||||||
): Promise<void> {
|
|
||||||
// This method is called by the sync client when writing files
|
|
||||||
// received from the server (remote updates). Do NOT call
|
|
||||||
// executeFileOperation here — that would echo the remote write
|
|
||||||
// back as a local modification, creating an infinite sync loop.
|
|
||||||
// User-initiated writes go through create(), atomicUpdateText(),
|
|
||||||
// or direct files.set() + executeFileOperation() in mock-agent.
|
|
||||||
this.files.set(path, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async delete(path: RelativePath): Promise<void> {
|
public override async delete(path: RelativePath): Promise<void> {
|
||||||
// Just perform the filesystem operation. The test agent calls
|
|
||||||
// executeFileOperation separately in mock-agent.ts. Not echoing
|
|
||||||
// here prevents the sync client's remote-delete writes from
|
|
||||||
// triggering spurious local-delete sync operations.
|
|
||||||
this.files.delete(path);
|
this.files.delete(path);
|
||||||
|
this.executeFileOperation(
|
||||||
|
async () => this.client.syncLocallyDeletedFile(path),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async rename(
|
public override async rename(
|
||||||
oldPath: RelativePath,
|
oldPath: RelativePath,
|
||||||
newPath: RelativePath
|
newPath: RelativePath
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Just perform the filesystem operation. The test agent calls
|
|
||||||
// executeFileOperation separately in mock-agent.ts. Not echoing
|
|
||||||
// here prevents the sync client's ensureClearPath / remote-rename
|
|
||||||
// writes from triggering spurious local-update sync operations.
|
|
||||||
const file = this.files.get(oldPath);
|
const file = this.files.get(oldPath);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
throw new Error(`File ${oldPath} does not exist`);
|
throw new Error(`File ${oldPath} does not exist`);
|
||||||
|
|
@ -120,13 +93,18 @@ export class MockClient extends debugging.InMemoryFileSystem {
|
||||||
if (oldPath !== newPath) {
|
if (oldPath !== newPath) {
|
||||||
this.files.delete(oldPath);
|
this.files.delete(oldPath);
|
||||||
}
|
}
|
||||||
|
this.executeFileOperation(
|
||||||
|
async () => this.client.syncLocallyUpdatedFile({
|
||||||
|
oldPath,
|
||||||
|
relativePath: newPath
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected executeFileOperation(
|
protected executeFileOperation(
|
||||||
callback: () => unknown,
|
callback: () => unknown,
|
||||||
ignoreSlowFileEvents = false
|
|
||||||
): void {
|
): void {
|
||||||
if (this.useSlowFileEvents && !ignoreSlowFileEvents) {
|
if (this.useSlowFileEvents) {
|
||||||
// we aren't the best client and it takes some time to notice changes
|
// we aren't the best client and it takes some time to notice changes
|
||||||
setTimeout(callback, Math.random() * 100);
|
setTimeout(callback, Math.random() * 100);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue