Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 86 additions & 1 deletion apps/server/src/git/Layers/GitCore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import path from "node:path";

import * as NodeServices from "@effect/platform-node/NodeServices";
import { it } from "@effect/vitest";
import { Effect, FileSystem, Layer, PlatformError, Scope } from "effect";
import { Effect, Fiber, FileSystem, Layer, PlatformError, Scope } from "effect";
import { describe, expect, vi } from "vitest";

import { GitCoreLive, makeGitCore } from "./GitCore.ts";
Expand Down Expand Up @@ -1610,6 +1610,91 @@ it.layer(TestLayer)("git integration", (it) => {
}),
);

it.effect("uses an extended timeout for status upstream refresh fetches", () =>
Effect.gen(function* () {
const remote = yield* makeTmpDir();
const source = yield* makeTmpDir();
yield* git(remote, ["init", "--bare"]);

const { initialBranch } = yield* initRepoWithCommit(source);
yield* git(source, ["remote", "add", "origin", remote]);
yield* git(source, ["push", "-u", "origin", initialBranch]);

const realGitCore = yield* GitCore;
let statusRefreshTimeoutMs: number | undefined;
const core = yield* makeIsolatedGitCore((input) => {
if (input.operation === "GitCore.fetchUpstreamRefForStatus") {
statusRefreshTimeoutMs = input.timeoutMs;
return Effect.succeed({ code: 0, stdout: "", stderr: "" });
}
return realGitCore.execute(input);
});

const details = yield* core.statusDetails(source);

expect(details.branch).toBe(initialBranch);
expect(statusRefreshTimeoutMs).toBe(300_000);
}),
);

it.effect("deduplicates in-flight status upstream refresh fetches", () =>
Effect.gen(function* () {
const remote = yield* makeTmpDir();
const source = yield* makeTmpDir();
yield* git(remote, ["init", "--bare"]);

const { initialBranch } = yield* initRepoWithCommit(source);
yield* git(source, ["remote", "add", "origin", remote]);
yield* git(source, ["push", "-u", "origin", initialBranch]);

const realGitCore = yield* GitCore;
let refreshFetchAttempts = 0;
let releaseFetch!: () => void;
const waitForReleasePromise = new Promise<void>((resolve) => {
releaseFetch = resolve;
});
const core = yield* makeIsolatedGitCore((input) => {
if (input.operation === "GitCore.fetchUpstreamRefForStatus") {
refreshFetchAttempts += 1;
return Effect.promise(() =>
waitForReleasePromise.then(() => ({ code: 0, stdout: "", stderr: "" })),
);
}
if (input.operation === "GitCore.statusDetails.status") {
return Effect.succeed({
code: 0,
stdout: `# branch.head ${initialBranch}\n# branch.upstream origin/${initialBranch}\n# branch.ab +0 -0\n`,
stderr: "",
});
}
if (
input.operation === "GitCore.statusDetails.unstagedNumstat" ||
input.operation === "GitCore.statusDetails.stagedNumstat"
) {
return Effect.succeed({ code: 0, stdout: "", stderr: "" });
}
return realGitCore.execute(input);
});

const statusFiber = yield* Effect.forkScoped(
Effect.all([core.statusDetails(source), core.statusDetails(source)], {
concurrency: "unbounded",
}),
);

yield* Effect.promise(() =>
vi.waitFor(() => {
expect(refreshFetchAttempts).toBe(1);
}),
);

releaseFetch();
const [first, second] = yield* Fiber.join(statusFiber);
expect(first.branch).toBe(initialBranch);
expect(second.branch).toBe(initialBranch);
}),
);

it.effect("prepares commit context by auto-staging and creates commit", () =>
Effect.gen(function* () {
const tmp = yield* makeTmpDir();
Expand Down
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/GitCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { decodeJsonResult } from "@t3tools/shared/schemaJson";
const DEFAULT_TIMEOUT_MS = 30_000;
const DEFAULT_MAX_OUTPUT_BYTES = 1_000_000;
const STATUS_UPSTREAM_REFRESH_INTERVAL = Duration.seconds(15);
const STATUS_UPSTREAM_REFRESH_TIMEOUT = Duration.seconds(5);
const STATUS_UPSTREAM_REFRESH_TIMEOUT = Duration.minutes(5);
Comment thread
ifBars marked this conversation as resolved.
const STATUS_UPSTREAM_REFRESH_CACHE_CAPACITY = 2_048;
const DEFAULT_BASE_BRANCH_CANDIDATES = ["main", "master"] as const;

Expand Down