Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
90f9b53
fix(ingest): make Vector delivery durable
izadoesdev Jul 31, 2026
00c664c
fix(uptime): durably relay checks through BullMQ
izadoesdev Jul 31, 2026
42ff5df
fix(analytics): deduplicate replayed uptime checks
izadoesdev Jul 31, 2026
cc1febc
fix(basket): durably admit core analytics events
izadoesdev Jul 31, 2026
ecbe223
fix(basket): prevent concurrent event delivery
izadoesdev Jul 31, 2026
70d4515
test(links): isolate logging mocks
izadoesdev Jul 31, 2026
c64d70d
test(ai): avoid stale Redis barrel mocks
izadoesdev Aug 1, 2026
53f4606
fix(basket): preserve retryable analytics delivery
izadoesdev Aug 1, 2026
0484991
refactor(basket): remove ephemeral delivery buffer
izadoesdev Aug 1, 2026
d0e88bd
fix(uptime): refresh durable scheduler jobs
izadoesdev Aug 1, 2026
9cb4cc7
chore(ingest): remove dead Vector sinks
izadoesdev Aug 1, 2026
f162c30
fix(basket): honor legacy delivery deduplication
izadoesdev Aug 1, 2026
9724ec3
fix(tracker): verify analytics delivery outcomes
izadoesdev Aug 1, 2026
b83be11
fix(uptime): validate durable delivery payloads
izadoesdev Aug 1, 2026
0610042
fix(basket): retry legacy dedup reservations
izadoesdev Aug 1, 2026
b8c7bba
fix(uptime): validate durable job envelopes
izadoesdev Aug 1, 2026
69ac91f
fix(uptime): preserve durable job metadata
izadoesdev Aug 1, 2026
5c3b505
refactor(analytics): derive uptime replay identity
izadoesdev Aug 1, 2026
6e47ee6
test(ai): isolate Redis barrel mocks
izadoesdev Aug 1, 2026
ae193fd
style(uptime): format job validation
izadoesdev Aug 1, 2026
6d9bb85
refactor(basket): simplify acknowledged delivery
izadoesdev Aug 1, 2026
4df2431
refactor(uptime): simplify durable delivery
izadoesdev Aug 1, 2026
16588fa
refactor(ingest): remove redundant Vector defaults
izadoesdev Aug 1, 2026
44ac677
refactor(tracker): remove redundant delivery paths
izadoesdev Aug 1, 2026
844f2ec
refactor(analytics): consolidate uptime replay queries
izadoesdev Aug 1, 2026
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
2 changes: 2 additions & 0 deletions .agents/skills/databuddy-internal/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ Keep additions **minimal**: one bullet, a new `rg` hint, or a routing note—eno
- Slack-reachable shared packages (`@databuddy/ai`, `@databuddy/rpc`) must not import `evlog/elysia`; use host-injected request logger providers from the API and plain evlog fallbacks elsewhere.
- AI link tools must assign link folders by existing folder `id` or `slug` only; folder names are display text and must not be used for routing or dedupe.
- `apps/basket`: ingest and LLM tracking service, Elysia app on port `4000`
- A legacy Basket dedupe value of `"1"` is an admission reservation, not delivery confirmation; claim or retry it rather than suppressing the event.
- `apps/docs`: Next.js + Fumadocs docs app on port `3005`
- When a user drops a prototype, remove only prototype-specific wiring and preserve the existing product surfaces it temporarily reused.
- `apps/links`: redirect/link service
- `apps/links` tests share Bun `mock.module` state; mocks of `../lib/logging` must include every export used by later test files, including `setAttributes` for producer imports.
- `apps/uptime`: uptime monitoring service
- `apps/uptime` BullMQ worker concurrency defaults high for Bun async I/O; do not lower it just because `10_000` looks large. Verify downstream saturation or lock/timeout evidence first.
- Public status pages render from `apps/status`; `apps/dashboard` owns status-page management/config UI only. When cleaning public status UX, update shared `@databuddy/ui/uptime` pieces or `apps/status` wrappers instead of redesigning dashboard-only route remnants.
Expand Down
1 change: 0 additions & 1 deletion apps/basket/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"@maxmind/geoip2-node": "^6.3.4",
"@types/ua-parser-js": "^0.7.39",
"async-mutex": "^0.5.0",
"effect": "^4.0.0-beta.90",
"elysia": "catalog:",
"evlog": "catalog:",
"kafkajs": "^2.2.4",
Expand Down
23 changes: 19 additions & 4 deletions apps/basket/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { shutdownPostgres } from "@databuddy/db";
import { clickHouse } from "@databuddy/db/clickhouse";
import { getRedisCache } from "@databuddy/redis/redis";
import { disconnect, disposeRuntime, runPromise } from "@lib/producer";
import { disconnect, ShutdownDrainError } from "@lib/producer";
import { Kafka } from "kafkajs";
import { databuddyEvlogRedaction } from "@databuddy/shared/evlog-redaction";
import {
Expand Down Expand Up @@ -79,13 +79,28 @@ async function gracefulShutdown(signal: string, exitCode = 0) {
error_message: error instanceof Error ? error.message : String(error),
});
const { shutdownRedis } = await import("@databuddy/redis");
// Wait for acknowledged delivery before tearing down its dependencies.
try {
await disconnect();
} catch (error) {
finalExitCode = 1;
if (error instanceof ShutdownDrainError) {
log.error({
lifecycle: "producerDrain",
error_message:
"Basket producer drain timed out waiting for in-flight delivery",
in_flight: error.inFlight,
drain_timeout_ms: error.deadlineMs,
});
} else {
logErr("producerDrain")(error);
}
}
await Promise.all([
shutdownRedis().catch(logErr("redisShutdown")),
shutdownPostgres().catch(logErr("postgresShutdown")),
flushBatchedAxiomDrain().catch(logErr("drainFlush")),
runPromise(disconnect).catch(logErr("shutdown")),
disposeRuntime().catch(logErr("runtimeDispose")),
]);
await flushBatchedAxiomDrain().catch(logErr("drainFlush"));
closeGeoIPReader();
} catch (error) {
finalExitCode = 1;
Expand Down
Loading
Loading