Generated page. Written from IdaMilk/SunApps_PrintWorker at commit e24c44d on 2026-07-28, version 1.0.1.
SunApps Print Worker
What is it?
A small, long-running Windows service that polls SQL Server for queued print jobs, claims one atomically, and sends its ZPL to a Zebra printer over a raw TCP socket on port 9100.
It is the consumer half of the queue that SunApps Printer produces into.
Purpose
Printers live on the plant network; the services that want to print do not necessarily sit near them. Splitting production from consumption means a web request never blocks on a physical printer, and a printer that is offline, jammed or unplugged delays a label instead of failing the operation that asked for it.
Running as a Windows service rather than a user process means it survives logout and restarts with the machine.
How it Works
A polling loop, deliberately simple:
- Claim the next available job atomically
- Fetch the target printer's configuration
- Open a TCP socket and write the ZPL
- Mark the job succeeded or failed
- Sleep for the configured interval and repeat
The claiming step is the part that matters. It uses SQL Server locking hints — ROWLOCK, READPAST, UPDLOCK — so a job can never be picked up twice even when several workers run at once. READPAST lets a worker skip rows another worker has already locked instead of blocking on them, which is what makes horizontal scaling work: run more workers and throughput rises, with no coordination between them.
Errors back off exponentially, so a printer that is down does not generate a tight retry loop. Shutdown is graceful: SIGINT/SIGTERM finish the current job and close connections rather than abandoning a half-written label.
All database timestamps use SQL Server's SYSUTCDATETIME(), so job timing is UTC regardless of the host's clock settings.
Structure
| File | Role |
|---|---|
src/index.js | Entry point |
src/worker.js | Polling loop and lifecycle |
src/claimJob.js | Atomic job claiming |
src/jobProcessor.js | Job execution |
src/printerTcp.js | Raw TCP socket to the printer |
src/db.js | Sequelize connection |
src/config.js | Environment configuration |
src/logger.js | pino structured logging |
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| Sequelize | 6.37.8 | ORM |
| tedious | 19.2.1 | SQL Server driver |
| pino | 10.3.1 | Structured JSON logging |
| dotenv | 17.4.2 | Configuration |
Node 18 or higher. No web framework — this service exposes no HTTP surface at all.
Interfaces
| System | Direction | Purpose |
|---|---|---|
| SQL Server | both | Claims jobs, reads printer configuration, writes status |
| Zebra printers | outbound | Raw ZPL over TCP port 9100 |
Note there is no direct link to SunApps Printer — the two communicate only through the database table. Either can be restarted without the other noticing.
Operations
Runs as a Windows Service under NSSM. It needs network reach to SQL Server and to the printers on port 9100 — that second requirement is the usual cause of a worker that starts cleanly but never prints.
Logs are structured JSON via pino, so job failures can be filtered by printer or job id rather than read line by line.
Diagnostic order when labels stop appearing: confirm the service is running, then check for PrintJob rows stuck in a claimed state (a worker that died mid-job), then check TCP reachability to the printer.
Repository
| Repository | IdaMilk/SunApps_PrintWorker |
| Version | 1.0.1 |
| Primary language | JavaScript (Node) |
| Files | 12 |
| Last activity | 2026-05-18 |
| Status | Active |
The README is short but genuinely good — it explains the concurrency design rather than just listing commands, which is the part a future maintainer actually needs.