Skip to content

Hot fix#376

Merged
ViktorSvertoka merged 12 commits intomainfrom
develop
Feb 27, 2026
Merged

Hot fix#376
ViktorSvertoka merged 12 commits intomainfrom
develop

Conversation

@ViktorSvertoka
Copy link
Member

@ViktorSvertoka ViktorSvertoka commented Feb 27, 2026

Summary by CodeRabbit

  • New Features

    • Added optimized lite order status endpoint for faster checkout status queries.
    • Implemented intelligent backoff and retry logic for order status polling.
    • Added activity tracking throttling to reduce unnecessary API calls.
  • Bug Fixes

    • Improved order status payload parsing with pre-validation logic.
    • Enhanced order status update semantics with configurable polling intervals.
  • Refactor

    • Optimized order checkout transaction handling.
    • Refactored payment webhook logic for improved reliability.
    • Implemented shipping interval flooring for consistent job scheduling.
  • Chores

    • Adjusted background workflow scheduling intervals.
    • Added database indexes to improve order query performance.
    • Extracted test helpers for improved test maintainability.

liudmylasovetovs and others added 12 commits February 25, 2026 08:41
…tics cleanup (#367)

* perf(vercel): cut runtime costs via notification, blog cache, and analytics changes

* perf(blog): remove server searchParams usage to preserve ISR
… to client-side (#370)

* refactor(frontend): remove locale layout dynamic auth and move header auth client-side

* fix(frontend): prevent stale auth responses in useAuth and remove redundant dashboard dynamic layout
…abs (#372)

* refactor(frontend): remove locale layout dynamic auth and move header auth client-side

* fix(frontend): prevent stale auth responses in useAuth and remove redundant dashboard dynamic layout

* feat(frontend): sync auth state across tabs via BroadcastChannel
…tars cache (#371)

* perf(quiz-flow): move quiz progress to client-side fetch, enable ISR for quizzes page

- Move user progress fetch from SSR to client-side API (/api/quiz/progress)
- Remove force-dynamic and getCurrentUser() from quizzes page
- Add revalidate=300 for ISR caching
- Use window.history.replaceState for tab URL sync (avoid Next.js navigation)
- Add forceMount to TabsContent to prevent layout shift on tab switch
- Fix nested <main> — use <section> inside DynamicGridBackground
- Cache GitHub stars count in sessionStorage to avoid refetch + re-animation

* perf: replace useRef with useState lazy initializer in GitHubStarButton

Fixes React 19 react-hooks/refs ESLint error — useRef.current cannot
be read during render. Uses useState(getStoredStars) to capture the
sessionStorage value once on mount instead.

* fix: stop star icon trembling on hover in GitHubStarButton
…zes page (#373)

* perf(quiz-flow): move quiz progress to client-side fetch, enable ISR for quizzes page

- Move user progress fetch from SSR to client-side API (/api/quiz/progress)
- Remove force-dynamic and getCurrentUser() from quizzes page
- Add revalidate=300 for ISR caching
- Use window.history.replaceState for tab URL sync (avoid Next.js navigation)
- Add forceMount to TabsContent to prevent layout shift on tab switch
- Fix nested <main> — use <section> inside DynamicGridBackground
- Cache GitHub stars count in sessionStorage to avoid refetch + re-animation

* perf: replace useRef with useState lazy initializer in GitHubStarButton

Fixes React 19 react-hooks/refs ESLint error — useRef.current cannot
be read during render. Uses useState(getStoredStars) to capture the
sessionStorage value once on mount instead.

* fix: stop star icon trembling on hover in GitHubStarButton

* fix: eliminate quiz timer flash on language switch

Remove Suspense boundary (loading.tsx) that unmounted QuizContainer
during locale navigation. Synchronous session restore via useReducer
lazy initializer and correct timer initialization via useState lazy
initializer prevent any visible state reset on language switch

* fix: replace quiz card layout shift with skeleton grid during progress load
…out polling + add sweep indexes (#375)

* (SP: 3) [Backend] add internal janitor (jobs 1-4), claim/lease + runbook (G0-G6)

* (SP: 3) [Backend] add provider selector, fix payments gating, i18n checkout errors

* Add shop category images to public

* (SP: 3) [Shop][Monobank] I1 structured logging: codes + logging safety checks

* (SP: 3) [Shop][Monobank] Fail-closed non-browser origin posture for webhook + janitor (ORIGIN_BLOCKED)

* (SP: 3) [Shop][Monobank] [Shop][Monobank] J gate: add orders status ownership test and pass all pre-prod invariants

* (SP: 3) [Shop][Monobank]  review fixes (tests, logging, success UI)

* (SP: 1) [Shop][Monobank] Tighten webhook log-code typing; harden DB tests; minor security/log/UI cleanups

* (SP: 1) [Shop][Monobank] harden Monobank webhook (origin/PII-safe logs) and remove duplicate sha256 hashing

* (SP: 1) [Cart] adding route for user orders to cart page

* (SP: 1) [Cart] fix after review cart mpage and adding index for orders

* (SP: 1) [Cart] Fix cart orders summary auth rendering and return totalCount for orders badge

* (SP: 1) [Cart] remove console.warn from CartPageClient to satisfy monobank logging safety invariant, namespace localStorage cart by user and reset on auth change

* (SP: 1) [Cart] rehydrate per cartOwnerId (remove didHydrate coupling)

* (SP: 2)[Backend] shop/shipping schema migrations foundation

* (SP: 2)[Backend] shop/shipping public routes + np cache + sync

* (SP: 2)[Backend] shop/shipping: shipping persistence + currency policy

* (SP: 2)[Backend] shop/shipping: webhook apply + psp fields + enqueue shipping

* (SP: 2)[Backend] shop/shipping: shipments worker + internal run + np mock

* (SP: 2)[Backend] shop/shipping: admin+ui shipping actions

* (SP: 2)[Backend] shop/shipping: retention + log sanitizer + metrics

* (SP: 1)[Backend] stabilize Monobank janitor (job1/job3) and fix failing apply-outcomes tests

* (SP: 1) [db]: add shop shipping core migration

* (SP: 1) [FIX] resolve merge artifacts in order details page

* (SP: 1) [FIX] apply post-review fixes for shipping and admin flows

* (SP: 1) [FIX] align cart shipping imports (localeToCountry + availability reason code)

* (SP: 1) [FIX] hard-block checkout when shipping disabled + i18n reason mapping

* (SP: 1) [FIX] harden webhook enqueue + shipping worker + NP catalog + cart fail-closed

* (SP: 1) [FIX] Initialize shippingMethodsLoading to true to avoid premature checkout.

* (SP: 1) [FIX] migration 17

* (SP: 1) [DB] migrarion to testind DB and adjusting tests

* (SP: 1)[DB] slow down restock janitor + enforce prod interval floor

* (SP: 1) [DB] add order status lite view (opt-in) + instrumentation

* (SP: 1) [DB] replace checkout success router.refresh polling with backoff API polling

* (SP: 1) [DB] throttle sessions activity heartbeat + use count(*) (PK invariant)

* (SP: 1)[DB] enforce production min intervals for internal shipping jobs

* (SP: 1) [DB] add minimal partial indexes for orders sweeps + rollout notes

* (SP: 1) [DB] refactor sweep claim step to FOR UPDATE SKIP LOCKED batching

* (SP: 1)[DB]: slow janitor schedule to every 30 minutes

* (SP: 1)[DB] increase polling delays for MonobankRedirectStatus

* (SP: 1)[FIX] harden webhooks + fix SSR hydration + janitor/np gates + sweeps refactor

* (SP: 1)[FIX] harden shipping enqueue gating + apply NP interval floor
@vercel
Copy link
Contributor

vercel bot commented Feb 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
devlovers-net Ignored Ignored Feb 27, 2026 6:45pm

Request Review

@ViktorSvertoka ViktorSvertoka merged commit 2bafe82 into main Feb 27, 2026
10 of 11 checks passed
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa74add and ffca8ca.

📒 Files selected for processing (27)
  • .github/workflows/shop-janitor-restock-stale.yml
  • frontend/app/[locale]/shop/checkout/success/MonobankRedirectStatus.tsx
  • frontend/app/[locale]/shop/checkout/success/OrderStatusAutoRefresh.tsx
  • frontend/app/api/sessions/activity/route.ts
  • frontend/app/api/shop/internal/orders/restock-stale/route.ts
  • frontend/app/api/shop/internal/shipping/np/sync/route.ts
  • frontend/app/api/shop/internal/shipping/retention/run/route.ts
  • frontend/app/api/shop/internal/shipping/shipments/run/route.ts
  • frontend/app/api/shop/orders/[id]/status/route.ts
  • frontend/app/api/shop/webhooks/stripe/route.ts
  • frontend/components/shared/OnlineCounterPopup.tsx
  • frontend/drizzle/0020_shop_orders_sweeps_partial_indexes.sql
  • frontend/drizzle/meta/0020_snapshot.json
  • frontend/drizzle/meta/_journal.json
  • frontend/lib/services/orders/checkout.ts
  • frontend/lib/services/orders/monobank-webhook.ts
  • frontend/lib/services/orders/summary.ts
  • frontend/lib/services/orders/sweeps.ts
  • frontend/lib/services/shop/shipping/inventory-eligibility.ts
  • frontend/lib/tests/helpers/seed-product.ts
  • frontend/lib/tests/shop/checkout-monobank-idempotency-contract.test.ts
  • frontend/lib/tests/shop/checkout-no-payments.test.ts
  • frontend/lib/tests/shop/monobank-events-claim.test.ts
  • frontend/lib/tests/shop/monobank-payments-disabled.test.ts
  • frontend/lib/tests/shop/monobank-webhook-apply.test.ts
  • frontend/lib/tests/shop/shipping-checkout-payload-phase6.test.ts
  • frontend/lib/validation/shop-shipping.ts

📝 Walkthrough

Walkthrough

This pull request introduces performance optimizations, new lite-mode order status features, refactored atomic webhook operations, improved batch sweep processing, and test infrastructure improvements across frontend APIs, services, and components.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/shop-janitor-restock-stale.yml
Updated scheduled trigger from 5-minute to 30-minute interval for the janitor restock task.
Order Status Polling & Refresh
frontend/app/[locale]/shop/checkout/success/MonobankRedirectStatus.tsx, frontend/app/[locale]/shop/checkout/success/OrderStatusAutoRefresh.tsx
Enhanced polling timeouts and delays; replaced interval-based polling with bounded async backoff loop featuring MAX_ATTEMPTS, MAX_DURATION_MS, jitter, and per-attempt abort handling. Reduced component API surface from accepting maxMs/intervalMs to only paymentStatus. Added helper functions for backoff calculation and error code extraction.
Lite Order Status Endpoint
frontend/app/api/shop/orders/[id]/status/route.ts, frontend/lib/services/orders/summary.ts
Added new responseMode toggle based on view query parameter; when view=lite, returns lightweight OrderStatusLiteSummary without full order/attempt details. Introduced getOrderStatusLiteSummary helper with fields: id, paymentStatus, totalAmountMinor, currency, itemsCount, updatedAt.
Shipping Job Interval Clamping
frontend/app/api/shop/internal/shipping/np/sync/route.ts, frontend/app/api/shop/internal/shipping/retention/run/route.ts, frontend/app/api/shop/internal/shipping/shipments/run/route.ts, frontend/lib/validation/shop-shipping.ts
Added runtime interval clamping logic with getInternalShippingMinIntervalFloorSeconds helper to enforce production-time minimum floor across multiple shipping endpoints. All routes now log wasClamped metadata alongside requestedMinIntervalSeconds and effectiveIntervalSeconds.
Restock Job Interval & Metadata
frontend/app/api/shop/internal/orders/restock-stale/route.ts
Increased production fallback interval from 300s to 900s; enhanced GateRow to include updated_at field; improved interval handling with nowTs/lastRunTs logging throughout acquisition and decision paths. API responses now carry timing metadata in both rate-limited and successful paths.
Session Activity Throttling
frontend/app/api/sessions/activity/route.ts
Added HEARTBEAT_THROTTLE_MS environment variable (min 1000ms floor) to gate lastActivity updates; conditional setWhere clause only updates when existing lastActivity exceeds throttle threshold. Changed count query from distinct session_id to count(*).
Stripe Webhook Atomic Enqueue
frontend/app/api/shop/webhooks/stripe/route.ts, frontend/lib/services/orders/monobank-webhook.ts
Refactored atomic shipment enqueue logic with multi-CTE workflows; replaced shouldAttemptEnqueue flag with explicit eligible_for_enqueue query and queued_order_ids tracking. Added on-conflict do-update behavior and post-enqueue fallback path to ensure shipment queuing in edge cases. Monobank webhook introduces ensureQueuedShipmentAndOrderShippingStatus helper and extended return fields (shipment/order metrics).
Order Sweeps Batch Processing
frontend/lib/services/orders/sweeps.ts
Introduced reusable claimOrdersForSweepBatch helper and compactConditions utility to centralize sweep claiming logic. Refactored restock functions to use batch claiming with optional extraSet overrides and per-batch debug logging. Added loopCount tracking for progress reporting.
Order Checkout Transaction Refactoring
frontend/lib/services/orders/checkout.ts
Replaced transactional insert pattern with direct non-transactional insert and compensating cleanup on shipping snapshot failure. Extended idempotency conflict path (23505) with compatibility validation and optional snapshot backfill for existing orders. Improved error handling and state consistency across new and existing-order scenarios.
Online Counter Activity Throttling
frontend/components/shared/OnlineCounterPopup.tsx
Added activity throttling via ACTIVITY_THROTTLE_MS and sessionStorage persistence keys. Component now caches online state, rehydrates on mount without forcing fetch, and skips subsequent requests within throttle window. Wrapped sessionStorage writes with try/catch for resilience.
Database Indexes & Migration
frontend/drizzle/0020_shop_orders_sweeps_partial_indexes.sql, frontend/drizzle/meta/_journal.json
Created two partial indexes on orders table targeting Stripe-pending and no-payment sweep selectors with explicit lock/statement timeouts. Added corresponding journal entry with breakpoints flag.
Shipping Inventory Eligibility
frontend/lib/services/shop/shipping/inventory-eligibility.ts
Simplified SQL generation by replacing manual IN(...) construction with inArray helper from drizzle-orm.
Test Infrastructure & Helpers
frontend/lib/tests/helpers/seed-product.ts, frontend/lib/tests/shop/checkout-monobank-idempotency-contract.test.ts, frontend/lib/tests/shop/checkout-no-payments.test.ts, frontend/lib/tests/shop/monobank-payments-disabled.test.ts, frontend/lib/tests/shop/monobank-events-claim.test.ts, frontend/lib/tests/shop/monobank-webhook-apply.test.ts, frontend/lib/tests/shop/shipping-checkout-payload-phase6.test.ts
Extracted product seeding logic into reusable getOrSeedActiveTemplateProduct and cleanupSeededTemplateProduct helpers with database introspection and enum handling. Updated multiple test files to use new helper and removed redundant in-test seeding code. Refined test cleanup filters and removed unused test assertions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant OrderStatusAutoRefresh
    participant BackoffLoop
    participant Fetch as fetchLiteOrderStatus
    participant API as /api/shop/orders/[id]/status

    Client->>OrderStatusAutoRefresh: Mount with paymentStatus
    OrderStatusAutoRefresh->>OrderStatusAutoRefresh: Extract orderId, statusToken from URL
    OrderStatusAutoRefresh->>BackoffLoop: Start bounded retry loop (MAX_ATTEMPTS, MAX_DURATION_MS)
    
    loop Until terminal status or max attempts/duration
        BackoffLoop->>Fetch: Build request (view=lite, statusToken)
        Fetch->>API: GET /api/shop/orders/[id]/status?view=lite
        API->>API: Parse lite response (paymentStatus)
        API-->>Fetch: OrderStatusLiteSummary or error
        Fetch->>Fetch: Parse paymentStatus, check terminal
        
        alt Terminal status detected
            Fetch->>OrderStatusAutoRefresh: Return paymentStatus
            OrderStatusAutoRefresh->>Client: Trigger router.refresh()
            BackoffLoop-->>OrderStatusAutoRefresh: Break loop
        else Non-terminal, retry
            BackoffLoop->>BackoffLoop: Calculate backoff + jitter
            BackoffLoop->>BackoffLoop: Wait (getBackoffDelayMs with jitter)
        end
        
        alt Error or shouldStopOnError
            Fetch-->>BackoffLoop: Structured error
            BackoffLoop-->>OrderStatusAutoRefresh: Break loop
        end
    end
Loading
sequenceDiagram
    participant StripeWebhook
    participant ApplyStripePaidAtomic as applyStripePaidAndQueueShipmentAtomic
    participant DB
    participant EnsureHelper as ensureQueuedShipmentAndOrderShippingStatus

    StripeWebhook->>ApplyStripePaidAtomic: Invoke with orderId, enqueueShipment flag
    ApplyStripePaidAtomic->>DB: Multi-CTE flow (update_order → update_attempt → eligible_for_enqueue)
    DB->>DB: Insert/update shipping_shipments (queued)
    DB->>ApplyStripePaidAtomic: Return queued_shipment_count, shipmentQueued flag

    alt shipmentQueued is false AND shipping prerequisites met
        StripeWebhook->>EnsureHelper: Invoke ensureQueuedShipment...
        EnsureHelper->>DB: Insert shipping_shipments (if not already queued)
        EnsureHelper->>DB: Update order shipping_status to queued
        DB-->>EnsureHelper: Return insert/update booleans
        EnsureHelper-->>StripeWebhook: shipmentQueued results
    else shipmentQueued is true
        ApplyStripePaidAtomic-->>StripeWebhook: Return with shipmentQueued=true
    end

    StripeWebhook->>StripeWebhook: Compute final shipmentQueued (atomic OR ensure results)
    StripeWebhook->>DB: Record shipping metrics if queued
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • AM1007

Poem

🐰 Hop along with intervals new,
Lite endpoints fetch faster, it's true!
Backoff with jitter, sweeps batch with care,
Orders flow queued in the shipping air!
Throttle and cache, the janitor sleeps,
Thirty-minute hops through data's deep keeps.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants