Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
Temporal Workflows for Tenant Management
This project implements Temporal workflows for enterprise tenant creation and management in the Alga PSA system.
Overview
The Temporal workflow system provides reliable, scalable, and observable tenant provisioning with the following capabilities:
- Tenant Creation: Automated tenant database setup and configuration
- User Management: Admin user creation with proper role assignment
- Data Setup: Initial configuration of contract lines, statuses, and preferences
- Error Handling: Comprehensive rollback mechanisms for failed operations
- Monitoring: Health checks and workflow state tracking
Architecture
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Client API │ │ Temporal │ │ Activities │
│ │───▶│ Workflows │───▶│ │
│ - REST endpoints│ │ │ │ - Tenant DB ops │
│ - Validation │ │ - Orchestration │ │ - User creation │
│ - Auth │ │ - Error handling│ │ - Data setup │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Database │
│ │
│ - PostgreSQL │
│ - Tenant data │
│ - User accounts │
└─────────────────┘
Project Structure
ee/temporal-workflows/
├── src/
│ ├── workflows/ # Temporal workflow definitions
│ │ ├── tenant-creation-workflow.ts
│ │ └── index.ts
│ ├── activities/ # Activity implementations
│ │ ├── tenant-activities.ts
│ │ ├── user-activities.ts
│ │ └── index.ts
│ ├── types/ # TypeScript type definitions
│ │ └── workflow-types.ts
│ ├── worker.ts # Temporal worker process
│ └── client.ts # Temporal client library
├── k8s/ # Kubernetes deployment manifests
│ └── deployment.yaml
├── scripts/ # Deployment and utility scripts
│ └── deploy.sh
├── Dockerfile # Container image definition
├── docker-compose.yaml # Local development setup
└── README.md # This file
Quick Start - Local Development
Prerequisites
- Node.js 20+
- Temporal CLI (
brew install temporalor download from https://temporal.io/downloads) - Local PostgreSQL database running (or use the project's Docker containers)
Step-by-Step Local Development Setup
1. Start Local Database (if not already running)
# From project root (~/alga-psa)
docker ps | grep postgres # Check if already running
# If not running, start the database containers:
docker-compose up -d postgres pgbouncer
2. Start Temporal Dev Server
# In a dedicated terminal, keep this running:
temporal server start-dev
# This starts:
# - Temporal server on port 7233
# - Web UI on port 8233 (http://localhost:8233)
# - Uses SQLite (no external dependencies needed!)
3. Configure Environment
cd ee/temporal-workflows
# Create .env file with the following content:
cat > .env << 'EOF'
# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME_SERVER=server
DB_USER_SERVER=postgres
DB_PASSWORD_SERVER=postpass123
DB_USER_ADMIN=postgres
DB_PASSWORD_ADMIN=postpass123
# Temporal Configuration (using local dev server)
TEMPORAL_ADDRESS=localhost:7233
TEMPORAL_NAMESPACE=default
TEMPORAL_TASK_QUEUE=tenant-workflows
# Auth Key (get from secrets/alga_auth_key)
ALGA_AUTH_KEY=your-auth-key-here
# Logging
LOG_LEVEL=info
# Worker Configuration
MAX_CONCURRENT_ACTIVITIES=10
MAX_CONCURRENT_WORKFLOWS=10
# Health Check
ENABLE_HEALTH_CHECK=true
HEALTH_CHECK_PORT=8080
# Environment
NODE_ENV=development
EOF
# Set the actual auth key
echo "ALGA_AUTH_KEY=$(cat ../../secrets/alga_auth_key 2>/dev/null || echo 'set-your-key')" >> .env
4. Install Dependencies and Build
npm install
npm run build
5. Start the Worker
# Terminal 3: Start the worker
npm run start:worker
6. Test the Worker
# Terminal 4: Run test client
npm run start:client
Quick Commands Reference
# All commands from ee/temporal-workflows directory
# Start everything (assuming port-forwarding is active):
npm run build && npm run start:worker
# Run tests:
npm test # Unit tests
npm run test:integration # Integration tests
# Watch mode for development:
npm run dev # If available
# Check worker logs:
docker-compose logs -f temporal-worker # If using Docker
# View Temporal Web UI (after port-forwarding):
open http://localhost:8088
Troubleshooting
Database Connection Issues
# Verify PostgreSQL is running:
docker ps | grep postgres
# Test connection:
PGPASSWORD=postpass123 psql -h localhost -p 5432 -U postgres -d server -c "SELECT 1"
# If connection fails, check Docker containers:
docker-compose ps
docker-compose up -d postgres pgbouncer
Temporal Connection Issues
# Verify port-forwarding is active:
lsof -i :7233
# Check Temporal service in cluster:
kubectl get svc -n temporal | grep frontend
# Restart port-forwarding:
kubectl port-forward -n temporal svc/temporal-frontend 7233:7233
Missing Environment Variables
# Check required variables are set:
grep -E "DB_|TEMPORAL_|ALGA_AUTH_KEY" .env
# Get auth key from secrets:
cat ../../secrets/alga_auth_key
Build Errors
# Clean and rebuild:
rm -rf dist node_modules
npm install
npm run build
Alternative: Docker Compose Development
If you prefer to use Docker Compose for everything:
Docker Development
-
Start services with Docker Compose:
docker-compose up -d -
View worker logs:
docker-compose logs -f temporal-worker -
Run example client:
docker-compose run --rm temporal-client-example
Usage
Starting a Tenant Creation Workflow
import { TenantWorkflowClient } from './src/client';
const client = await TenantWorkflowClient.create();
const { workflowId, result } = await client.startTenantCreation({
tenantName: 'Acme Corporation',
adminUser: {
firstName: 'John',
lastName: 'Admin',
email: 'admin@acme.com',
password: 'securePassword123!'
},
companyName: 'Acme Corp',
contractLine: 'Enterprise'
});
console.log('Workflow started:', workflowId);
const finalResult = await result;
console.log('Tenant created:', finalResult);
Monitoring Workflow State
// Get current workflow state
const state = await client.getTenantCreationState(workflowId);
console.log('Workflow progress:', state.progress + '%');
console.log('Current step:', state.step);
// Cancel a workflow if needed
await client.cancelTenantCreation(workflowId, 'User requested cancellation', 'admin@example.com');
Health Checking
// Verify Temporal connectivity
const health = await client.healthCheck();
console.log('System status:', health.status);
Deployment
Kubernetes Deployment
-
Build and deploy:
./scripts/deploy.sh deploy -t v1.0.0 -r your-registry.com -
Check status:
./scripts/deploy.sh status -
View logs:
./scripts/deploy.sh logs -
Rollback if needed:
./scripts/deploy.sh rollback
Configuration
The worker uses environment variables for configuration:
| Variable | Description | Default |
|---|---|---|
TEMPORAL_ADDRESS |
Temporal server address | temporal-frontend.temporal.svc.cluster.local:7233 |
TEMPORAL_NAMESPACE |
Temporal namespace | default |
TEMPORAL_TASK_QUEUE |
Task queue name | tenant-workflows |
DATABASE_URL |
PostgreSQL connection string | Required |
ADMIN_DATABASE_URL |
Admin database connection | Required |
STRIPE_SECRET_KEY |
Stripe API secret key for billing integration | Required for Stripe |
MASTER_BILLING_TENANT_ID |
Nine Minds billing tenant UUID | Required for Stripe |
LOG_LEVEL |
Logging level | info |
MAX_CONCURRENT_ACTIVITIES |
Max concurrent activities | 10 |
MAX_CONCURRENT_WORKFLOWS |
Max concurrent workflows | 10 |
Workflow Details
Tenant Creation Workflow
The main workflow (tenantCreationWorkflow) performs these steps:
- Validate Input: Check tenant name and admin user details
- Create Tenant: Insert tenant record and optional default company
- Create Admin User: Set up admin user with proper authentication
- Setup Initial Data: Configure roles, statuses, billing, and preferences
- Complete: Return tenant and user IDs
Error Handling
The workflow includes comprehensive error handling:
- Validation Errors: Input validation with clear error messages
- Database Errors: Transaction rollback and data cleanup
- Timeout Handling: Configurable timeouts for each activity
- Retry Logic: Automatic retries with exponential backoff
- Rollback Operations: Clean removal of partially created data
Signals and Queries
- Cancel Signal: Gracefully cancel workflow execution
- Update Signal: Modify workflow parameters during execution
- State Query: Get current workflow progress and status
Integration
Database Integration
The workflows integrate with the existing Alga PSA database schema:
- Uses
@alga-psa/dbutilities for database connections - Follows CitusDB compatibility requirements
- Maintains tenant isolation and security policies
- Leverages existing action patterns from
server/src/lib/actions/
Security
- Passwords are hashed using the same algorithm as the main application
- All database operations respect tenant boundaries
- User permissions are properly configured
- Admin users get full system access within their tenant
Monitoring
- Structured logging with Winston
- Health check endpoints for Kubernetes
- Temporal Web UI integration for workflow visualization
- Metrics and alerting support
Testing
Unit Testing
npm test
Integration Testing
npm run test:integration
Load Testing
The system supports horizontal scaling through:
- Multiple worker instances
- Configurable concurrency limits
- Kubernetes HPA for automatic scaling
Troubleshooting
Common Issues
-
Connection Errors:
- Verify Temporal server address and connectivity
- Check network policies and service discovery
-
Database Errors:
- Ensure database credentials are correct
- Verify tenant isolation is properly configured
-
Workflow Failures:
- Check Temporal Web UI for detailed execution history
- Review worker logs for activity failures
Debugging
-
Enable debug logging:
export LOG_LEVEL=debug -
Check Temporal Web UI: https://temporal.nineminds.com
-
View worker metrics:
kubectl logs -l app=temporal-workflows-worker -n default
Development Guidelines
Adding New Workflows
- Create workflow definition in
src/workflows/ - Implement required activities in
src/activities/ - Add type definitions in
src/types/ - Update client interface if needed
- Add tests and documentation
Database Operations
- Always use transaction wrappers from
@alga-psa/db - Include tenant filtering in all queries
- Follow CitusDB compatibility patterns
- Implement proper rollback logic
Error Handling
- Use specific error types for different failure modes
- Implement idempotent operations where possible
- Provide detailed error messages and context
- Log errors with appropriate severity levels
Contributing
- Follow existing code patterns and TypeScript conventions
- Add tests for new functionality
- Update documentation for API changes
- Ensure CitusDB compatibility for database operations
- Test deployment with the provided scripts
License
This is part of the Alga PSA enterprise edition. See the main project license for details.