Background Processing
Worker Threads
Offload CPU-intensive operations from the main event loop using Node.js worker threads. Perfect for JWT operations, password hashing, encryption, and heavy computations.
Overview
Good Use Cases
- JWT token signing/verification
- Password hashing (bcrypt, argon2)
- Data encryption/decryption
- Large data transformations
- Image/video processing
- Data compression/decompression
Not Recommended
- Simple I/O operations (use async/await)
- Database queries (already non-blocking)
- Network requests (already non-blocking)
- Small computations (overhead > benefit)
Getting Started
Basic Usagetypescript
1import { createApp, getWorkerManager } from '@morojs/moro';
2
3const app = await createApp();
4const workers = getWorkerManager();
5
6// Execute a task on worker thread
7app.post('/api/hash', async (req, res) => {
8 const result = await workers.executeTask({
9 id: `hash-${Date.now()}`,
10 type: 'crypto:hash',
11 data: {
12 input: req.body.password,
13 algorithm: 'sha256'
14 }
15 });
16
17 return { hash: result };
18});
19
20app.listen(3000);Configurationtypescript
1import { createApp, WorkerManager } from '@morojs/moro';
2
3const app = await createApp({
4 workers: {
5 count: 4, // Number of worker threads (default: CPU cores - 1)
6 maxQueueSize: 1000 // Maximum queued tasks (default: 1000)
7 }
8});
9
10// Or configure manually
11const workers = new WorkerManager({
12 workerCount: 4,
13 maxQueueSize: 1000
14});Built-in Tasks
JWT Operationstypescript
1import { workerTasks } from '@morojs/moro';
2
3// Verify JWT token
4app.post('/api/auth/verify', async (req, res) => {
5 const result = await workerTasks.verifyJWT(
6 req.body.token,
7 process.env.JWT_SECRET
8 );
9
10 if (result.valid) {
11 return { user: result.payload };
12 } else {
13 return res.status(401).json({ error: 'Invalid token' });
14 }
15});
16
17// Sign JWT token
18app.post('/api/auth/login', async (req, res) => {
19 const user = await authenticateUser(req.body);
20
21 const token = await workerTasks.signJWT(
22 { userId: user.id, role: user.role },
23 process.env.JWT_SECRET,
24 { expiresIn: '7d' }
25 );
26
27 return { token };
28});Cryptographic Operationstypescript
1// Hash password
2app.post('/api/register', async (req, res) => {
3 const hash = await workerTasks.hashData(
4 req.body.password,
5 'sha256'
6 );
7
8 const user = await createUser({
9 email: req.body.email,
10 password: hash
11 });
12
13 return user;
14});
15
16// Encrypt sensitive data
17app.post('/api/secrets', async (req, res) => {
18 const encrypted = await workerTasks.encryptData(
19 req.body.secret,
20 process.env.ENCRYPTION_KEY
21 );
22
23 return { encrypted };
24});
25
26// Decrypt data
27app.get('/api/secrets/:id', async (req, res) => {
28 const secret = await getSecret(req.params.id);
29
30 const decrypted = await workerTasks.decryptData(
31 secret.data,
32 process.env.ENCRYPTION_KEY
33 );
34
35 return { secret: decrypted };
36});Data Compressiontypescript
1// Compress large response
2app.get('/api/export', async (req, res) => {
3 const data = await getLargeDataset();
4
5 const compressed = await workerTasks.compressData(
6 JSON.stringify(data)
7 );
8
9 res.setHeader('Content-Encoding', 'gzip');
10 res.setHeader('Content-Type', 'application/json');
11 return compressed;
12});
13
14// Decompress data
15app.post('/api/import', async (req, res) => {
16 const decompressed = await workerTasks.decompressData(
17 req.body.data
18 );
19
20 const data = JSON.parse(decompressed);
21 await importData(data);
22
23 return { success: true, records: data.length };
24});Task Priority & Timeout
Task Prioritytypescript
1import { getWorkerManager } from '@morojs/moro';
2
3const workers = getWorkerManager();
4
5// High priority task (executes first)
6await workers.executeTask({
7 id: 'critical-task',
8 type: 'crypto:hash',
9 data: { input: 'critical-data' },
10 priority: 'high' // 'high' | 'normal' | 'low'
11});
12
13// Normal priority (default)
14await workers.executeTask({
15 id: 'normal-task',
16 type: 'crypto:hash',
17 data: { input: 'normal-data' },
18 priority: 'normal'
19});
20
21// Low priority (executes last)
22await workers.executeTask({
23 id: 'background-task',
24 type: 'crypto:hash',
25 data: { input: 'background-data' },
26 priority: 'low'
27});Task Timeouttypescript
1await workers.executeTask({
2 id: 'long-task',
3 type: 'heavy:computation',
4 data: { operation: 'complex-calculation' },
5 timeout: 30000 // 30 seconds
6});Best Practices
1. Use Workers for CPU-Intensive Tasks Only
typescript
1// ✅ Good: CPU-intensive
2await workerTasks.hashData(password, 'sha256');
3await workerTasks.compressData(largeData);
4await workerTasks.heavyComputation(complexCalc);
5
6// ❌ Bad: I/O operations (already non-blocking)
7await db.users.find(); // Use normal async/await
8await fetch('https://api.example.com'); // Already non-blocking2. Monitor Worker Health
typescript
1// Check worker stats periodically
2setInterval(() => {
3 const stats = workers.getStats();
4
5 if (stats.queueSize > 500) {
6 console.warn('Worker queue is getting large:', stats);
7 }
8
9 if (stats.activeTasks === stats.workers) {
10 console.log('All workers are busy');
11 }
12}, 10000);
13
14// Expose metrics endpoint
15app.get('/metrics/workers', (req, res) => {
16 return workers.getStats();
17});3. Graceful Shutdown
typescript
1import { getWorkerManager } from '@morojs/moro';
2
3const workers = getWorkerManager();
4
5process.on('SIGTERM', async () => {
6 console.log('Shutting down workers...');
7 await workers.shutdown();
8 process.exit(0);
9});