remove em dashes

This commit is contained in:
2026-04-09 21:07:28 +04:00
parent 5f20b41e91
commit 79ba63d86b
31 changed files with 154 additions and 154 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
// this cache each poll re-runs a 500-row scan against `monitors` with an array
// predicate, which dominates the api's Postgres traffic at any real fleet size.
//
// The list almost never changes between polls monitor create/edit/delete is at
// The list almost never changes between polls - monitor create/edit/delete is at
// most a few times per hour. So we memoize per-region with a short TTL and bust
// the cache from the monitor mutation handlers so edits are visible instantly.
@@ -54,7 +54,7 @@ export async function getMonitorsForRegion(region: string): Promise<MonitorRow[]
}
// Called by monitor create/patch/delete/toggle handlers. Wipes the entire
// region map fine because (a) entries are tiny, (b) refresh is cheap, and
// region map - fine because (a) entries are tiny, (b) refresh is cheap, and
// (c) we don't know which regions a freshly-edited monitor belongs to without
// reading it back. Simpler than per-region invalidation, identical net effect.
export function invalidateMonitorList(): void {
+7 -7
View File
@@ -9,7 +9,7 @@ import sql from "../db";
// Each periodic pass scans ONLY pings newer than the watermark, then merges
// them into existing rollup rows additively (total = total + new_total, etc.)
// via ON CONFLICT … DO UPDATE. This makes per-pass work proportional to the
// delta of new pings, not the bucket size critical once a single account has
// delta of new pings, not the bucket size - critical once a single account has
// thousands of monitors.
type BucketType = "hourly" | "daily";
@@ -50,7 +50,7 @@ async function rollupSinceWatermark(bucket: BucketType): Promise<number> {
// after `boundary` will be picked up on the next pass.
const boundary = new Date();
// GROUP BY 1,2,4 (ordinals) instead of repeating the date_trunc expression
// GROUP BY 1,2,4 (ordinals) instead of repeating the date_trunc expression -
// when the unit is a $-bound parameter, Postgres won't recognize the two
// expressions as identical and will reject the column. Ordinals are safe.
//
@@ -91,7 +91,7 @@ async function rollupSinceWatermark(bucket: BucketType): Promise<number> {
// One-shot recompute over an arbitrary window, fully overwriting matched rows.
// Used for the startup backfill and the "still empty after backfill" force-run.
// Takes an explicit upper boundary so the caller can capture it BEFORE running
// the recompute and use the same value for the watermark write afterwards
// the recompute and use the same value for the watermark write afterwards -
// any ping with checked_at > boundary is guaranteed to be outside this window
// and will be picked up by the first incremental pass instead. This closes
// the race where a ping ingested between boundary capture and the SELECT
@@ -137,7 +137,7 @@ export async function startRollupJob() {
// Startup backfill. Capture the boundary FIRST, then run the one-shot
// recompute bounded by it. The watermark is then set to the same boundary,
// so any ping with checked_at > boundary is guaranteed to be picked up by
// the first incremental pass never folded in twice and never missed.
// the first incremental pass - never folded in twice and never missed.
try {
const boundary = new Date();
const [h, d] = await Promise.all([
@@ -150,7 +150,7 @@ export async function startRollupJob() {
setWatermark("daily", boundary),
]);
} catch (e) {
console.error("[rollup] backfill FAILED rollup table will be empty until fixed:", e);
console.error("[rollup] backfill FAILED - rollup table will be empty until fixed:", e);
}
// Force-run check: if any bucket type is still empty after the backfill,
@@ -159,7 +159,7 @@ export async function startRollupJob() {
try {
for (const b of ["hourly", "daily"] as BucketType[]) {
if (await rollupIsEmpty(b)) {
console.log(`[rollup] ${b} still empty forcing incremental aggregation`);
console.log(`[rollup] ${b} still empty - forcing incremental aggregation`);
// Reset watermark so the pass picks up everything in retention.
await setWatermark(b, new Date(0));
await rollupSinceWatermark(b);
@@ -170,7 +170,7 @@ export async function startRollupJob() {
}
// Periodic incremental refreshes. Each pass scans only pings newer than the
// last watermark, so the work is proportional to the delta not the bucket
// last watermark, so the work is proportional to the delta - not the bucket
// size. Hourly runs frequently so the current-hour bar appears quickly for
// fresh monitors; daily can run less often.
setInterval(() => { rollupSinceWatermark("hourly").catch((e) => console.warn("[rollup] hourly failed:", e)); }, 30 * 1000); // every 30s
+2 -2
View File
@@ -108,13 +108,13 @@ export const internal = new Elysia({ prefix: "/internal", detail: { hide: true }
const lookaheadMs = Math.min(Number(params.get('lookahead_ms') || 2000), 10000);
// No JOIN, no state lookup. The check schedule for a monitor is purely
// a function of its created_at and interval_s every interval since
// a function of its created_at and interval_s - every interval since
// creation is a tick. We pull all enabled monitors that match this
// region, compute the next tick in JS, and return the ones whose next
// tick falls within the lookahead window.
//
// The monitor list itself is memoized in apps/api/src/cache/monitor-list.ts
// with a 5s TTL runners poll this endpoint roughly once a second per
// with a 5s TTL - runners poll this endpoint roughly once a second per
// region, but the underlying list almost never changes between polls. The
// cache is busted from monitor create/patch/delete/toggle so edits show up
// immediately.
+1 -1
View File
@@ -17,7 +17,7 @@ const MonitorBody = t.Object({
retry_interval_s: t.Optional(t.Number({ minimum: 1, maximum: 600, default: 30, description: "Seconds between retries" })),
resend_interval: t.Optional(t.Number({ minimum: 0, maximum: 1000, default: 0, description: "Re-alert every Nth consecutive down beat. 0 = never resend." })),
cert_alert_days: t.Optional(t.Number({ minimum: 0, maximum: 365, default: 0, description: "Alert when TLS cert is within N days of expiry. 0 disables (default)." })),
query: t.Optional(t.Any({ description: "PingQL query filter conditions for up/down" })),
query: t.Optional(t.Any({ description: "PingQL query - filter conditions for up/down" })),
regions: t.Optional(t.Array(t.String(), { description: "Regions to run checks from. Empty array = all regions." })),
channel_ids: t.Optional(t.Array(t.String(), { description: "Notification channel IDs to attach to this monitor." })),
tags: t.Optional(t.Array(t.String({ pattern: "^[a-z0-9][a-z0-9-]{0,40}$" }), { description: "Lowercase tag slugs for grouping. Replaces the existing tag set." })),
+1 -1
View File
@@ -61,7 +61,7 @@ export const ingest = new Elysia()
// notifications never carry an empty label.
const region = body.region && body.region.length > 0 ? body.region : 'default';
// The monitor lookup and the per-region state lookup are independent
// The monitor lookup and the per-region state lookup are independent -
// the state row's primary key doesn't depend on anything from the monitor
// row. Fire them in parallel to halve the wall-clock cost on the hottest
// path in the system. (Combining them into a JOIN is a wash on a warm
+2 -2
View File
@@ -39,7 +39,7 @@ const StatusPageBody = t.Object({
}))),
});
// Strip @import and expression() from custom CSS basic sanity, not a full
// Strip @import and expression() from custom CSS - basic sanity, not a full
// parser. The CSS still runs in the visitor's browser; this just blocks the
// most common smuggling vectors.
function sanitizeCss(css: string | null | undefined): string | null {
@@ -63,7 +63,7 @@ async function replaceGroupsAndMonitors(
await sql`DELETE FROM status_page_groups WHERE status_page_id = ${pageId}`;
}
// Single bulk INSERT instead of one round-trip per group. The RETURNING set
// comes back in INSERT order, which equals the array order that lets us
// comes back in INSERT order, which equals the array order - that lets us
// map index → id without a follow-up SELECT. Mirrors the bulk insert pattern
// used by the monitors block right below.
const groupIds: string[] = [];
+3 -3
View File
@@ -21,7 +21,7 @@ function isPrivateIP(ip: string): boolean {
if (second >= 16 && second <= 31) return true;
}
// IPv6 normalize: strip zone ID (%eth0) and lowercase
// IPv6 - normalize: strip zone ID (%eth0) and lowercase
const ip6 = ip.replace(/%.*$/, "").toLowerCase();
if (ip6 === "::1" || ip6 === "::") return true;
if (ip6.startsWith("fe80")) return true; // fe80::/10 link-local
@@ -29,7 +29,7 @@ function isPrivateIP(ip: string): boolean {
if (ip6.startsWith("fd00:ec2::")) return true; // AWS EC2 metadata IPv6
if (ip6 === "::ffff:127.0.0.1") return true;
if (ip6.startsWith("::ffff:")) {
// IPv4-mapped IPv6 extract the IPv4 part and re-check
// IPv4-mapped IPv6 - extract the IPv4 part and re-check
const v4 = ip6.slice(7);
return isPrivateIP(v4);
}
@@ -55,7 +55,7 @@ export async function validateMonitorUrl(url: string): Promise<string | null> {
}
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
return `Blocked scheme: ${parsed.protocol} only http: and https: are allowed`;
return `Blocked scheme: ${parsed.protocol} - only http: and https: are allowed`;
}
const hostname = parsed.hostname.toLowerCase();