Lewati ke konten
getnextpdf.com

Pro edisi

Stream — Referensi Mendalam

Halaman ini mendokumentasikan kontrak, kelas, metode, dan mode kegagalan publik dari subsistem NextPDF\Pro\Stream di luar yang ada pada halaman tinjauan. Setiap tipe di bawah ini merupakan bagian dari permukaan publik Pro yang terdokumentasi.

Kapabilitas ini dikirim dalam NextPDF Pro (nextpdf/pro) dan aktif dengan envelope lisensi tier Pro. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.

Tidak ada flag lisensi per-fitur yang berlaku; kode dikirim bersama edisi Pro. Jumlah worker, ukuran batch, anggaran retry, dan backend store adalah parameter runtime.

NextPDF\Pro\Stream\Engine\RenderEngineInterface adalah kontrak antara mesin throughput dan prosesor stream document-job. Mesin mengimplementasikannya (memegang konkurensi, siklus hidup worker-pool, backpressure, memori terbatas); prosesor stream mengonsumsinya (memegang keyed state, dedup, retry, checkpoint, dan commit exactly-once). Mesin mengembalikan byte ditambah sha-256, tidak pernah lokasi yang sudah di-commit — kebebasan efek-samping itulah yang memungkinkan prosesor melakukan staging, commit, dan checkpoint tepat sekali.

public function renderBatch(array $manifests, array $variablesByJobId = []): array; // list<EngineRenderResult>, input order
public function maxBatchSize(): int; // int<1, max> backpressure hint
public function isAvailable(): bool;

$manifests adalah list<RenderManifest> berukuran paling banyak maxBatchSize(); $variablesByJobId memetakan job id ke variabel templat array<string, scalar>. Kegagalan per-manifes adalah hasil Failed/Timeout per-item dan tidak pernah membatalkan batch.

NextPDF\Pro\Stream\Engine\InProcessRenderEngine

Bagian berjudul “NextPDF\Pro\Stream\Engine\InProcessRenderEngine”

Baseline sinkron, satu-proses. Memvalidasi setiap manifes secara fail-closed melalui RenderManifestValidator (batas payload inline 16 MiB, allow-list konformansi/tanda tangan, format content-hash sha-256, sintaks locale BCP-47) sebelum me-render melalui Core SingleDocumentRenderer. Galat validasi yang memblokir melakukan short-circuit ke EngineRenderResult::failed(jobId, 'SPEC-MANIFEST-INVALID', ...); eksepsi render menjadi 'SPEC-RENDER-EXCEPTION'. Konstruktor: __construct(SingleDocumentRenderer $renderer, int $maxBatchSize = 64, ?RenderManifestValidator $validator = null)maxBatchSize < 1 memunculkan InvalidArgumentException. isAvailable() selalu true.

NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine

Bagian berjudul “NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine”

final readonly, __construct(RenderUnitExecutorInterface $executor). Membungkus setiap manifes dalam RenderUnit berindeks, menjalankannya melalui executor, dan menyortir ulang penyelesaian berdasarkan indeks sehingga keluaran identik secara byte dengan render sekuensial. Indeks penyelesaian di luar [0, count) memunculkan RenderEngineException::unknownUnit(); indeks yang berulang memunculkan duplicateResult(); indeks yang hilang memunculkan missingResult(). maxBatchSize() dan isAvailable() mendelegasikan ke executor.

NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface

Bagian berjudul “NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface”
public function execute(array $units): iterable; // iterable<CompletedRenderUnit>, any order
public function maxBatchSize(): int;
public function isAvailable(): bool;

Implementasi boleh meng-yield penyelesaian dalam urutan apa pun; ConcurrentRenderEngine memulihkan urutan berdasarkan indeks.

NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor

Bagian berjudul “NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor”

final readonly, __construct(RenderEngineInterface $inner). Me-render setiap unit secara berurutan melalui mesin dalam — referensi kebenaran deterministik yang harus dipadankan executor paralel byte demi byte. Tanpa waktu, proses, thread, atau keacakan.

NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor

Bagian berjudul “NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor”

final readonly. Mendistribusikan sebuah batch ke hingga maxWorkers subproses worker php (satu chunk masing-masing) yang me-render secara paralel; keluaran identik secara byte dengan baseline inline. Konstruktor:

__construct(
int $maxWorkers = 4,
int $maxBatchSize = 64,
?string $phpBinary = null,
?string $workerScript = null,
?string $autoload = null,
?int $timeoutSeconds = 300, // null disables the wall-clock watchdog
)

Kontrak ketangguhan:

  • Bebas deadlock, aman di Windows. Payload dan hasil unit melintas melalui berkas temp, bukan pipe; parent melakukan polling proc_get_status() dan hanya menguras pipe hingga EOF setelah worker keluar, sehingga worker tidak dapat memacetkan parent.
  • Tunggu terbatas. timeoutSeconds membatasi keseluruhan render paralel; saat kedaluwarsa, setiap worker yang masih berjalan diterminasi dan sebuah RenderEngineException dimunculkan.
  • Higiene sumber daya. Sebuah finally menutup pipe, melakukan upaya terminate-and-reap terbatas pada worker yang masih bertahan (terminate anggun → force-kill → reap; anak yang tidak teramati berhenti dalam masa tenggang terbatas ditinggalkan alih-alih mengambil risiko blokir tak terbatas), dan menghapus tautan setiap berkas temp di semua jalur.
  • Korelasi tepercaya. Setiap worker harus mengembalikan tepat himpunan indeks yang ditugaskan kepadanya (tanpa indeks yang hilang, duplikat, atau asing); byte setiap hasil render di-hash ulang dan dicocokkan terhadap sha-256 yang dilaporkan worker, dan status apa pun selain rendered/failed gagal-keras. Kegagalan render per-manifes adalah hasil Failed per-unit; hanya kesalahan infrastruktural (exit non-nol, keluaran yang tak terbaca/rusak, timeout) yang menggagalkan-keras executor.

isAvailable() mensyaratkan baik berkas autoload maupun skrip worker ada. Batas non-positif atau timeout negatif memunculkan InvalidArgumentException.

final readonlyint<0, max> $index, RenderManifest $manifest, array<string, scalar> $variables. Korelasi dilakukan berdasarkan index, tidak pernah berdasarkan job id (job id tidak dijamin unik dalam satu batch).

NextPDF\Pro\Stream\Engine\CompletedRenderUnit

Bagian berjudul “NextPDF\Pro\Stream\Engine\CompletedRenderUnit”

final readonlyint $index (tidak tepercaya, divalidasi oleh mesin), EngineRenderResult $result.

NextPDF\Pro\Stream\Engine\EngineRenderResult

Bagian berjudul “NextPDF\Pro\Stream\Engine\EngineRenderResult”

final readonly. Field: jobId, EngineRenderStatus $status, ?string $bytes, ?string $sha256, int $pageCount, ?string $errorCode, ?string $errorMessage, array<non-empty-string, float> $timings. Factory: rendered(jobId, bytes, sha256, pageCount, timings = []), failed(jobId, errorCode, errorMessage), timedOut(jobId, errorMessage) (kode SPEC-ENGINE-TIMEOUT). isRendered() melaporkan status. Hasil yang ter-render membawa byte dan sebuah digest, tidak pernah lokasi yang sudah di-commit.

NextPDF\Pro\Stream\Engine\EngineRenderStatus

Bagian berjudul “NextPDF\Pro\Stream\Engine\EngineRenderStatus”

Enum berbasis string: Rendered, Failed, Timeout. isRetryable() bernilai true hanya untuk Timeout, sehingga pemanggil mengklasifikasikan timeout sebagai transien tanpa memeriksa ulang galatnya.

NextPDF\Pro\Stream\Commit\OutputCommitterInterface

Bagian berjudul “NextPDF\Pro\Stream\Commit\OutputCommitterInterface”
public function commit(
string $jobId,
OutputObjectKey $target,
string $bytes,
string $sha256,
bool $overwrite = false,
): CommitReceipt;

Publikasi exactly-once: atomik, idempoten (commit ulang yang identik secara byte tidak melakukan penulisan dan mengembalikan CommitReceipt dengan idempotentReuse = true — sebuah receipt baru, bukan yang asli; committedAt-nya adalah jam saat ini), tanpa clobber diam-diam, dan terperiksa integritasnya (committer menghitung ulang digest). Mode kegagalan: CommitIntegrityException (sha-256 yang dideklarasikan tidak cocok dengan byte), OutputCommitConflictException (byte yang berbeda pada key yang sudah terisi dengan overwrite = false), UnsupportedTargetException (skema target yang tidak didukung).

NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter

Bagian berjudul “NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter”

final readonly, mengimplementasikan OutputCommitterInterface, DurableCapability. __construct(string $rootDirectory, ?AtomicFileWriter $writer = null, ?ClockInterface $clock = null). Hanya melayani skema file; meresolusi setiap target di bawah satu root yang dikonfigurasi dan menulis melalui writer atomik (temp O_EXCL → fsync → rename satu-volume). Seluruh seksi kritis (termasuk pembuatan direktori-induk) berjalan di bawah flock eksklusif pada berkas kunci per-root yang disimpan di luar keyspace keluaran, dan commit bersifat fail-closed jika kunci tidak dapat dibuka atau diperoleh. Ia menolak komponen final yang ber-symlink dan key apa pun yang mengandung titik dua (vektor NTFS alternate-data-stream). Exactly-once konkuren lintas-host ke key yang sama membutuhkan committer Enterprise yang durable. Root yang merupakan atau memuat direktori temp sistem memunculkan InvalidArgumentException.

final readonlyjobId, OutputObjectKey $target, sha256, int<0, max> $bytesWritten, bool $idempotentReuse, DateTimeImmutable $committedAt. toArray() / fromArray() sepenuhnya dapat di-round-trip (target bersifat terstruktur, bukan URI yang lossy); fromArray() bersifat ketat dan memunculkan InvalidArgumentException pada field yang hilang atau cacat.

NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface

Bagian berjudul “NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface”

load(string $runId): ?RunCheckpoint dan save(RunCheckpoint $checkpoint): void (durable dan atomik — pembaca tidak pernah melihat checkpoint yang setengah-tertulis).

final readonlyrunId, int<0, max> $committedOffset, array $keyedState, DateTimeImmutable $updatedAt; SCHEMA_VERSION = '1.0'. Factory start(runId, at) dan advancedTo(committedOffset, keyedState, at). toArray()/toJson()/fromArray()/fromJson() menserialisasikannya; fromArray() mensyaratkan run id yang tidak kosong dan updated_at yang valid, menolak schema_version yang tidak kompatibel (non-1.x), dan menormalkan keyed state dengan membuang nilai apa pun yang tidak dapat diserialisasi-JSON di setiap kedalaman sehingga state yang dipulihkan selalu dapat diserialisasi ulang. Pada pemulihan, prosesor mempercepat-maju melewati committedOffset dan memulihkan keyed state; state yang dimutasi setelah barrier terakhir dihitung-ulang ke depan, tidak pernah sebuah galat, karena exactly-once durable berasal dari dedup digest milik committer.

NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore

Bagian berjudul “NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore”

final readonly, mengimplementasikan CheckpointStoreInterface, DurableCapability. Satu berkas JSON per run, ditulis secara atomik. Run id harus cocok dengan [A-Za-z0-9._-]+ dan tidak mengandung ..; direktori yang tidak ada memunculkan InvalidArgumentException.

NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface

Bagian berjudul “NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface”

isCommitted(IdempotencyKey $key): bool, markCommitted(IdempotencyKey $key, CommitReceipt $receipt): void, receiptFor(IdempotencyKey $key): ?CommitReceipt. Jalur cepat yang melakukan short-circuit sebelum me-render sebuah replay; perbandingan digest milik committer tetap menjadi jaminan durable, sehingga rekaman yang hilang paling buruk hanya menyia-nyiakan render ulang yang didedup oleh committer.

  • InMemoryIdempotencyStore — cakupan single-run / pengujian (hilang saat crash).
  • FilesystemIdempotencyStoreDurableCapability; satu berkas JSON atomik per key yang sudah di-commit (receipt terserialisasi), dinamai berdasarkan hash dari nilai key. Tanda bersifat idempoten; re-mark konkuren berlomba tanpa bahaya pada satu berkas. Direktori yang tidak ada memunculkan InvalidArgumentException.

final readonlypositive-int $maxAttempts, positive-int $baseDelayMs, positive-int $maxDelayMs. __construct(int $maxAttempts = 3, int $baseDelayMs = 100, int $maxDelayMs = 30000) dengan invarian maxAttempts >= 1 dan 1 <= baseDelayMs <= maxDelayMs <= 7 days (jika tidak, InvalidArgumentException). Factory default() dan none() (satu upaya). shouldRetry(int $attempt): bool. delayMsForAttempt(int $attempt): int<0, max> adalah exponential backoff deterministik baseDelayMs * 2^(attempt-1) dibatasi pada maxDelayMs (tanpa jitter bawaan; terapkan di sisi pemanggil).

NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface

Bagian berjudul “NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface”

add(DeadLetterRecord $record): void, all(): list<DeadLetterRecord>, count(): int<0, max>.

final readonlyjobId, idempotencyKeyValue, positive-int $attempts, lastErrorCode, lastErrorMessage, DateTimeImmutable $failedAt, opsional ?string $runId, opsional int<1, max> $sourceOffset. dedupKey() adalah runId:sourceOffset ketika keduanya diketahui, jika tidak nilai idempotency key. fromArray() mem-parsing failed_at secara ketat sebagai ATOM (menolak ekspresi relatif atau non-ATOM) sehingga serialise/deserialise tetap simetris.

  • InMemoryDeadLetterStore — cakupan single-run / pengujian.
  • FilesystemDeadLetterStoreDurableCapability; satu berkas JSON atomik per rekaman, dinamai berdasarkan hash SHA-256 dari dedup key (….dlq.json), sehingga menambahkan item yang sama kembali saat resume bersifat idempoten. all() membaca rekaman dalam urutan deterministik (tersortir) dan memunculkan rekaman yang korup dengan melempar; count() adalah penghitungan berkas yang murah, bukan pemeriksaan validitas.

NextPDF\Pro\Stream\State\KeyedStateStoreInterface

Bagian berjudul “NextPDF\Pro\Stream\State\KeyedStateStoreInterface”

has, get, put, remove, clear, ditambah snapshot(): array dan restore(array $snapshot): void untuk batas checkpoint. Nilai harus dapat diserialisasi-JSON. Untuk workload render-and-commit baku, tidak ada keyed state yang digunakan; ia ada untuk ekstensi agregasi/windowing. InMemoryKeyedStateStore adalah implementasi single-run; kehilangannya saat pemulihan adalah no-op semantik untuk workload baku karena exactly-once berasal dari dedup digest milik committer.

final readonly, __construct(string $tenantField = 'tenant_id', string $documentField = 'document_id'). keyFor(RenderManifest $manifest): non-empty-string menurunkan partition key dari metadata manifes sebagai rawurlencode(tenant):rawurlencode(document) (encoding ini mencegah ("a:b","c") bertabrakan dengan ("a","b:c")), beralih ke job id ketika salah satu field tidak ada — sehingga setiap manifes resolusi ke key yang stabil dan tidak kosong.

NextPDF\Pro\Stream\DurableCapability adalah marker interface untuk store/committer apa pun yang state-nya bertahan melewati restart proses. Run yang crash-safe mensyaratkan setiap kolaborator mengimplementasikannya, sehingga ia gagal cepat alih-alih menjanjikan exactly-once yang tidak dapat dipertahankan oleh store in-memory.

Semua eksepsi subsistem mengimplementasikan NextPDF\Pro\Stream\Exception\StreamException (memperluas Throwable), sehingga pemanggil dapat melakukan catch (StreamException) secara seragam:

  • RenderEngineException (RuntimeException) — executor melanggar kontrak batch (unit yang tidak dikenal, duplikat, atau hilang; kesalahan worker; timeout).
  • CommitIntegrityException (RuntimeException) — sha-256 yang dideklarasikan tidak cocok dengan payload; kode spec SPEC-COMMIT-422.
  • OutputCommitConflictException (RuntimeException) — byte yang berbeda pada key yang sudah terisi dengan overwrite dimatikan; kode spec SPEC-COMMIT-409 (diekspos melalui specCode()).
  • UnsupportedTargetException (InvalidArgumentException) — skema target yang tidak dapat dilayani committer.

Mesin memvalidasi manifes terhadap model manifes Core dan menghasilkan byte deterministik ditambah digest sha-256; committer menegakkan penulisan yang atomik, terperiksa integritasnya, dan exactly-once. Modul tidak melakukan operasi kriptografis di luar digest konten sha-256 dan tidak mendefinisikan perilaku spesifik-FIPS.

  • renderBatch() tidak pernah membatalkan pada kegagalan per-manifes; periksa setiap EngineRenderResult.
  • ProcessPoolRenderUnitExecutor mengorelasikan secara ketat berdasarkan indeks dan me-hash ulang byte worker; worker yang bermasalah gagal-keras alih-alih merusak keluaran.
  • LocalFilesystemCommitter bersifat satu-host; exactly-once lintas-host membutuhkan committer Enterprise yang durable.
  • Run yang crash-safe harus menggunakan store DurableCapability (filesystem) secara menyeluruh, bukan varian in-memory.

Halaman ini mendokumentasikan hanya perilaku yang teramati secara eksternal dan permukaan API publik yang didukung. Jalur namespace internal, kelas helper, tabel mekanisme, nama berkas runbook, dan prefiks tiket berada di luar cakupan.