Skip to content

Feat/backend health rollback bonus scaling 697 698 699 715#851

Merged
Wilfred007 merged 5 commits into
Gildado:mainfrom
xeladev4:feat/backend-health-rollback-bonus-scaling-697-698-699-715
May 29, 2026
Merged

Feat/backend health rollback bonus scaling 697 698 699 715#851
Wilfred007 merged 5 commits into
Gildado:mainfrom
xeladev4:feat/backend-health-rollback-bonus-scaling-697-698-699-715

Conversation

@xeladev4
Copy link
Copy Markdown
Contributor

Pull Request

Summary

Closes #697 , Closes #698 , Closes #699 , Closes #715

Four backend issues addressed in one branch:

What Changed

Chore — Re-sequence migrations (prerequisite)

  • Two existing migration files both had the 040_ prefix, which the migration runner rejects with a fatal duplicate-prefix error.
  • Created rollback files for all previously-untracked migrations (040_api_database_scaling_part27, 041_optimize_transaction_log_indexes, 042_circuit_breaker_part11, 043_V15__scaling_indexes).
  • Ran node scripts/resequence-migrations.mjs (the prescribed fix per CONTRIBUTING.md) to restore unique, contiguous numbering.
  • Added a root-level eslint.config.js (ESLint v10 flat config) so the pre-commit lint-staged hook no longer errors on non-JS staged files.

#697 — Health Check Endpoints

  • Added HealthController.getLiveness() — returns { status: "alive", uptime, timestamp } with no dependency checks; safe for k8s liveness probes that must never block.
  • Added HealthController.getReadiness() — checks PostgreSQL and Redis; returns 200 { status: "ready" } or 503 { status: "not_ready" }.
  • Registered four new routes in app.ts:
    • GET /api/v1/health/live
    • GET /api/v1/health/ready
    • GET /health/live
    • GET /health/ready
  • Added 8 new unit tests covering 200/503 responses, individual dependency failures, and confirmed the liveness probe never queries the DB.

#698 — Database Migration Rollback Strategy

  • Migration 044_migration_rollback_audit.sql — creates migration_rollback_log table: an immutable audit trail of every rollback event (filename, timestamp, user, reason, execution_ms).
  • MigrationStatusService — reads schema_migrations and migration_rollback_log to surface a full status report. Gracefully returns an empty rollback history if the log table does not exist yet (safe for pre-044 databases).
  • MigrationStatusController + migrationStatusRoutes:
    • GET /api/v1/migrations/status — full report: applied, pending (with rollback availability flag), rollback history
    • GET /api/v1/migrations/applied — applied migrations with checksums and timestamps
    • GET /api/v1/migrations/rollbacks — rollback event log, most recent first (?limit= capped at 100)
  • Added 8 unit tests covering all three service methods, including limit clamping and graceful handling of missing table.

#699 — Performance Bonuses in Payroll Engine

  • Migration 045_add_performance_bonus_fields.sql:
    • payroll_items.bonus_type VARCHAR(50)CHECK constrained to ('performance','referral','project','retention','spot','other').
    • payroll_items.performance_score NUMERIC(5,2) — 0–100 range check; NULL for non-performance bonuses.
    • Partial indexes on both columns for efficient filtered queries.
  • PayrollBonusService updates:
    • addBonusItem / addBatchBonusItems — now accept and persist bonus_type and performance_score.
    • listBonusesByType(orgId, bonusType) — filter bonus history by category.
    • getPerformanceBonusesByScore(orgId, minScore) — list performance bonuses above a score threshold, ordered score-descending.
  • PayrollBonusController — two new methods: listBonusesByType, getPerformanceBonuses.
  • payrollBonusRoutes — two new routes:
    • GET /api/v1/payroll-bonus/bonuses/by-type/:bonusType
    • GET /api/v1/payroll-bonus/bonuses/performance?minScore=
  • Added 18 unit tests in payrollBonusService.test.ts covering create, add (with/without new fields), batch insert, transaction rollback on error, listBonusesByType, getPerformanceBonusesByScore, deletePayrollItem.

#715 — API & Database Scaling Part 25

  • Migration 046_api_database_scaling_part25.sql:
    • api_latency_histogram table — stores pre-bucketed latency observations per endpoint/method, with a 30-day auto-prune function.
    • idx_employees_list_covering — covering index on employees(organization_id, status, created_at DESC) INCLUDE (first_name, last_name, email, wallet_address) to avoid heap fetches on the high-traffic employee list query.
    • idx_transactions_list_covering — covering index on transactions(organization_id, status, created_at DESC) INCLUDE (amount, type).
  • scalingRoutes.ts — two new Part 25 endpoints:
    • GET /api/v1/scaling/latency-percentiles — computes p50/p95/p99 per endpoint from api_latency_histogram over a configurable time window (?limit=, ?windowMinutes=).
    • GET /api/v1/scaling/pool-history — time-series snapshots from db_pool_health for connection-pool saturation trend analysis (?limit=).
  • Added 8 integration tests for both endpoints.

Checklist

  • I linked the relevant issue(s) in the summary.
  • I added or updated tests for the change.
  • I ran the relevant test suite locally.
  • I updated documentation where needed, or explained why it was not needed.
  • If this change touches the UI, I verified responsive behavior and accessibility. (N/A — backend only)
  • I included screenshots, logs, or other proof when they help review.

Testing

cd backend

# Unit tests (no live DB required)
npm run test -- src/controllers/__tests__/healthController.test.ts
npm run test -- src/services/__tests__/migrationStatusService.test.ts
npm run test -- src/services/__tests__/payrollBonusService.test.ts

# Scaling routes integration tests (mock DB)
npm run test -- src/__tests__/scalingRoutes.test.ts

# All backend tests
npm run test

For the migration runner dry-run:

cd backend
npm run db:migrate:dry-run

Documentation

  • Migration guide already documents the rollback strategy (backend/src/db/MIGRATION_GUIDE.md); the new migration_rollback_log table extends that infrastructure.
  • Swagger JSDoc annotations added to all new routes.

Accessibility / Responsiveness

N/A — backend API changes only.

Notes

  • Migration checklist (per CONTRIBUTING.md):

    • Migration files named correctly (NNN_short_description.sql)
    • Migration numbers are unique (044, 045, 046)
    • Migrations use IF NOT EXISTS / IF EXISTS for idempotency
    • Matching rollback files created in backend/src/db/rollbacks/
    • No existing migration file was modified
  • The pre-existing duplicate 040_ prefix is fixed as part of this PR via the prescribed resequence-migrations.mjs script. The two affected migration files were already merged to main by previous contributors; this PR adds their missing rollback files before resequencing, as required.

xeladev4 and others added 5 commits May 29, 2026 23:44
Two migration files shared the 040_ prefix (040_api_database_scaling_part27.sql
and 040_optimize_transaction_log_indexes.sql). The resequence script was run to
restore a contiguous, unique numbering scheme:

  040_optimize_transaction_log_indexes.sql → 041_…
  041_circuit_breaker_part11.sql           → 042_…
  V15__scaling_indexes.sql                 → 043_…

Rollback files were created for the three previously untracked migrations
(040_api_database_scaling_part27, 041_optimize_transaction_log_indexes, and
042_circuit_breaker_part11) before resequencing so both directories stay in sync.

Also adds a root eslint.config.js (ESLint v10 flat config) so the lint-staged
pre-commit hook can run without erroring on non-JS files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two Kubernetes-style health probe endpoints to the Express app:

  GET /api/v1/health/live   — liveness: returns 200 immediately, no dependency
                              checks. Used by k8s/Docker to confirm the process
                              is alive without risk of cascading timeouts.

  GET /api/v1/health/ready  — readiness: checks PostgreSQL and Redis reachability,
                              returns 200 when all deps are up, 503 otherwise.
                              Prevents load-balancer traffic until the instance is
                              ready to serve requests.

Both probes are also available on the short /health/live and /health/ready paths
for backward compatibility with non-versioned infrastructure.

Tests: added 8 new test cases covering 200/503 responses, dependency failures,
and confirming the liveness probe does not call pool.query.

Closes Gildado#697

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ldado#698)

Adds the database migration rollback infrastructure required by Issue Gildado#698:

Migration files:
  044_migration_rollback_audit.sql — creates migration_rollback_log table to
  persist an immutable audit trail of every rollback event.

New service/controller/routes:
  MigrationStatusService  — reads schema_migrations + migration_rollback_log
                            to produce a full status report (applied, pending,
                            rollback history). Gracefully degrades if the log
                            table does not exist yet.
  MigrationStatusController — three endpoints backed by the service.
  migrationStatusRoutes — registered at /api/v1/migrations/.

API endpoints:
  GET /api/v1/migrations/status    — full report: applied + pending + history
  GET /api/v1/migrations/applied   — applied migrations with checksums & dates
  GET /api/v1/migrations/rollbacks — rollback event log (most recent first)

Tests: 8 unit tests covering getApplied, getStatus (pending detection, missing
table graceful handling), getRollbackHistory (limit clamping, error resilience).

Closes Gildado#698

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…do#699)

Extends the payroll engine to track why a bonus was issued and, for
performance-based bonuses, record the employee's performance score.

Migration 045_add_performance_bonus_fields.sql:
  ALTER TABLE payroll_items ADD COLUMN bonus_type  VARCHAR(50)
    CHECK (bonus_type IN ('performance','referral','project','retention','spot','other'))
  ALTER TABLE payroll_items ADD COLUMN performance_score NUMERIC(5,2) CHECK (0–100)
  Partial indexes on both columns for efficient filtered queries.

Service changes (PayrollBonusService):
  • addBonusItem / addBatchBonusItems — now accept bonus_type and
    performance_score and persist them with each bonus item.
  • listBonusesByType(orgId, bonusType) — filter bonus history by category.
  • getPerformanceBonusesByScore(orgId, minScore) — list performance bonuses
    above a score threshold, ordered score-descending.

Controller changes (PayrollBonusController):
  • listBonusesByType  → GET /api/v1/payroll-bonus/bonuses/by-type/:bonusType
  • getPerformanceBonuses → GET /api/v1/payroll-bonus/bonuses/performance

Tests: 18 new unit tests covering bonus creation with/without type+score,
batch inserts, transaction rollback on error, listBonusesByType filtering,
getPerformanceBonusesByScore, and deletePayrollItem totals recalculation.

Closes Gildado#699

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ldado#715)

Migration 046_api_database_scaling_part25.sql:
  • api_latency_histogram table — stores pre-bucketed p50/p95/p99 latency
    observations per endpoint, with a 30-day auto-prune function.
  • idx_employees_list_covering — covering index on employees (org, status,
    created_at) to avoid heap fetches on the high-traffic employee list API.
  • idx_transactions_list_covering — covering index on transactions for the
    same reason.

New API endpoints (scalingRoutes.ts):
  GET /api/v1/scaling/latency-percentiles — compute p50/p95/p99 per endpoint
    from the histogram table over a configurable time window.
    Params: limit (default 20, max 100), windowMinutes (default 60, max 1440).

  GET /api/v1/scaling/pool-history — time-series snapshots from db_pool_health
    so operators can spot connection-pool saturation trends without Grafana.
    Params: limit (default 20, max 200).

Tests: 8 new integration tests for latency-percentiles (200 response, empty
result, limit capping, windowMinutes parameter) and pool-history (200, limit
capping, 500 on DB error).

Closes Gildado#715

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 29, 2026

@xeladev4 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Wilfred007 Wilfred007 merged commit 98e0419 into Gildado:main May 29, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants