fix(observability,webhooks,i18n): timestamped logs, dedupe webhook retries, default non-de locales to English

- New custom server.js (replaces react-router-serve): ISO timestamps on
  all console.* output and on access logs, and skip successful /healthz
  polls so real traffic stays visible.
- New ProcessedWebhook table + dedupe helper keyed on
  X-Shopify-Webhook-Id; stops Shopify retries from triggering a second
  invoice email when the original delivery exceeded the 5s ack timeout.
- orders/create + orders/fulfilled now respond 200 immediately and run
  the PDF/email work in the background so we stay under that timeout.
- pickLanguage(): non-German locales (it, fr, es, ...) now default to
  English instead of falling back to German. Empty/unknown still maps to
  'de' so the per-shop defaultLanguage chain keeps working.
- Tests for pickLanguage and dedupe via node --test + tsx.
This commit is contained in:
Gerhard Scheikl
2026-05-15 11:02:17 +02:00
parent 274ccfbc01
commit dde53319e5
12 changed files with 361 additions and 29 deletions
+11
View File
@@ -182,6 +182,17 @@ model EmailLog {
@@index([shopDomain, invoiceId])
}
// Idempotency table for inbound Shopify webhooks. See
// `app/services/webhooks/dedupe.server.ts` for details.
model ProcessedWebhook {
webhookId String @id
topic String
shopDomain String
receivedAt DateTime @default(now())
@@index([shopDomain, topic])
}
// Per-shop logo bytes cache. Avoids fetching the logo from Shopify Files on
// every PDF render.
model LogoCache {