Files
evidencija-rezija/CLAUDE.md
Knee Cola 3e4d8fb95c refactor: rename email-server-worker to email-worker
Rename directory from email-server-worker to email-worker for clarity and brevity. Update all references in CLAUDE.md documentation.
2025-12-30 10:33:59 +01:00

225 lines
9.9 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository Structure
This is a multi-project repository containing:
- **web-app/**: Next.js 14 utility bills tracking application
- **docker-stack/**: Docker Compose configurations and deployment scripts
- **housekeeping/**: Database backup and maintenance scripts
- **email-worker/**: Background worker service with HTTP health monitoring
Each project is self-contained with its own dependencies.
## Development Commands
All commands should be run from within the respective project directory.
**Web App** (`cd web-app`):
- `npm install` - Install dependencies
- `npm run dev` - Start development server
- `npm run build` - Build production version
- `npm start` - Start production server
- `npm run prettier` - Format code
- `npm run seed` - Seed database with initial data
**Housekeeping** (`cd housekeeping`):
- `./db-backup--standalone.sh` - Run standalone database backup
- `./db-backup--swarm.sh` - Run swarm database backup
- `./db-dump--standalone.sh` - Run standalone database dump
- See housekeeping/README.md for more details
**Email Server Worker** (`cd email-worker`):
- `npm install` - Install dependencies
- `npm run start` - Start development server with nodemon
- `npm run build` - Build TypeScript to JavaScript
- `npm run test` - Run tests with Jest in watch mode
- `npm run run-server` - Run built server from ./build directory
## Deployment Commands
**Building Docker Image** (`cd web-app`):
- `./build.sh <version>` - Build Docker image
**Deploying** (`cd docker-stack`):
- `./deploy-standalone.sh <version>` - Deploy with docker-compose (standalone)
- `./deploy-swarm.sh <version>` - Deploy with Docker Swarm
## Architecture Overview
This is a Next.js 14 utility bills tracking application ("Evidencija Režija") with the following key components:
### Tech Stack
- **Framework**: Next.js 14 with App Router and standalone output for Docker
- **Authentication**: NextAuth v5 with Google OAuth
- **Database**: MongoDB with connection pooling
- **Internationalization**: next-intl (Croatian/English)
- **Styling**: Tailwind CSS with DaisyUI components
- **Deployment**: Docker with MongoDB 4.4.27 (AVX compatibility)
### Core Architecture Patterns
**Multi-user Data Isolation**: All database operations use the `withUser` higher-order function from `web-app/app/lib/auth.ts:102` to automatically inject authenticated user ID into queries, ensuring data isolation between users.
**Server Actions Pattern**: Form handling uses Next.js Server Actions with Zod validation. Actions are defined in `web-app/app/lib/actions/` and follow the pattern:
```typescript
export const actionName = withUser(async (user: AuthenticatedUser, ...args) => {
// Server action implementation with automatic user context
});
```
**Internationalization**: Uses next-intl with locale-based routing. Messages are in `web-app/messages/` directory. The middleware handles both auth and i18n routing.
### Key Files & Responsibilities
- `web-app/middleware.ts` - Handles authentication and i18n routing, defines public pages
- `web-app/app/lib/auth.ts` - NextAuth configuration, `withUser` HOF for user context
- `web-app/app/lib/dbClient.ts` - MongoDB connection with development/production handling
- `web-app/app/lib/actions/` - Server actions for data mutations (locations, bills, months)
- `web-app/app/i18n.ts` - Internationalization configuration (Croatian default)
- `web-app/next.config.js` - Standalone build config with `serverActions.allowedOrigins` for Docker deployment
- `housekeeping/` - Database backup and maintenance scripts
### Database Schema
- **Collections**: Locations, Bills, Months (year-month periods)
- **User Association**: All documents include `userId` field for multi-tenant isolation
- **Database Name**: "utility-bills"
### Docker Deployment Notes
- Uses standalone Next.js build for Docker optimization
- MongoDB 4.4.27 required for older CPU compatibility (no AVX instructions)
- `HOSTNAME=0.0.0.0` with `serverActions.allowedOrigins` config to handle reverse proxy headers
- Environment variables: `MONGODB_URI`, `GOOGLE_ID`, `GOOGLE_SECRET`, `AUTH_SECRET`
### Barcode/QR Code Feature
- Uses `@zxing/library` and `@zxing/browser` for PDF document scanning
- Heavy barcode decoding operations should be moved to background threads if performance issues arise
- PDF processing with `pdfjs-dist` for utility bill scanning
### Testing & Code Quality
- ESLint with Next.js and Prettier configurations
- No specific test framework configured - check with user before assuming testing approach
## Email Server Worker Architecture
The email-worker is a TypeScript-based background worker service that combines periodic task execution with HTTP health monitoring and metrics collection.
### Tech Stack
- **Runtime**: Node.js with TypeScript
- **Framework**: Express for HTTP endpoints
- **Metrics**: Prometheus (prom-client) with custom PRTG adapter
- **Testing**: Jest with TypeScript support
### Core Architecture: Worker Pattern
The service implements a **self-contained worker pattern** that runs periodic background tasks while exposing HTTP endpoints for monitoring.
**Entry Point** (`email-worker/src/entry.ts:1`):
- Creates Express HTTP server with graceful shutdown support (stoppable)
- Starts the worker via `startSyncWorker()` from `email-worker/src/workRunner.ts:134`
- Handles SIGTERM/SIGINT for graceful shutdown (Docker-compatible)
- Calls `disposeSyncWorker()` on shutdown to allow pending work to complete
**Work Runner** (`email-worker/src/workRunner.ts:1`):
The work runner implements a self-scheduling loop with the following characteristics:
- **Self-Scheduling Loop**: After completing work, schedules next execution via `setTimeout(workRunner, PULL_INTERVAL)` at `email-worker/src/workRunner.ts:113`
- **Graceful Shutdown**: Tracks pending work via Promise, allows in-flight operations to complete before shutdown
- **Status Tracking**: Exports `workerRunnerInfo` with `status` and `lastWorkTime` for health monitoring
- **Error Isolation**: Worker errors don't crash the process - caught, logged, and execution continues
- **Metrics Integration**: Automatic Prometheus metrics collection (duration, success/failure counters)
- **Single Work Instance**: Ensures only one work cycle runs at a time via `pendingWork` Promise
Work Runner States (WorkerRunnerStatus enum):
- `init` - Initial state before first run
- `beginWork` - Work cycle started
- `workDone` - Work completed successfully
- `disposed` - Worker stopped, no longer scheduling
- Other states track Prometheus stats updates
**Worker Implementation Pattern**:
Workers must export a `doWork` function with signature:
```typescript
export const doWork = async () => {
// Perform periodic work here
// Throw errors to increment failedRequestCounter
// Return normally to increment successfulRequestCounter
};
```
The work runner imports and calls this function at `email-worker/src/workRunner.ts:88`.
### Key Files & Responsibilities
**Core Worker Files**:
- `email-worker/src/entry.ts` - HTTP server setup, signal handling, worker lifecycle management
- `email-worker/src/workRunner.ts` - Self-scheduling loop, graceful shutdown, metrics integration
- `email-worker/src/app.ts` - Express app configuration, route registration
- `email-worker/src/lib/logger.ts` - Debug logger factory (uses 'debug' package)
**HTTP Routes** (`email-worker/src/routes/`):
- `healthcheckRouter.ts` - Health check endpoint (checks worker status via `workerRunnerInfo`)
- `metricsRouter.ts` - Prometheus metrics endpoint
- `prtgMetricsRouter.ts` - PRTG-compatible metrics adapter
- `pingRouter.ts` - Simple ping/pong endpoint
- `errorRouter.ts` - Structured error handler for expected errors
- `finalErrorRouter.ts` - Catch-all error handler for unexpected errors
**Infrastructure**:
- `email-worker/src/lib/metricsCounters.ts` - Prometheus counter/histogram definitions
- `email-worker/src/lib/initTools.ts` - Utility functions (coalesce, etc.)
- `email-worker/src/lib/serializeError.ts` - Error serialization for logging
- `email-worker/src/lib/Prometheus2Prtg.ts` - Converts Prometheus metrics to PRTG XML format
### Environment Variables
**Required**:
- `PULL_INTERVAL` - Milliseconds between work cycles (default: "10000")
**Optional**:
- `PORT` - HTTP server port (default: "3000")
- `PROMETHEUS_APP_LABEL` - App label for Prometheus metrics (default: "evo-open-table-sync-svc")
- `PROMETHEUS_HISTOGRAM_BUCKETS` - Histogram bucket sizes (default: "0.1, 0.5, 1, 5, 10")
- `DEBUG` - Debug namespaces for console logging (e.g., "server:server")
- `ENV` - Environment mode: "dev", "jest" (affects logging behavior)
### Creating a New Worker
To implement a new worker task:
1. **Create worker file** (e.g., `email-worker/src/myWorker.ts`):
```typescript
export const doWork = async () => {
// Implement your periodic task here
logger.info("Work Title", "Work completed successfully");
// Throw errors to mark as failed:
// throw new Error("Something went wrong");
};
```
2. **Update `workRunner.ts`** import at line 6:
```typescript
import { doWork } from "./myWorker";
```
3. **Add environment variables** to `email-worker/src/types/environment.d.ts` as needed
4. **Update `package.json` metadata** if the service purpose changes (name, description)
### Docker Deployment
- Uses `stoppable` library for graceful shutdown (10-second timeout before force-close)
- Health check endpoint at `/healthcheck` verifies worker is running and not stalled
- Prometheus metrics at `/metrics` for monitoring
- PRTG-compatible metrics at `/prtg` for legacy monitoring systems
- Graceful shutdown ensures work in progress completes before container stops
### Testing
- **Framework**: Jest with esbuild-jest for TypeScript
- **Test Location**: `email-worker/tests/`
- **Mocks**: Common mocks in `email-worker/tests/__mocks__/` (prom-client)
- **Test Pattern**: Co-located with source in `tests/` mirroring `src/` structure
- **Run Tests**: `npm run test` (watch mode)