Skip to main content

The Print Service: VeloxFactory on your printers

VeloxFactory does not talk to printers directly. Instead, a lightweightA companion Windows application, the BackgroundVeloxFactory PrintingPrint Service, runs on any Windows machine that has the target printers installed. It receives print tasks from VeloxFactory, rendersprints the PDF toon the printer,right printer and reports the result back. TheBoth two componentssides communicate exclusivelyonly over the VeloxFactory REST API and WebSocket;the thereWebSocket server (Laravel Reverb). There is no shared database and no shared file system.

This chapter describes version 2.0. It replaces the former console application Background Printing Service (.NET Framework 4.7.2, configuration in App.config) completely.


At a glance

One program, two ways to run Started without parameters it opens a window with dashboard, live console, job history, printer overview, statistics and settings. Started with --headless the same program runs without any window from the Windows Task Scheduler, whether a user is logged on or filesystem.not. Reliable receiving WebSocket events for speed, a safety poll against lost events, automatic polling while the WebSocket is down. Only tasks of the own broadcast ids are taken. No double prints A local job journal remembers every task. A task that reached the Windows spooler is never printed a second time, even after a crash or a lost confirmation. Sharp output PDFium draws every page directly onto the printer in its native resolution. Text, lines and barcodes stay vector graphics, nothing is rasterised in between. Rate limit aware Reads the rate limit headers of the API. On HTTP 429 every API call pauses until Retry-After, print tasks wait instead of failing. Nothing on disk PDFs stay in memory. The API token is stored encrypted (DPAPI) and separate from the configuration. Operable Rolling log files, Windows event log with fixed event ids, optional local health endpoint, diagnostic package, graceful stop for updates.

How it works

The

VeloxFactory                               servicePrint startsService as a regular Windows console process and works through two sequential phases.

Phase 1(Windows) ------------ Initial----------------------- pull

Print

Ontask startupcreated the service immediately calls GET /api/v1/report-print-task?status=pending and processes all tasks it finds. It repeats this in a loop, waiting two seconds between rounds, until the queue comes back empty and no jobs are still running. This ensures that any tasks queued while the service was offline are handled before switching to real-time mode.

Phase 2 -- WebSocket listener

event

Once--> Receiver (WebSocket / poll) <-- GET task + PDF --- Journal: known task? skip Worker -> printer lock -> PDFium -> Windows spooler <-- set-printed ------- Outbox (retried until delivered) <-- set-status error -- on permanent failures

    Receive. A new print task triggers the initial queue is drained, the service connects to VeloxFactory's WebSocket endpointevent (Laravelreport-print-task.created Reverb) and subscribes toon the private channel private-report-print-tasks. FromThe thisevent pointonly on, it reacts to incoming events in real time. Ifcarries the WebSockettask connectionid dropsand forthe anybroadcast reason,id. In addition, the service waitspolls fivethe secondspending tasks of its broadcast ids (details in Receiving and reconnects automatically, no manual restart required.
    ℹ️ The WebSocket uses the Pusher protocol. When a connection is established, the service authenticates with VeloxFactory via POST /api/v1/broadcasting/auth and subscribes to the private channel using the configured API token.

    Processing aprocessing print task

    Whether a task arrives via the initial pull or via a WebSocket event, the processing steps are identical:

      tasks
      ). FetchFetch.: The service calls GET /api/v1/report-print-task/{id} to retrieveloads the full task record, including the PDF as(withMedia=true). aThe Base64printer string.machine therefore needs HTTP access to VeloxFactory, not only WebSocket access. Write temp fileDeduplicate.: The PDFjob journal decides whether the task is decodednew. Known tasks are skipped. Print. A worker takes the task, waits for the printer if another job is running on it, checks the Windows queue (offline, paper out) and prints. Transient problems are retried. Confirm. Success is written to a temporary file in reportPdfFileTempPath (e.g. C:\VeloxFactory\temp\42_delivery_note.pdf). Print: PdfiumViewer opens the PDFoutbox first and sendsthen itsent to the printer specified in printerName. The print is repeated numberOfCopies times. Report back: On success, the service callswith PATCH /api/v1/report-print-task/{id}/set-printed,. whichIf setsVeloxFactory is unreachable, the statusoutbox toretries printed. On failure,until it callssucceeds. Permanent failures are reported with PATCH /api/v1/report-print-task/{id}/set-status withand {"status":a "error",categorised "errorMessage":error "..."}. Cleanup: The temporary file is deleted regardless of the outcome.message.
      ⚠️ The WebSocket event only carries the task ID and broadcastId, not the PDF. The service always fetches the full task from the API as a second step. This means the printer machine needs HTTP access to VeloxFactory, not just WebSocket access.

      BroadcastOperating ID filteringmodes

      listeningBroadcastIds is a list of broadcast channel identifiers the service will accept. Any report-print-task.created event whose broadcastId is not in this list is silently ignored.

      This makes it straightforward to run multiple service instances in parallel, for example one per location or printer group, each configured to respond only to its own broadcastId. The initial pull is not filtered this way: it always processes all pending tasks returned by the API, regardless of broadcastId.


      Configuration

      All settings live in App.config in the applicationSettings section. Edit the file in a text editor and restart the service for changes to take effect.

      SettingMode DescriptionStarted by ExampleBehaviour
      apiToken
      Bearer token used for all API requests and for the WebSocket subscription. Must belong to a user with global:use-api and with report-print-task:read, :update and :delete. The :read permission is also what the private channel report-print-tasks requires, a token without it can call the API but never receives a print job over the WebSocket.Headless 4|abc123...--headless, normally from the scheduled task The engine runs without any window. This is the production mode. websocketUrlMonitor WebSocketProgram endpointstarted without parameters while a headless engine runs The window shows state, console, jobs and statistics of Laravelthe Reverb.headless ws://10.0.0.10:8080/app/veloxfactoryengine and edits its configuration. It does not print itself. websocketAuthUrlInteractive VeloxFactoryProgram broadcastingstarted authwithout endpoint.parameters, no engine running http://10.0.0.10:8088/api/v1/broadcasting/authThe engine runs reportPrintTask_indexinside URLthe window. Closing the window keeps it running in the notification area. Useful for thesetup, initialtests pull,and mustmachines includewithout ?status=pending. http://10.0.0.10:8088/api/v1/report-print-task?status=pending reportPrintTask_get URL template for fetching a singlescheduled task. {0} is replaced with the task ID. http://10.0.0.10:8088/api/v1/report-print-task/{0} reportPrintTask_setPrinted URL template for marking a task as printed. {0} is replaced with the task ID. http://10.0.0.10:8088/api/v1/report-print-task/{0}/set-printed reportPrintTask_setError URL template for reporting a failed task. {0} is replaced with the task ID. http://10.0.0.10:8088/api/v1/report-print-task/{0}/set-status listeningBroadcastIds List of broadcast IDs this instance will accept. Add one <string> entry per ID. Standard, Warehouse maxParallelPrintJobs Maximum number of tasks processed concurrently. Default: 10. 10 reportPdfFileTempPath Directory for temporary PDF files. Created automatically on startup if it does not exist. C:\VeloxFactory\temp logFile Path to the log file. Relative paths are resolved from the executable directory. .\Log.log laconicLogging If True, only errors are logged. If False, all informational messages are logged as well. False

      A

      Concurrency

      named

      mutex per instance makes sure only one engine runs. The servicewindow usesdetects twoa layersrunning ofheadless concurrencyengine controlautomatically and switches to avoidmonitor overloading printers.mode.

      A

      globalℹ️ semaphoreSeveral limitsinstances theper totalmachine. numberWith of--config tasks<path> beingevery processedinstance atgets its own configuration, token, journal, logs and scheduled task. Use one instance per broadcast id or site. Two instances listening to the same timebroadcast toid maxParallelPrintJobs.would In addition, a per-printer semaphore ensures that only oneboth print job runs on a given printer at a time, jobs targeting different printers can execute in parallel, but two jobs targeting the same printer are always serialised. This preventstask, the spoolerjournal fromonly receivingprotects multiplewithin jobsone simultaneouslyinstance. from the service.

      Logging

      In

      Thethis service uses Serilog and writes to both the console and a rolling log file. Log files are capped at 100 MB each; up to 10 rotated files are retained before the oldest is deleted.

      Set laconicLogging to True in App.config to suppress informational messages and log only errors, useful in production once the service is confirmed working.


      Dependencieschapter

      Package Purpose PdfiumViewerInstallation and updates PDFRequirements, renderingfolder layout, service account, scheduled task, update and printing. Wraps the native PDFium library (bundled via PdfiumViewer.Native.x86_64.v8-xfa), no separate PDF reader installation required on the target machine.rollback RestSharpConfiguration reference HTTPEvery clientkey forof allconfig.json APIwith callsdefault toand VeloxFactory.range, token, hot reload, import and export Newtonsoft.JsonReceiving and processing print tasks JSONReceive serialisationmodes, andbroadcast deserialisationids, (APIrate responses,limit, WebSocketpipeline, messages).retries, pause, journal, outbox, dry run SerilogPrinters and printing StructuredPrinter loggingcomparison, toalias, consoleper-printer settings, dialog printers, test page The Print Service window Dashboard, console, jobs, printers, statistics, settings, info, tray icon Command line reference All parameters, exit codes and rollingexamples file. Monitoring and troubleshooting Log files, event ids, health endpoint, diagnostic package, common problems
      ℹ️⚠️ TheComing from the Background Printing Service? There is no import of the old App.config. Set up the new service targetsin .NETits Frameworkwindow 4.7.2(URL, token, WebSocket, broadcast ids), run both in parallel on a test broadcast id, then stop and runsremove onthe Windowsold only.console application. The PDFiumAPI native binary is bundled with the build output,token no additionallonger runtimeneeds installation is needed beyond report-print-task:delete.NET Framework 4.7.2, which ships with Windows 10 and Windows Server 2016 and later.