Building a Distributed Print System with Node.js and WebSockets
# Building a Distributed Print System with Node.js and WebSockets
Enterprise label printing demands reliability at scale. This architecture handles thousands of print jobs across multiple locations with automatic printer discovery and intelligent failover.
## System Overview
The print system consists of three layers:
- >API Gateway - Receives print requests
- >Job Orchestrator - Routes and manages jobs
- >Print Workers - Execute actual printing
┌─────────────┐ ┌───────────────┐ ┌──────────────┐
│ Client │────▶│ Gateway │────▶│ Orchestrator│
└─────────────┘ └───────────────┘ └──────────────┘
│
┌─────────────────────────────┼─────────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Worker 1 │ │ Worker 2 │ │ Worker N │
│ (Warehouse) │ │ (Shipping) │ │ (Office) │
└──────────────┘ └──────────────┘ └──────────────┘
## Auto-Discovery Protocol
Workers announce themselves on startup via UDP broadcast:
javascriptconst dgram = require('dgram'); const socket = dgram.createSocket('udp4'); function announceWorker(workerId, capabilities) { const message = Buffer.from(JSON.stringify({ type: 'WORKER_ANNOUNCE', workerId, capabilities, timestamp: Date.now() })); socket.setBroadcast(true); socket.send(message, 0, message.length, 5000, '255.255.255.255'); }
### Discovery Response
The orchestrator listens for announcements and maintains a registry:
javascriptconst workers = new Map(); socket.on('message', (msg, rinfo) => { const data = JSON.parse(msg.toString()); if (data.type === 'WORKER_ANNOUNCE') { workers.set(data.workerId, { ...data, address: rinfo.address, lastSeen: Date.now() }); } });
## WebSocket Communication
Real-time job dispatch uses WebSockets for bidirectional communication:
javascriptconst WebSocket = require('ws'); class PrintWorker { constructor(orchestratorUrl, workerId) { this.ws = new WebSocket(orchestratorUrl); this.workerId = workerId; this.activeJobs = new Map(); this.ws.on('message', this.handleMessage.bind(this)); } handleMessage(data) { const message = JSON.parse(data); switch (message.type) { case 'JOB_ASSIGN': this.processJob(message.job); break; case 'JOB_CANCEL': this.cancelJob(message.jobId); break; case 'STATUS_REQUEST': this.reportStatus(); break; } } }
## Smart Retry Logic
Print failures are inevitable. The retry system handles them gracefully:
| Failure Type | Retry Strategy | Max Attempts |
|---|---|---|
| Network Timeout | Exponential backoff | 5 |
| Paper Jam | Immediate retry | 3 |
| Offline Printer | Route to backup | 1 |
| Invalid Data | No retry (fail fast) | 0 |
javascriptasync function executeWithRetry(job, options = {}) { const { maxAttempts = 3, backoffMs = 1000 } = options; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { return await executePrintJob(job); } catch (error) { if (!isRetryable(error) || attempt === maxAttempts) { throw error; } const delay = backoffMs * Math.pow(2, attempt - 1); await sleep(delay); } } }
## Brother Raster Protocol Integration
Label printing uses the Brother raster protocol for thermal printers:
javascriptconst net = require('net'); function sendLabelToPrinter(printerIp, labelData) { return new Promise((resolve, reject) => { const socket = new net.Socket(); socket.connect(9100, printerIp, () => { // Initialize printer socket.write(Buffer.from([0x1B, 0x40])); // ESC @ // Set media type socket.write(Buffer.from([0x1B, 0x69, 0x7A, ...])); // Send raster data socket.write(labelData); // End job socket.write(Buffer.from([0x1A])); socket.end(); }); socket.on('close', resolve); socket.on('error', reject); }); }
## Monitoring and Metrics
Every component emits metrics for observability:
- >Job Latency - Time from submission to completion
- >Queue Depth - Pending jobs per worker
- >Error Rates - Failures by type and printer
- >Throughput - Jobs per minute per location
## Conclusion
Distributed printing requires careful orchestration of discovery, routing, and failure handling. This event-driven architecture scales horizontally while maintaining reliability through smart retry logic and real-time communication.