A distributed job processing system built with NestJS, Apache Pulsar, and Nx monorepo architecture.
Workq is a microservices-based job processing platform with the following components:
- Auth Service - GraphQL API for user authentication with JWT and gRPC
- Jobs Service - GraphQL API for job submission and management
- Executor Service - Background worker that processes jobs from message queues
- Framework: NestJS
- Message Queue: Apache Pulsar
- Database: PostgreSQL with Prisma ORM
- API: GraphQL with Apollo Server
- RPC: gRPC for inter-service communication
- Monorepo: Nx workspace
- Authentication: JWT with Passport
- Logging: Pino
workq/
βββ apps/
β βββ auth/ # Authentication service (GraphQL + gRPC)
β βββ jobs/ # Job management service (GraphQL)
β βββ executor/ # Job execution worker
βββ libs/
β βββ graphql/ # Shared GraphQL utilities and guards
β βββ grpc/ # gRPC protocol definitions
β βββ nestjs/ # Shared NestJS utilities (logging, init)
β βββ prisma/ # Database client and schemas
β βββ pulsar/ # Apache Pulsar client and consumer abstractions
βββ docker-compose.yml # Local development environment
- Node.js 18+
- Docker and Docker Compose
- npm or yarn
# Install dependencies
npm install
# Start infrastructure (PostgreSQL, Pulsar)
docker-compose up -d
# Run database migrations
npx prisma migrate dev --schema apps/auth/prisma/schema.prisma# Run all services in development mode
npm start
# Or run individual services
npx nx serve auth # http://localhost:3000
npx nx serve jobs # http://localhost:3001
npx nx serve executor # Background worker- Job Submission: Submit jobs via GraphQL API
- Message Queue: Apache Pulsar for reliable message delivery
- Retry Logic: Configurable retry with exponential backoff
- Dead Letter Queue: Failed messages sent to DLQ for investigation
- Idempotency: Prevent duplicate message processing
- User Management: Create and authenticate users
- JWT Tokens: Secure token-based authentication
- GraphQL Guards: Protected queries and mutations
- gRPC Auth Service: Inter-service authentication
The Pulsar consumer implementation includes:
- Retry Configuration: Configurable max retries with exponential backoff
- Dead Letter Queue: Automatic routing of failed messages
- Idempotent Processing: Deduplication store prevents duplicate processing
- Message Properties: Track retry count and error details
A sample job implementation demonstrating the job processing pipeline:
// Submit a job
mutation {
executeJob(executeJobInput: {
name: "Fibonacci"
data: { iterations: 10 }
}) {
name
description
}
}Message queue abstraction with built-in reliability features:
PulsarClient- Client for creating producers and consumersPulsarConsumer- Abstract consumer with retry/DLQ supportDeduplicationStore- In-memory idempotency tracking- Idempotency Utilities - Key generation helpers
Shared GraphQL utilities:
AbstractModel- Base GraphQL model with IDGraphQLContext- Request/response contextGqlAuthGuard- Authentication guard using gRPC
NestJS initialization and logging:
init- Common app initialization (validation, logging, cookies)LoggerModule- Pino logger configuration
gRPC service definitions for inter-service communication.
# Build all projects
npx nx run-many -t build
# Build specific project
npx nx build auth# Run tests
npx nx test auth
# Run tests for all projects
npx nx run-many -t test# Lint all projects
npx nx run-many -t lint
# Auto-fix issues
npx nx run-many -t lint --fixPre-commit hooks are configured with Husky and lint-staged:
- ESLint for code quality
- Prettier for formatting
- Staged files only
Each service has a multi-stage Dockerfile:
# Build auth service image
docker build -f apps/auth/Dockerfile -t workq-auth .
# Build jobs service image
docker build -f apps/jobs/Dockerfile -t workq-jobs .
# Build executor service image
docker build -f apps/executor/Dockerfile -t workq-executor .GraphQL Endpoints:
mutation createUser- Create a new usermutation login- Authenticate and receive JWT cookiequery users- Get all users (requires authentication)
gRPC Service:
AuthService.authenticate- Validate JWT tokens
GraphQL Endpoints:
query jobs- List all available job typesmutation executeJob- Submit a job for processing
- JWT tokens stored in HTTP-only cookies
- Password hashing with bcrypt
- GraphQL authentication guards
- gRPC authentication for inter-service calls
- Input validation with class-validator
- Environment-based configuration
Environment variables (create .env files for each service):
# Auth Service
PORT=3000
JWT_SECRET=your-secret-key
JWT_EXPIRATION_MS=3600000
DATABASE_URL=postgresql://user:pass@localhost:5432/auth
PULSAR_SERVICE_URL=pulsar://localhost:6650
# Jobs Service
PORT=3001
PULSAR_SERVICE_URL=pulsar://localhost:6650
# Executor Service
PULSAR_SERVICE_URL=pulsar://localhost:6650This project uses Nx for monorepo management:
# Visualize project dependencies
npx nx graph
# Show project details
npx nx show project auth
# Run affected tests
npx nx affected -t test
# Generate new library
npx nx g @nx/node:lib my-lib
# Generate new app
npx nx g @nx/nest:app my-app- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
MIT
- Nx Documentation
- NestJS Documentation
- Apache Pulsar Documentation
- Prisma Documentation
- GraphQL Documentation