Skip to content
getnextpdf.com

Enterprise edition

Output Pipeline — Deep Reference

NextPDF\Enterprise\OutputPipeline executes many Pro pipeline manifests as one batch. BatchPipelineOrchestrator wraps the Pro PipelineExecutor with batch coordination: a bounded-resource guard on batch size, an optional global batch timeout, per-manifest variable injection, and aggregate accounting. An optional end-of-batch compliance check re-validates every completed output through the Enterprise compliance gateway and fails closed. Each run returns a BatchPipelineResult carrying per-manifest results, completed and failed counts, timing, and the optional compliance report.

This capability ships in NextPDF Enterprise (nextpdf/enterprise) and activates with an Enterprise-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.

TierOutput-pipeline surface
CoreNo output-pipeline surface.
ProSingle-manifest pipeline (capability pro.output.pipeline).
EnterpriseBatch orchestration, batch-size bound, batch timeout, compliance handoff.

The Enterprise batch surface carries no separate per-feature capability code; the package boundary gates it. The Pro single-manifest capability pro.output.pipeline is a prerequisite, not the gate. A Pro license alone unlocks only the underlying single-manifest pipeline, not this batch surface.

Terminal window
composer require nextpdf/enterprise:^3
SymbolParametersDefault behaviorReturnsThrows or fails withNotes
BatchPipelineOrchestrator::__construct()PipelineExecutor $executor, BatchPipelineConfig $config, ?ComplianceGateway $complianceGateway, ComplianceProfile $complianceProfileDefault config; no gateway; profile ComplianceProfile::PdfA4NothingInject a gateway when the compliance check is enabled; without one, every checked manifest is reported failed.
BatchPipelineOrchestrator::executeBatch()list<PipelineManifest> $manifests, array<string, array<string, mixed>> $variablesMap = []Executes manifests in submission order; variables resolve by manifest IDBatchPipelineResultOverflowException when the batch exceeds 10,000 manifests; gateway exceptions when the compliance check is enabled (see Edge cases)Resolver Throwables never escape; the Pro executor downgrades them to failed step results.
BatchPipelineConfig::__construct()int $maxConcurrency = 4, int $timeoutMs = 0, bool $complianceCheckOnComplete = falseConcurrency 4; no timeout; no compliance checkNothingReadonly value object. timeoutMs = 0 disables the batch timeout.
BatchPipelineResult::__construct()list<PipelineResult> $results, int $totalManifests, int $completedCount, int $failedCount, float $durationMs, ?array $complianceReport = nullAggregate over per-manifest PipelineResult valuesNothingReadonly. complianceReport stays null unless the check ran.
BatchPipelineResult::allSucceeded()Tests failedCount === 0boolNothingReturns true on a timeout-truncated batch with zero failures; see Edge cases.
BatchPipelineResult::successRate()completedCount / totalManifestsfloatNothingReturns 1.0 for an empty batch.
BatchPipelineResult::hasComplianceReport()Tests complianceReport !== nullboolNothing
public function __construct(
private readonly PipelineExecutor $executor,
private readonly BatchPipelineConfig $config = new BatchPipelineConfig(),
private readonly ?ComplianceGateway $complianceGateway = null,
private readonly ComplianceProfile $complianceProfile = ComplianceProfile::PdfA4,
) {}
public function executeBatch(
array $manifests,
array $variablesMap = [],
): BatchPipelineResult
public function __construct(
public int $maxConcurrency = 4,
public int $timeoutMs = 0,
public bool $complianceCheckOnComplete = false,
) {}

executeBatch() first asserts the batch size against a cap of 10,000 manifests. A batch above the cap raises OverflowException before any manifest executes; nothing degrades silently.

Manifests then execute in submission order through the Pro PipelineExecutor. Each manifest receives the variables entry keyed by its ID in $variablesMap; a manifest without an entry receives an empty variables map. A manifest counts as completed when its PipelineResult status is Completed; any other terminal status counts as failed. Resolver exceptions do not escape: the Pro executor converts every resolver Throwable into a failed step result, so executeBatch() always aggregates results rather than aborting mid-batch on a step error.

When timeoutMs is greater than zero, elapsed time is checked before each manifest starts. Once the budget is exhausted, remaining manifests are skipped: they produce no PipelineResult, and they count as neither completed nor failed. totalManifests always reports the submitted count.

When complianceCheckOnComplete is enabled, the orchestrator validates the final PDF of every completed manifest against the configured ComplianceProfile through the injected ComplianceGateway. The check fails closed:

  • No gateway injected: every checked manifest is reported failed, since compliance was never validated.
  • No PDF output resolvable from the manifest’s step outputs: failed.
  • Gateway returns no result (optional-mode sidecar unavailability): failed. Absence of a positive result is not a pass.
  • Gateway reports any non-conformance: failed.

The final PDF is resolved by scanning a completed manifest’s step outputs, last step first, for a direct string value beginning with the %PDF header. Step outputs never nest PDF byte-strings inside sub-arrays; only direct output values are inspected. Manifests that did not complete are skipped, not checked.

The compliance report is an array with keys profile, checked, passed, failed, and failures; each failure entry carries manifestId and reason. The report attaches to BatchPipelineResult::$complianceReport and is reachable via hasComplianceReport().

The compliance handoff is a re-validation aid, not an authorization control. It reports findings only.

  • More than 10,000 manifests: OverflowException before any execution starts.
  • timeoutMs = 0 means no batch timeout. Set a finite value in production.
  • Timeout truncation: skipped manifests appear in no count, so completedCount + failedCount can be less than totalManifests. allSucceeded() tests only failedCount === 0 and can return true for a truncated batch. Compare count($result->results) with totalManifests to detect truncation.
  • successRate() returns 1.0 for an empty batch (zero manifests submitted).
  • Manifest IDs are not deduplicated at batch level. Two manifests sharing an ID both execute and resolve the same variables entry.
  • Structural manifest errors (empty step list, duplicate step IDs, unknown dependency, dependency cycle, output-type mismatch, missing resume step) raise InvalidArgumentException at manifest construction, before executeBatch() is ever called.
  • With the compliance check enabled, ComplianceGateway::validate() can throw ComplianceSidecarUnavailableException (sidecar unavailable in required mode) or InvalidArgumentException (no validator registered for the profile’s tool). Either exception escapes executeBatch() after execution but before the result is built, so per-manifest results are lost to the caller. In optional mode the gateway returns null instead, and the manifest is recorded as a compliance failure.
  • An in-pipeline compliance handoff step fails when no upstream step output contains recognizable PDF bytes; it never passes silently.
  • This module performs no cryptographic operations; FIPS mode is not applicable.

This module is an orchestration layer. The optional compliance check defers to the Enterprise compliance gateway and its external validators, which carry their own references. The default profile is ComplianceProfile::PdfA4; other gateway profiles cover further PDF/A, PDF/UA, and PAdES targets.

A compliance report states validator findings against the selected profile.

  • In production deployments, parallel worker dispatch and backpressure are handled by a separate execution sidecar. The PHP orchestrator provides batch coordination and compliance-handoff logic and is invoked by the job worker, not directly by request handlers.
  • The PHP fallback path executes manifests sequentially. maxConcurrency bounds concurrent worker callbacks in the sidecar-driven deployment; sizing it relative to the PHP worker pool is the operator’s responsibility.
  • The in-pipeline compliance handoff step resolver is an internal type registered for inspect-type steps. Enable end-of-batch validation through BatchPipelineConfig rather than constructing pipeline steps for it directly.
  • Construct PipelineManifest instances early. Their structural validation runs in the constructor, so invalid graphs fail fast and never consume batch budget.

This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.