Skip to content

Commit 1f70466

Browse files
committed
feat(insights): harden deterministic investigations
1 parent 32578c5 commit 1f70466

57 files changed

Lines changed: 7018 additions & 1081 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ BULLMQ_REDIS_URL="redis://localhost:6379"
99
INSIGHTS_PORT="4002"
1010
INSIGHTS_BULLMQ_REDIS_URL=""
1111
INSIGHTS_DISPATCH_INTERVAL_MS="300000"
12+
INSIGHTS_SCHEDULED_DISPATCH_ENABLED="false"
13+
# Comma-separated organization IDs for canaries; use * only after rollout.
14+
INSIGHTS_SCHEDULED_ORGANIZATION_IDS=""
1215
INSIGHTS_MAINTENANCE_INTERVAL_MS="300000"
1316
INSIGHTS_STALE_ITEM_MS="900000"
1417
INSIGHTS_WORKER_CONCURRENCY="2"

apps/dashboard/app/(main)/insights/hooks/use-insights-local-state.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,9 @@ export function useInsightsLocalState(
9393

9494
const setFeedbackAction = useCallback(
9595
(insightId: string, vote: "up" | "down" | null) => {
96-
if (!organizationId) {
97-
return;
98-
}
9996
setVoteMutation.mutate({ insightId, vote });
10097
},
101-
[organizationId, setVoteMutation]
98+
[setVoteMutation]
10299
);
103100

104101
const feedbackById = votesQuery.data?.votes ?? {};

apps/insights/src/delivery.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,41 @@ describe("Slack finding blocks", () => {
9191
);
9292
});
9393

94+
it("honors Retry-After values longer than five seconds", async () => {
95+
const responses = [
96+
new Response("rate limited", {
97+
headers: { "Retry-After": "120" },
98+
status: 429,
99+
}),
100+
Response.json({ ok: true, ts: "123.456" }),
101+
];
102+
const delays: number[] = [];
103+
const fetcher = (async () => {
104+
const response = responses.shift();
105+
if (!response) {
106+
throw new Error("Unexpected Slack request");
107+
}
108+
return response;
109+
}) as typeof fetch;
110+
111+
await postToSlack(
112+
"token",
113+
"channel-test",
114+
[{ type: "divider" }],
115+
"Finding",
116+
"effect-test",
117+
{
118+
fetcher,
119+
random: () => 0,
120+
sleep: async (milliseconds) => {
121+
delays.push(milliseconds);
122+
},
123+
}
124+
);
125+
126+
expect(delays).toEqual([120_000]);
127+
});
128+
94129
it("uses the durable effect ID as Slack's client message ID", () => {
95130
expect(
96131
buildSlackPostPayload(

apps/insights/src/delivery.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const SLACK_POST_URL = "https://slack.com/api/chat.postMessage";
1515
const SLACK_POST_TIMEOUT_MS = 10_000;
1616
const SLACK_RATE_LIMIT_ATTEMPTS = 3;
1717
const SLACK_RATE_LIMIT_FALLBACK_MS = 1000;
18-
const SLACK_RATE_LIMIT_MAX_WAIT_MS = 5000;
1918
const MAX_DIGEST_INSIGHTS = 3;
2019
const MAX_ONGOING_LINES = 5;
2120
const SLACK_HEADER_MAX = 150;
@@ -436,10 +435,7 @@ function rateLimitDelay(response: Response, random: () => number): number {
436435
Number.isFinite(seconds) && seconds > 0
437436
? seconds * 1000
438437
: SLACK_RATE_LIMIT_FALLBACK_MS;
439-
return (
440-
Math.min(requested, SLACK_RATE_LIMIT_MAX_WAIT_MS) +
441-
Math.floor(random() * 250)
442-
);
438+
return requested + Math.floor(random() * 250);
443439
}
444440

445441
export async function postToSlack(

0 commit comments

Comments
 (0)