Enterprise edizione
Stream: elaborazione di job documentali
In sintesi
Sezione intitolata “In sintesi”NextPDF\Enterprise\Stream\DocumentJobStreamProcessor trasforma uno stream di manifest di rendering in esiti durevoli e tracciabili. Consuma un iterable<RenderManifest> come generatore, esegue il rendering di finestre limitate tramite il motore di rendering Pro e finalizza ogni job nell’ordine di origine. Ogni job termina in esattamente uno stato terminale: output committato, riconosciuto come già committato, oppure dead-lettered. L’avanzamento è sottoposto a checkpoint, così un run andato in crash riprende senza ripubblicare nulla.
La storia dello Stream si divide tra due edizioni, e la divisione è deliberata. Pro fornisce il motore di rendering durevole e concorrente e gli store del filesystem locale a singolo host — la metà in-process. Enterprise fornisce questo processore di stream di job documentali più i pezzi che attraversano i confini tra host: il committer verso l’object storage (ObjectStorageCommitter) e l’outbox durevole degli eventi terminali (FilesystemOutboxEmitter). La pagina Pro Stream enuncia lo stesso confine dal proprio lato.
Disponibilità e licenze
Sezione intitolata “Disponibilità e licenze”Questa capacità viene distribuita in NextPDF Enterprise (nextpdf/enterprise) e si attiva con un envelope di licenza di livello Enterprise. Un deployment privo di tale entitlement non carica le classi della capacità. Confronta le edizioni e ottieni una licenza.
Installazione
Sezione intitolata “Installazione”composer require nextpdf/enterpriseLe classi di questa pagina risiedono sotto NextPDF\Enterprise\Stream e NextPDF\Enterprise\Stream\Storage. Consumano i contratti Pro congelati in NextPDF\Pro\Stream — interfacce di motore, committer, checkpoint, idempotenza, retry e dead-letter.
Panoramica concettuale
Sezione intitolata “Panoramica concettuale”Il compito del processore è la semantica di consegna, non il rendering. Raggruppa lo stream di manifest in finestre di offset di origine non più grandi della dimensione di batch del motore. Ogni finestra esegue il rendering tramite RenderEngineInterface::renderBatch(), con retry limitato e deterministico dei timeout per elemento. Poi ogni elemento viene finalizzato nell’ordine di offset di origine verso un esito terminale.
Il confine exactly-once è per elemento, ed è ancorato nel committer, non nella coordinazione. L’avanzamento durevole è un high-watermark di offset in base 1: ogni offset pari o inferiore al checkpoint ha raggiunto un esito terminale. L’ordine della barriera è fisso: committare i byte, avanzare il watermark, salvare il checkpoint, scaricare i mark di idempotenza bufferizzati, poi emettere gli eventi terminali. Un crash tra commit e checkpoint ri-committa in modo idempotente alla ripresa, perché il committer confronta i digest. Un crash dopo il checkpoint avanza rapidamente oltre l’offset, così nulla viene pubblicato due volte.
ObjectStorageCommitter implementa il Pro OutputCommitterInterface verso un object store tramite il minimale ObjectStorageClientInterface. Il container del target è il bucket e la sua key la chiave dell’oggetto. Ri-committare byte identici è un no-op con confronto dei digest. Byte divergenti senza overwrite sollevano il conflitto SPEC-COMMIT-409. Un oggetto nuovo viene creato solo tramite la scrittura condizionale atomica putIfAbsent(); perdere quella race innesca un loop limitato di rilettura e risoluzione. L’exactly-once cross-writer regge quindi esattamente nella misura in cui il putIfAbsent() del tuo adapter è una vera scrittura condizionale — If-None-Match: * su S3, ifGenerationMatch: 0 su GCS. Questo ciclo distribuisce l’interfaccia più il NullObjectStorageClient in-memory; l’adapter S3/GCS dal vivo è fornito dall’host.
Gli eventi terminali chiudono il cerchio per i sistemi a valle. Dopo la barriera del checkpoint il processore tenta di emettere un JobTerminalEvent per ogni job finalizzato — identificatori, stato, ricevuta, dettagli dell’errore, conteggio dei tentativi, e mai alcun byte PDF. Con un semplice emitter a callback, l’emissione è at-most-once: gli eventi successivi a un checkpoint possono essere saltati alla ripresa dopo un crash. FilesystemOutboxEmitter rende durevole ogni evento una volta che emit() viene eseguito: ogni evento è un file JSON atomico denominato da un hash del suo eventId deterministico, così ri-emettere dopo una ripresa è idempotente, un relay consegna at-least-once e i consumatori deduplicano su eventId. Un confine rimane in ogni caso: l’emissione avviene dopo la barriera del checkpoint, così un crash tra checkpoint.save() ed emit() salta l’evento terminale di quell’elemento alla ripresa. I sistemi a valle che richiedono un registro completo degli eventi dovrebbero riconciliarsi con gli oggetti committati (lo store è la fonte di verità), non con il solo outbox.
Le licenze sono cablate nel percorso di output. La factory withBrandingFromLicense() risolve una strategia di branding di valutazione una volta per run a partire dalla licenza. Una licenza a pagamento si risolve in una trasformazione identità. Una licenza di valutazione o mancante applica un watermark a ogni documento committato, e un documento a cui non è possibile applicare il branding viene dead-lettered — il processore non committa mai byte di valutazione senza branding.
Perché funziona così
Sezione intitolata “Perché funziona così”La decisione portante è che l’exactly-once poggia sull’oggetto del committer, creato in modo condizionale e con confronto dei digest — non su lock distribuiti o consenso. La scrittura condizionale dell’object store è l’unica primitiva atomica che il design richiede, e tutto il resto può fallire e recuperare. È per questo che il motore di rendering deve rimanere privo di effetti collaterali, per cui lo stato con chiave e le cache di deduplicazione in-run sono trattati come accelerazioni ricalcolabili, e per cui un commit ambiguo aborta il run invece di indovinare: il percorso di ripresa converge attraverso lo stesso confronto dei digest. È anche per questo che il singolo scrittore per runId è un requisito dichiarato piuttosto che una lease imposta — lo store dei checkpoint rimane deliberatamente semplice, e il livello di commit rimane la rete di sicurezza.
Contesto di design: Generazione documentale ad alto volume.
Superficie API
Sezione intitolata “Superficie API”DocumentJobStreamProcessor
Sezione intitolata “DocumentJobStreamProcessor”Gli host dovrebbero costruire tramite la factory, così che il controllo dal-licenza-al-branding non resti mai non cablato:
public static function withBrandingFromLicense( RenderEngineInterface $engine, OutputCommitterInterface $committer, IdempotencyStoreInterface $idempotency, CheckpointStoreInterface $checkpoints, KeyedStateStoreInterface $state, DeadLetterStoreInterface $deadLetters, RetryPolicy $retryPolicy, ClockInterface $clock, EntitlementEvaluator $entitlementEvaluator, ?LicenseKey $license, ?StreamProcessorProbe $probe = null, ?JobCompletionEmitterInterface $emitter = null, ?BrandingApplicator $brandingApplicator = null,): self$clock è Symfony\Component\Clock\ClockInterface (il backoff dei retry dorme attraverso di esso). Una licenza null si risolve fail-closed nel branding di valutazione.
L’unico punto di ingresso elabora un run e restituisce i suoi contatori:
public function process(iterable $manifests, StreamProcessorConfig $config): ProcessingSummarySolleva o fallisce con: NextPDF\Enterprise\Stream\Exception\StreamProcessorException quando le precondizioni di crash-safety falliscono (un run crashSafe con collaboratori non durevoli) o quando un commit è ambiguo; InvalidArgumentException quando windowSize supera il maxBatchSize() del motore.
StreamProcessorConfig
Sezione intitolata “StreamProcessorConfig”public function __construct( public string $runId, int $windowSize = 32, int $checkpointIntervalJobs = 100, public bool $crashSafe = true, public bool $emitSkippedCompletions = false,)Solleva o fallisce con: InvalidArgumentException quando windowSize o checkpointIntervalJobs è inferiore a 1. $runId è l’identificatore di run stabile a singolo scrittore che dà la chiave alla ripresa da checkpoint.
ObjectStorageCommitter
Sezione intitolata “ObjectStorageCommitter”public function __construct( private ObjectStorageClientInterface $client, private string $scheme, private ClockInterface $clock,) {}$scheme nomina lo schema di target che questo committer serve (per esempio s3 o gcs); $clock qui è Psr\Clock\ClockInterface.
public function commit( string $jobId, OutputObjectKey $target, string $bytes, string $sha256, bool $overwrite = false,): CommitReceiptSolleva o fallisce con: UnsupportedTargetException su una mancata corrispondenza dello schema; RenderManifestException quando la chiave di target non è sicura rispetto al container; CommitIntegrityException quando lo sha-256 dichiarato non corrisponde ai byte; OutputCommitConflictException (SPEC-COMMIT-409) su byte divergenti senza overwrite; RuntimeException quando la race di creazione non riesce a convergere dopo 5 tentativi sotto mutazione concorrente.
ObjectStorageClientInterface
Sezione intitolata “ObjectStorageClientInterface”La superficie minimale dell’adapter che un’integrazione S3/GCS dal vivo implementa:
public function shaOf(string $bucket, string $key): ?string;
public function put(string $bucket, string $key, string $bytes, string $sha256): void;
public function putIfAbsent(string $bucket, string $key, string $bytes, string $sha256): bool;putIfAbsent() deve essere una vera creazione condizionale atomica (If-None-Match: * su S3, ifGenerationMatch: 0 su GCS) e restituisce true solo quando questa chiamata ha scritto l’oggetto. put() è la sovrascrittura incondizionata usata unicamente quando il manifest ha richiesto overwrite.
JobCompletionEmitterInterface e FilesystemOutboxEmitter
Sezione intitolata “JobCompletionEmitterInterface e FilesystemOutboxEmitter”public function emit(JobTerminalEvent $event): void;L’emitter è opzionale sul processore. Gli eventi si attivano solo dopo che un elemento è stato finalizzato in modo durevole. FilesystemOutboxEmitter è l’implementazione durevole distribuita:
public function __construct(string $directory, ?AtomicFileWriter $writer = null)Solleva o fallisce con: InvalidArgumentException quando la directory non esiste; emit() solleva RuntimeException se un evento non può essere codificato in JSON. hasEvent(string $eventId): bool verifica l’outbox; count(): int riporta gli eventi non consegnati.
JobTerminalEvent e JobTerminalStatus
Sezione intitolata “JobTerminalEvent e JobTerminalStatus”public function __construct( public string $eventId, public string $runId, public int $sourceOffset, public string $jobId, public string $idempotencyKeyValue, public JobTerminalStatus $status, public ?CommitReceipt $receipt, public ?string $errorCode, public ?string $errorMessage, public int $attempts, public DateTimeImmutable $occurredAt,) {}eventId è deterministico — runId:sourceOffset:idempotencyKey:status — ed è ciò che rende possibile la deduplicazione dell’outbox. toArray() serializza l’evento per il trasporto; non trasporta byte PDF. JobTerminalStatus è un enum di stringhe: Committed (committed), DeadLettered (dead_lettered), Skipped (skipped).
ProcessingSummary
Sezione intitolata “ProcessingSummary”Contatori immutabili restituiti da process(): runId, sourceRead, fastForwardedByCheckpoint, skippedByIdempotency, windows, renderBatchCalls, renderRetries, commitReceipts, deadLettered, checkpointSaves e finalCommittedOffset (l’high-watermark terminale finale).
Esempio di codice — Avvio rapido
Sezione intitolata “Esempio di codice — Avvio rapido”Commit exactly-once verso object storage in isolamento. Il NullObjectStorageClient in-memory sostituisce il tuo adapter S3/GCS; le semantiche che osservi sono quelle che un adapter dal vivo deve preservare.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Stream\Storage\NullObjectStorageClient;use NextPDF\Enterprise\Stream\Storage\ObjectStorageCommitter;use NextPDF\Manifest\OutputObjectKey;use NextPDF\Pro\Stream\Exception\OutputCommitConflictException;use Symfony\Component\Clock\NativeClock;
$committer = new ObjectStorageCommitter( client: new NullObjectStorageClient(), // swap in your S3/GCS adapter scheme: 's3', clock: new NativeClock(),);
$target = new OutputObjectKey(scheme: 's3', container: 'invoices', key: '2026/07/inv-1001.pdf');$bytes = '%PDF-1.7 example-rendered-bytes';$sha = hash('sha256', $bytes);
$first = $committer->commit('inv-1001', $target, $bytes, $sha);$replay = $committer->commit('inv-1001', $target, $bytes, $sha); // crash-resume replay
printf("first : reuse=%s, %d bytes\n", var_export($first->idempotentReuse, true), $first->bytesWritten);printf("replay: reuse=%s\n", var_export($replay->idempotentReuse, true));
try { $divergent = '%PDF-1.7 different-bytes'; $committer->commit('inv-1001', $target, $divergent, hash('sha256', $divergent));} catch (OutputCommitConflictException $conflict) { echo 'conflict: ' . $conflict->specCode() . "\n"; // no silent clobber}Output atteso:
first : reuse=false, 31 bytesreplay: reuse=trueconflict: SPEC-COMMIT-409Esempio di codice — Produzione
Sezione intitolata “Esempio di codice — Produzione”Un run crash-safe completo: store Pro durevoli, il committer verso object storage, un outbox durevole e branding risolto dalla licenza. Rieseguire lo stesso runId dopo un crash avanza rapidamente e converge.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Licensing\EntitlementEvaluator;use NextPDF\Enterprise\Stream\DocumentJobStreamProcessor;use NextPDF\Enterprise\Stream\Exception\StreamProcessorException;use NextPDF\Enterprise\Stream\FilesystemOutboxEmitter;use NextPDF\Enterprise\Stream\Storage\ObjectStorageCommitter;use NextPDF\Enterprise\Stream\StreamProcessorConfig;use NextPDF\Manifest\Render\SingleDocumentRenderer;use NextPDF\Manifest\RenderManifest;use NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore;use NextPDF\Pro\Stream\Dedup\FilesystemIdempotencyStore;use NextPDF\Pro\Stream\Engine\InProcessRenderEngine;use NextPDF\Pro\Stream\Retry\FilesystemDeadLetterStore;use NextPDF\Pro\Stream\Retry\RetryPolicy;use NextPDF\Pro\Stream\State\InMemoryKeyedStateStore;use Symfony\Component\Clock\NativeClock;
// Production requires a host-supplied adapter whose putIfAbsent() is a TRUE// atomic conditional create (S3 If-None-Match: *, GCS ifGenerationMatch: 0)// and whose shaOf() reads durable object state. NullObjectStorageClient is// for the quick start only - it keeps nothing across processes.$s3Client = new \Aws\S3\S3Client(['region' => 'eu-central-1', 'version' => 'latest']);$objectClient = new \Acme\Storage\S3ObjectStorageClient($s3Client); // implements ObjectStorageClientInterface
$stateDir = '/var/lib/nextpdf/stream';foreach (['checkpoints', 'idempotency', 'dead-letters', 'outbox'] as $sub) { if (!is_dir($stateDir . '/' . $sub)) { mkdir($stateDir . '/' . $sub, 0770, true); }}
// One manifest per JSONL line; the generator never materialises the batch.$manifests = (static function (string $path): Generator { $handle = fopen($path, 'rb'); if ($handle === false) { throw new RuntimeException('Cannot open job stream: ' . $path); } try { while (($line = fgets($handle)) !== false) { if (trim($line) !== '') { yield RenderManifest::fromJson(trim($line)); } } } finally { fclose($handle); }})('/var/spool/nextpdf/jobs.jsonl');
$license = null; // your licensing bootstrap yields a LicenseKey; null = evaluation branding
$processor = DocumentJobStreamProcessor::withBrandingFromLicense( engine: new InProcessRenderEngine(SingleDocumentRenderer::standalone()), // For a live bucket, implement ObjectStorageClientInterface over your S3/GCS SDK. committer: new ObjectStorageCommitter($objectClient, 's3', new NativeClock()), idempotency: new FilesystemIdempotencyStore($stateDir . '/idempotency'), checkpoints: new FilesystemCheckpointStore($stateDir . '/checkpoints'), state: new InMemoryKeyedStateStore(), // recomputable; durability not required here deadLetters: new FilesystemDeadLetterStore($stateDir . '/dead-letters'), retryPolicy: new RetryPolicy(maxAttempts: 3, baseDelayMs: 200, maxDelayMs: 5_000), clock: new NativeClock(), entitlementEvaluator: new EntitlementEvaluator(), license: $license, emitter: new FilesystemOutboxEmitter($stateDir . '/outbox'),);
$config = new StreamProcessorConfig( runId: 'nightly-invoices-2026-07-03', windowSize: 32, checkpointIntervalJobs: 100, crashSafe: true,);
try { $summary = $processor->process($manifests, $config);} catch (StreamProcessorException $e) { // Ambiguous commit or a non-durable collaborator: the finalized prefix is // checkpointed. Re-run the SAME runId; the committer converges by digest. fwrite(STDERR, 'Run aborted for safe resume: ' . $e->getMessage() . PHP_EOL); exit(1);}
printf( "run %s: read=%d committed=%d dedup-skipped=%d dead-lettered=%d checkpoints=%d final-offset=%d\n", $summary->runId, $summary->sourceRead, $summary->commitReceipts, $summary->skippedByIdempotency, $summary->deadLettered, $summary->checkpointSaves, $summary->finalCommittedOffset,);Output di esempio (i contatori dipendono dal tuo stream di job):
run nightly-invoices-2026-07-03: read=1200 committed=1187 dedup-skipped=13 dead-lettered=0 checkpoints=12 final-offset=1200Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Il singolo scrittore per
runIdè una tua responsabilità. Lo store dei checkpoint non ha lease né compare-and-swap. Due scrittori concorrenti su un unicorunIdsono fuori dal contratto; imponi l’esclusività nel tuo scheduler. crashSafe: truefallisce rapidamente su collaboratori non durevoli. Gli store di committer, checkpoint, idempotenza e dead-letter devono implementare tutti il markerDurableCapability, altrimentiprocess()sollevaStreamProcessorExceptionnominando i responsabili. Lo store dello stato con chiave è deliberatamente esentato: lo stato con chiave perso viene ricalcolato dal checkpoint in avanti.windowSizedeve stare nel motore. Una finestra più grande dimaxBatchSize()sollevaInvalidArgumentExceptionprima che inizi qualsiasi lavoro.- Un commit ambiguo aborta; un conflitto no.
SPEC-COMMIT-409è un conflitto terminale deterministico: l’elemento va in dead-letter e il run continua. Qualsiasi altro fallimento di commit è ambiguo: il prefisso finalizzato viene sottoposto a checkpoint e il run solleva per una ripresa sicura. - I fallimenti di rendering non abortano mai il run. Un risultato
Failedper elemento, un budget di retry esaurito o byte di valutazione a cui non è possibile applicare il branding portano tutti quell’elemento in dead-letter e continuano. - Valori di
jobIdduplicati sono sicuri; il lavoro duplicato è gestito con chiave suidempotencyKey. I risultati si correlano agli elementi tramite offset di origine univoco, mai tramitejobId. Una chiave di idempotenza duplicata viene riconosciuta anche all’interno dello stesso intervallo di barriera, prima di ri-eseguire il rendering. - La durabilità dell’emitter decide la semantica degli eventi. Un semplice emitter a callback è solo osservatore e at-most-once attraverso un crash.
FilesystemOutboxEmitterrende l’outbox durevole e con chiave di deduplicazione; la consegna via relay è allora at-least-once, e l’exactly-once a valle richiede la deduplicazione da parte del consumatore sueventId. La sua directory (come quella di ogni store su filesystem) deve pre-esistere, altrimenti il costruttore sollevaInvalidArgumentException. - Gli eventi Skipped sono disattivati per impostazione predefinita. Imposta
emitSkippedCompletions: trueper emettere anche un evento terminaleSkippedper gli elementi cortocircuitati dalla deduplicazione.
Note di sicurezza
Sezione intitolata “Note di sicurezza”- Le chiavi di output falliscono in modo chiuso.
commit()riafferma che la chiave di target è sicura rispetto al container: nessun traversal.., nessuna fuga assoluta, nessun byte null, nessuno schema di stream-wrapper incorporato e nessun due punti (che chiude il vettore NTFS alternate-data-stream). Le chiavi non sicure sollevano prima di qualsiasi chiamata allo storage. - L’integrità viene riverificata al confine. Il committer ricalcola lo sha-256 sui byte effettivi e rifiuta una mancata corrispondenza con
CommitIntegrityException, così un handoff corrotto non può atterrare silenziosamente. - Gli eventi non trasportano contenuto documentale.
JobTerminalEvente le righe dell’outbox contengono solo identificatori, digest, timestamp e stringhe di errore. I messaggi di errore possono riecheggiare la diagnostica del motore; ripuliscili, insieme a qualsiasi schema dijobIdche identifichi il tenant, prima di spedire i file dell’outbox a sink di terze parti. - L’output di valutazione non viene mai pubblicato senza branding. Quando il branding è richiesto e non può essere applicato, l’elemento viene dead-lettered anziché committato.
- L’exactly-once cross-writer è forte solo quanto il tuo adapter. Se
putIfAbsent()non è una vera scrittura condizionale atomica, la garanzia degrada a una semantica a singolo scrittore. Le credenziali dell’object store e la policy del bucket sono responsabilità dell’host; il modulo non le gestisce mai.
Conformità
Sezione intitolata “Conformità”Nessuno standard pubblicato definisce il comportamento di questo modulo. Le garanzie di exactly-once, checkpoint e outbox su questa pagina sono contratti ingegneristici dell’API NextPDF Enterprise, enunciati qui come comportamento osservabile esternamente — non sono conformità a, né certificazione rispetto a, alcuno standard. L’uso interno di SHA-256 come digest di integrità è parimenti idraulica, non una rivendicazione di conformità. Come ovunque in NextPDF: il supporto non è conformità, e la conformità non è certificazione. NextPDF non detiene alcuna certificazione e non ne concede nessuna; se un deployment costruito su questo modulo soddisfi i tuoi obblighi normativi o contrattuali è una determinazione che spetta ai tuoi valutatori.
Contratto di comportamento
Sezione intitolata “Contratto di comportamento”Gli eventi terminali non fanno parte della transazione di checkpoint: l’emissione viene eseguita dopo checkpoint.save(), così l’outbox contiene ogni evento emesso in modo durevole ma non è un registro completo attraverso i crash. Gli oggetti committati rimangono la fonte di verità.
- Ogni offset di origine pari o inferiore a
finalCommittedOffsetha raggiunto esattamente un esito terminale:Committed,SkippedoDeadLettered. - Gli elementi vengono finalizzati nell’ordine di offset di origine; l’ordine della barriera è commit, salvataggio del checkpoint, flush del mark di idempotenza, poi emissione dell’evento.
- Rieseguire un run con lo stesso
runIdnon pubblica mai due volte: gli offset sottoposti a checkpoint avanzano rapidamente, e i re-commit byte-identici sono no-op con confronto dei digest conidempotentReuse: true. - Un oggetto nuovo viene creato solo tramite la creazione condizionale atomica; byte divergenti su una chiave occupata senza
overwritesono un dead-letter deterministicoSPEC-COMMIT-409, mai una sovrascrittura. - Un commit ambiguo sottopone a checkpoint il prefisso finalizzato e aborta con
StreamProcessorException; l’offset fallito non viene avanzato. - Un run
crashSaferifiuta collaboratori di committer, checkpoint, idempotenza o dead-letter non durevoli prima di leggere qualsiasi input. - Gli id degli eventi sono una funzione pura di run, offset, chiave di idempotenza e stato, così un outbox durevole contiene al massimo una riga per evento.
Fallback su Core
Sezione intitolata “Fallback su Core”NextPDF Core esegue il rendering di un documento alla volta tramite il writer e il contratto render-manifest — vedi Writer. Core da solo non ha stream di job durevoli, né ripresa da checkpoint, né deduplicazione con idempotenza, né commit verso object storage, né outbox di eventi terminali. NextPDF Pro aggiunge il motore di rendering durevole e concorrente e gli store del filesystem a singolo host (Stream in Pro). La metà cross-host — questo processore, il committer verso object storage e l’outbox durevole — richiede NextPDF Enterprise.
Confine di pubblicazione
Sezione intitolata “Confine di pubblicazione”Questa pagina documenta solo il comportamento osservabile esternamente e la superficie API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi dei file di runbook e i prefissi dei ticket sono fuori ambito.
Vedi anche
Sezione intitolata “Vedi anche”- Stream (Pro) — la metà in-process: motore di rendering, executor e store locali durevoli.
- Stream — Riferimento approfondito — il riferimento a livello di contratto per le interfacce Stream condivise.
- Output Pipeline (Enterprise) — orchestrazione batch su manifest di pipeline.
- Trial e branding — come il branding di valutazione viene risolto e applicato.
- Generazione documentale ad alto volume — lo scenario per cui questo modulo esiste.
- Gestire NextPDF in produzione — postura di deployment per worker a lunga esecuzione.