From b224ebc92776427d965ec56ac73fc55d9bd74d05 Mon Sep 17 00:00:00 2001 From: plenarius Date: Mon, 20 Apr 2026 21:55:52 -0400 Subject: [PATCH] feat: add upstream repo polling every 15 minutes --- packages/backend/src/index.ts | 2 ++ packages/backend/src/services/git.service.ts | 33 ++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 4af401c..7482568 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -16,6 +16,7 @@ import githubRouter from "./routes/github.js"; import reposRouter from "./routes/repos.js"; import { attachWebSocket, createTerminalSession } from "./services/terminal.service.js"; import { attachLspWebSocket } from "./services/lsp.service.js"; +import { startUpstreamPolling } from "./services/git.service.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const app = express(); @@ -77,4 +78,5 @@ server.on("upgrade", (request, socket, head) => { const PORT = parseInt(process.env.PORT || "3000", 10); server.listen(PORT, "0.0.0.0", () => { console.log(`Layonara Forge listening on http://0.0.0.0:${PORT}`); + startUpstreamPolling(); }); diff --git a/packages/backend/src/services/git.service.ts b/packages/backend/src/services/git.service.ts index 0a50944..0f3e262 100644 --- a/packages/backend/src/services/git.service.ts +++ b/packages/backend/src/services/git.service.ts @@ -2,6 +2,7 @@ import simpleGit, { SimpleGit } from "simple-git"; import fs from "fs/promises"; import { REPOS, type RepoName } from "../config/repos.js"; import { getRepoPath, readConfig } from "./workspace.service.js"; +import { broadcast } from "./ws.service.js"; function git(repoPath: string): SimpleGit { return simpleGit(repoPath); @@ -174,3 +175,35 @@ export async function listReposWithStatus() { return results; } + +const lastKnownBehind = new Map(); +let pollingInterval: ReturnType | null = null; + +export function startUpstreamPolling(intervalMs: number = 900000): void { + if (pollingInterval) return; + pollingInterval = setInterval(async () => { + for (const repo of REPOS) { + try { + const repoPath = getRepoPath(repo.name); + await fs.access(repoPath); + const behind = await fetchUpstream(repoPath); + const prev = lastKnownBehind.get(repo.name) || 0; + if (behind !== prev) { + lastKnownBehind.set(repo.name, behind); + if (behind > 0) { + broadcast("git", "upstream-update", { repo: repo.name, behind }); + } + } + } catch { + // repo not cloned or fetch failed + } + } + }, intervalMs); +} + +export function stopUpstreamPolling(): void { + if (pollingInterval) { + clearInterval(pollingInterval); + pollingInterval = null; + } +}