mirror of
https://github.com/zkldi/Tachi.git
synced 2026-09-30 02:48:01 +03:00
Zk/patches (#1700)
* fix: assorted fixes * fix: FOURTH patch on the cron task viewer * fix: remove the import viewer from the global viewer * fix: add git to the server dockerfile
This commit is contained in:
@@ -43,7 +43,8 @@ ENV MIGRATIONS_DIR=/app/db/migrations
|
||||
ENV PORT=8080
|
||||
|
||||
# curl is only needed by the API healthcheck below; workers don't use it.
|
||||
RUN apk add --no-cache curl
|
||||
# git is needed by cron tasks that clone the seeds repo (BMS table sync, backsync, etc.).
|
||||
RUN apk add --no-cache curl git
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app .
|
||||
|
||||
@@ -11,7 +11,6 @@ import GoalLink from "#components/util/GoalLink";
|
||||
import LinkButton from "#components/util/LinkButton";
|
||||
import Loading from "#components/util/Loading";
|
||||
import useApiQuery from "#components/util/query/useApiQuery";
|
||||
import WorkerVisualizer from "#components/workers/WorkerVisualizer";
|
||||
import { UserContext } from "#context/UserContext";
|
||||
import { UserSettingsContext } from "#context/UserSettingsContext";
|
||||
import { WindowContext } from "#context/WindowContext";
|
||||
@@ -72,8 +71,6 @@ function DashboardLoggedIn({ user }: { user: UserDocument }) {
|
||||
<UserGameProfiles />
|
||||
</Route>
|
||||
<Route exact path="/global-activity">
|
||||
<WorkerVisualizer />
|
||||
<hr />
|
||||
<Activity url="/ublock-blocks-this" />
|
||||
</Route>
|
||||
</Switch>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import DB from "#services/pg/db";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
|
||||
import { GetCronTaskExecutions } from "./admin-queries";
|
||||
|
||||
const TEST_CHATTY_TASK = "test-cron-chatty-task";
|
||||
const TEST_DAILY_TASK = "test-cron-daily-task";
|
||||
|
||||
async function cleanupTestExecutions() {
|
||||
await DB.deleteFrom("cron_task_execution")
|
||||
.where("task_id", "in", [TEST_CHATTY_TASK, TEST_DAILY_TASK])
|
||||
.execute();
|
||||
}
|
||||
|
||||
describe("GetCronTaskExecutions", () => {
|
||||
afterEach(cleanupTestExecutions);
|
||||
|
||||
it("caps results per task so a high-frequency task cannot crowd out other tasks", async () => {
|
||||
const now = Date.now();
|
||||
const isoAt = (offsetMs: number) => new Date(now - offsetMs).toISOString();
|
||||
|
||||
// Insert 25 executions for a chatty minutely task — exceeds the 20-per-task cap.
|
||||
const chattyValues = Array.from({ length: 25 }, (_, i) => ({
|
||||
task_id: TEST_CHATTY_TASK,
|
||||
scheduled_at: isoAt(i * 60_000),
|
||||
status: "success" as const,
|
||||
completed_at: isoAt(i * 60_000 - 1_000),
|
||||
output: null,
|
||||
error: null,
|
||||
}));
|
||||
|
||||
// Insert 3 executions for a daily task. These must not be crowded out.
|
||||
const dailyValues = Array.from({ length: 3 }, (_, i) => ({
|
||||
task_id: TEST_DAILY_TASK,
|
||||
scheduled_at: isoAt(i * 24 * 60 * 60_000),
|
||||
status: "success" as const,
|
||||
completed_at: isoAt(i * 24 * 60 * 60_000 - 1_000),
|
||||
output: null,
|
||||
error: null,
|
||||
}));
|
||||
|
||||
await DB.insertInto("cron_task_execution")
|
||||
.values([...chattyValues, ...dailyValues])
|
||||
.execute();
|
||||
|
||||
const results = await GetCronTaskExecutions();
|
||||
|
||||
const chatty = results.filter((r) => r.task_id === TEST_CHATTY_TASK);
|
||||
const daily = results.filter((r) => r.task_id === TEST_DAILY_TASK);
|
||||
|
||||
expect(chatty).toHaveLength(20);
|
||||
expect(daily).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,9 @@
|
||||
import type { Action, CronTask, CronTaskExecution, JobQueue } from "tachi-db";
|
||||
|
||||
import { ONE_HOUR } from "#lib/constants/time";
|
||||
import {
|
||||
SELECT_CRON_TASK,
|
||||
SELECT_CRON_TASK_EXECUTION,
|
||||
SELECT_JOB_QUEUE,
|
||||
} from "#lib/db-formats/admin-jobs";
|
||||
import { SELECT_CRON_TASK, SELECT_JOB_QUEUE } from "#lib/db-formats/admin-jobs";
|
||||
import DB from "#services/pg/db";
|
||||
import { sql } from "kysely";
|
||||
|
||||
export const ADMIN_PAGE_SIZE = 50;
|
||||
|
||||
@@ -161,11 +158,22 @@ export function GetCronTasks(): Promise<Array<CronTask>> {
|
||||
.execute();
|
||||
}
|
||||
|
||||
export function GetCronTaskExecutions(): Promise<Array<CronTaskExecution>> {
|
||||
return DB.selectFrom("cron_task_execution")
|
||||
.select(SELECT_CRON_TASK_EXECUTION)
|
||||
.where("cron_task_execution.scheduled_at", ">=", adminRecentSinceIso(24 * 7))
|
||||
.orderBy("cron_task_execution.scheduled_at", "desc")
|
||||
.limit(100)
|
||||
.execute();
|
||||
/** Most recent executions per task, capped at 20 per task_id to prevent high-frequency tasks from crowding out others. */
|
||||
export async function GetCronTaskExecutions(): Promise<Array<CronTaskExecution>> {
|
||||
const since = adminRecentSinceIso(24 * 7);
|
||||
|
||||
const rows = await sql<CronTaskExecution>`
|
||||
SELECT id, task_id, scheduled_at, started_at, completed_at, status, output, error
|
||||
FROM (
|
||||
SELECT
|
||||
id, task_id, scheduled_at, started_at, completed_at, status, output, error,
|
||||
ROW_NUMBER() OVER (PARTITION BY task_id ORDER BY scheduled_at DESC) AS rn
|
||||
FROM cron_task_execution
|
||||
WHERE scheduled_at >= ${since}
|
||||
) ranked
|
||||
WHERE rn <= 20
|
||||
ORDER BY scheduled_at DESC
|
||||
`.execute(DB);
|
||||
|
||||
return rows.rows;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user