Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

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 Usage

typescript

1import { createApp, getWorkerManager } from '@morojs/moro';
2
3const app = 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);

Configuration

typescript

1import { createApp, WorkerManager } from '@morojs/moro';
2
3const app = 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 Operations

typescript

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 Operations

typescript

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 Compression

typescript

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 Priority

typescript

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 Timeout

typescript

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

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-blocking

2. Monitor Worker Health

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

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});

Next Steps