Investigate deadlock (#178)
This commit is contained in:
parent
564d4a6c37
commit
7a13cb57ce
7 changed files with 85 additions and 17 deletions
|
|
@ -2,10 +2,13 @@ import { choose } from "../utils/choose";
|
|||
import { v4 as uuidv4 } from "uuid";
|
||||
import { assert } from "../utils/assert";
|
||||
import type { RelativePath, SyncSettings } from "sync-client";
|
||||
import { debugging, Logger, LogLevel } from "sync-client";
|
||||
import { debugging, Logger, LogLevel, utils } from "sync-client";
|
||||
import { MockClient } from "./mock-client";
|
||||
import { sleep } from "../utils/sleep";
|
||||
import type { LogLine } from "sync-client/dist/types/tracing/logger";
|
||||
import type { LogLine } from "sync-client";
|
||||
import { withTimeout } from "../utils/with-timeout";
|
||||
|
||||
const TIMEOUT_MS = 10 * 60 * 1000;
|
||||
|
||||
export class MockAgent extends MockClient {
|
||||
private readonly writtenContents: string[] = [];
|
||||
|
|
@ -134,15 +137,26 @@ export class MockAgent extends MockClient {
|
|||
}
|
||||
|
||||
public async finish(): Promise<void> {
|
||||
await this.client.setSetting("isSyncEnabled", true);
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
await Promise.all(this.pendingActions);
|
||||
await this.client.waitUntilFinished();
|
||||
await withTimeout(
|
||||
(async (): Promise<void> => {
|
||||
await this.client.setSetting("isSyncEnabled", true);
|
||||
await utils.awaitAll(this.pendingActions);
|
||||
await this.client.waitUntilFinished();
|
||||
})(),
|
||||
TIMEOUT_MS,
|
||||
"finish()"
|
||||
);
|
||||
}
|
||||
|
||||
public async destroy(): Promise<void> {
|
||||
await this.client.waitUntilFinished();
|
||||
await this.client.destroy();
|
||||
await withTimeout(
|
||||
(async (): Promise<void> => {
|
||||
await this.client.waitUntilFinished();
|
||||
await this.client.destroy();
|
||||
})(),
|
||||
TIMEOUT_MS,
|
||||
"destroy()"
|
||||
);
|
||||
}
|
||||
|
||||
public assertFileSystemsAreConsistent(otherAgent: MockAgent): void {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { SyncSettings } from "sync-client";
|
||||
import { utils } from "sync-client";
|
||||
import { MockAgent } from "./agent/mock-agent";
|
||||
import { sleep } from "./utils/sleep";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
|
@ -56,14 +57,12 @@ async function runTest({
|
|||
}
|
||||
|
||||
try {
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
await Promise.all(clients.map(async (client) => client.init()));
|
||||
await utils.awaitAll(clients.map(async (client) => client.init()));
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
console.info(`Iteration ${i + 1}/${iterations}`);
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
await Promise.all(clients.map(async (client) => client.act()));
|
||||
await sleep(100);
|
||||
await utils.awaitAll(clients.map(async (client) => client.act()));
|
||||
await sleep(Math.random() * 200);
|
||||
}
|
||||
|
||||
console.info("Stopping agents");
|
||||
|
|
@ -71,6 +70,7 @@ async function runTest({
|
|||
// Each agent can have unpushed changes which might conflict with eachother so each has to resolve the conflicts & push, and
|
||||
for (const client of clients) {
|
||||
try {
|
||||
console.info(`Finishing up ${client.name}`);
|
||||
await client.finish();
|
||||
} catch (err) {
|
||||
if (!slowFileEvents) {
|
||||
|
|
@ -82,6 +82,7 @@ async function runTest({
|
|||
// then we need a second pass to ensure that all agents pull the same state.
|
||||
for (const client of clients) {
|
||||
try {
|
||||
console.info(`Destroying ${client.name}`);
|
||||
await client.destroy();
|
||||
} catch (err) {
|
||||
if (!slowFileEvents) {
|
||||
|
|
|
|||
16
frontend/test-client/src/utils/with-timeout.ts
Normal file
16
frontend/test-client/src/utils/with-timeout.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
export async function withTimeout<T>(
|
||||
promise: Promise<T>,
|
||||
timeoutMs: number,
|
||||
operationName: string
|
||||
): Promise<T> {
|
||||
return Promise.race([
|
||||
promise,
|
||||
new Promise<T>((_, reject) =>
|
||||
setTimeout(() => {
|
||||
reject(
|
||||
new Error(`${operationName} timed out after ${timeoutMs}ms`)
|
||||
);
|
||||
}, timeoutMs)
|
||||
)
|
||||
]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue