Pro phiên bản
Stream — Tài liệu tham chiếu chuyên sâu
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Trang này ghi lại các hợp đồng công khai, các lớp, các phương thức, và các chế độ thất bại của subsystem NextPDF\Pro\Stream vượt ngoài trang giới thiệu. Mọi kiểu bên dưới đều là một phần của bề mặt công khai Pro đã được ghi tài liệu.
Tính khả dụng & cấp phép
Phần tiêu đề “Tính khả dụng & cấp phép”Năng lực này xuất xưởng trong NextPDF Pro (nextpdf/pro) và kích hoạt bằng một license envelope cấp Pro. Một triển khai không có quyền đó sẽ không nạp các lớp của năng lực này. So sánh các phiên bản và lấy giấy phép.
Không có cờ giấy phép riêng theo từng tính năng; mã xuất xưởng cùng phiên bản Pro. Số lượng worker, kích thước batch, ngân sách thử lại, và backend kho là các tham số lúc chạy.
Kiến trúc: đường nối engine được đóng băng
Phần tiêu đề “Kiến trúc: đường nối engine được đóng băng”NextPDF\Pro\Stream\Engine\RenderEngineInterface là hợp đồng giữa engine thông lượng và bộ xử lý luồng document-job. Engine hiện thực hóa nó (sở hữu mức đồng thời, vòng đời worker-pool, backpressure, bộ nhớ có giới hạn); bộ xử lý luồng tiêu thụ nó (sở hữu trạng thái có-khóa, dedup, thử lại, checkpoint, và commit chính-xác-một-lần). Engine trả về byte cộng với sha-256, không bao giờ là một vị trí đã commit — chính sự tự-do-tác-dụng-phụ đó là thứ để cho bộ xử lý dàn dựng (stage), commit, và checkpoint đúng một lần.
public function renderBatch(array $manifests, array $variablesByJobId = []): array; // list<EngineRenderResult>, input orderpublic function maxBatchSize(): int; // int<1, max> backpressure hintpublic function isAvailable(): bool;$manifests là một list<RenderManifest> có kích thước tối đa maxBatchSize(); $variablesByJobId ánh xạ job id tới các biến template array<string, scalar>. Một thất bại theo từng manifest là một kết quả Failed/Timeout theo từng item và không bao giờ hủy bỏ batch.
Các engine
Phần tiêu đề “Các engine”NextPDF\Pro\Stream\Engine\InProcessRenderEngine
Phần tiêu đề “NextPDF\Pro\Stream\Engine\InProcessRenderEngine”Baseline đồng bộ, đơn-tiến-trình. Xác thực mỗi manifest theo lối fail-closed qua RenderManifestValidator (giới hạn inline-payload 16 MiB, các allow-list về conformance/chữ ký, định dạng content-hash sha-256, cú pháp locale BCP-47) trước khi kết xuất qua SingleDocumentRenderer của Core. Một lỗi xác thực chặn-luồng sẽ đoản mạch tới EngineRenderResult::failed(jobId, 'SPEC-MANIFEST-INVALID', ...); một ngoại lệ kết xuất trở thành 'SPEC-RENDER-EXCEPTION'. Constructor: __construct(SingleDocumentRenderer $renderer, int $maxBatchSize = 64, ?RenderManifestValidator $validator = null) — maxBatchSize < 1 ném InvalidArgumentException. isAvailable() luôn là true.
NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine
Phần tiêu đề “NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine”final readonly, __construct(RenderUnitExecutorInterface $executor). Bọc mỗi manifest trong một RenderUnit có chỉ số, chạy chúng qua executor, và sắp xếp lại các lần hoàn tất theo chỉ số nên đầu ra là byte-identical với một lượt kết xuất tuần tự. Một chỉ số hoàn tất nằm ngoài [0, count) ném RenderEngineException::unknownUnit(); một chỉ số lặp lại ném duplicateResult(); một chỉ số bị thiếu ném missingResult(). maxBatchSize() và isAvailable() ủy quyền cho executor.
Các executor
Phần tiêu đề “Các executor”NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface
Phần tiêu đề “NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface”public function execute(array $units): iterable; // iterable<CompletedRenderUnit>, any orderpublic function maxBatchSize(): int;public function isAvailable(): bool;Các hiện thực có thể yield các lần hoàn tất theo bất kỳ thứ tự nào; ConcurrentRenderEngine khôi phục thứ tự theo chỉ số.
NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor
Phần tiêu đề “NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor”final readonly, __construct(RenderEngineInterface $inner). Kết xuất mỗi unit theo thứ tự qua engine bên trong — tham chiếu đúng-đắn tất định mà một executor song song phải khớp từng-byte-một. Không có thời gian, tiến trình, luồng, hay tính ngẫu nhiên.
NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor
Phần tiêu đề “NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor”final readonly. Phân phối một batch trên tối đa maxWorkers tiến trình con worker php (mỗi cái một chunk) vốn kết xuất song song; đầu ra là byte-identical với baseline inline. Constructor:
__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)Hợp đồng độ bền vững:
- Không deadlock, an toàn trên Windows. Payload và kết quả của unit di chuyển qua các tệp tạm, không qua pipe; tiến trình cha thăm dò
proc_get_status()và chỉ rút cạn một pipe tới EOF sau khi một worker đã thoát, nên một worker không thể làm kẹt tiến trình cha. - Chờ có giới hạn.
timeoutSecondsgiới hạn toàn bộ lượt kết xuất song song; khi hết hạn, mọi worker còn đang chạy đều bị kết thúc và mộtRenderEngineExceptionđược ném ra. - Vệ sinh tài nguyên. Một
finallyđóng các pipe, thực hiện một nỗ lực terminate-and-reap có giới hạn trên các worker còn sống (terminate êm ái → force-kill → reap; một tiến trình con không được quan sát thấy dừng trong khoảng grace có giới hạn sẽ bị bỏ rơi thay vì mạo hiểm một lần chặn vô thời hạn), và unlink mọi tệp tạm trên mọi đường đi. - Tương quan đáng tin. Mỗi worker phải trả về đúng tập chỉ số được giao cho nó (không thiếu, không trùng lặp, không ngoại lai); các byte của mỗi kết quả đã kết xuất được băm lại và đối chiếu với sha-256 mà worker báo cáo, và bất kỳ trạng thái nào khác
rendered/failedđều thất bại cứng. Một thất bại kết xuất theo từng manifest là một kết quảFailedtheo từng unit; chỉ một lỗi hạ tầng (exit khác không, đầu ra không đọc được/bị nhiễu, timeout) mới làm thất bại cứng executor.
isAvailable() đòi hỏi cả tệp autoload lẫn worker script đều tồn tại. Một giới hạn không-dương hoặc timeout âm sẽ ném InvalidArgumentException.
Render unit và kết quả
Phần tiêu đề “Render unit và kết quả”NextPDF\Pro\Stream\Engine\RenderUnit
Phần tiêu đề “NextPDF\Pro\Stream\Engine\RenderUnit”final readonly — int<0, max> $index, RenderManifest $manifest, array<string, scalar> $variables. Tương quan là theo index, không bao giờ theo job id (job id không được đảm bảo là duy nhất trong một batch).
NextPDF\Pro\Stream\Engine\CompletedRenderUnit
Phần tiêu đề “NextPDF\Pro\Stream\Engine\CompletedRenderUnit”final readonly — int $index (không đáng tin, được engine xác thực), EngineRenderResult $result.
NextPDF\Pro\Stream\Engine\EngineRenderResult
Phần tiêu đề “NextPDF\Pro\Stream\Engine\EngineRenderResult”final readonly. Các trường: jobId, EngineRenderStatus $status, ?string $bytes, ?string $sha256, int $pageCount, ?string $errorCode, ?string $errorMessage, array<non-empty-string, float> $timings. Các factory: rendered(jobId, bytes, sha256, pageCount, timings = []), failed(jobId, errorCode, errorMessage), timedOut(jobId, errorMessage) (mã SPEC-ENGINE-TIMEOUT). isRendered() báo cáo trạng thái. Một kết quả đã kết xuất mang theo byte và một digest, không bao giờ là một vị trí đã commit.
NextPDF\Pro\Stream\Engine\EngineRenderStatus
Phần tiêu đề “NextPDF\Pro\Stream\Engine\EngineRenderStatus”Enum được hậu thuẫn bởi chuỗi: Rendered, Failed, Timeout. isRetryable() là true chỉ với Timeout, nên bên gọi phân loại một timeout là thoáng qua mà không cần soi lại error.
Commit
Phần tiêu đề “Commit”NextPDF\Pro\Stream\Commit\OutputCommitterInterface
Phần tiêu đề “NextPDF\Pro\Stream\Commit\OutputCommitterInterface”public function commit( string $jobId, OutputObjectKey $target, string $bytes, string $sha256, bool $overwrite = false,): CommitReceipt;Xuất bản chính-xác-một-lần: nguyên tử, idempotent (commit lại byte-identical không thực hiện ghi nào và trả về một CommitReceipt với idempotentReuse = true — một receipt mới, không phải bản gốc; committedAt của nó là đồng hồ hiện tại), không ghi đè âm thầm, và được kiểm tra toàn vẹn (committer tính lại digest). Các chế độ thất bại: CommitIntegrityException (sha-256 được khai báo không khớp các byte), OutputCommitConflictException (các byte phân kỳ tại một key đã bị chiếm với overwrite = false), UnsupportedTargetException (scheme đích không được hỗ trợ).
NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter
Phần tiêu đề “NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter”final readonly, hiện thực OutputCommitterInterface, DurableCapability. __construct(string $rootDirectory, ?AtomicFileWriter $writer = null, ?ClockInterface $clock = null). Chỉ phục vụ scheme file; phân giải mọi đích dưới một root được cấu hình và ghi qua một atomic writer (temp O_EXCL → fsync → rename cùng-volume). Toàn bộ vùng tới hạn (bao gồm việc tạo thư mục cha) chạy dưới một flock độc quyền trên một tệp khóa theo từng-root được giữ bên ngoài không gian key đầu ra, và commit là fail-closed nếu khóa không mở được hoặc không giành được. Nó từ chối các thành phần cuối là symlink và bất kỳ key nào chứa một dấu hai chấm (vector luồng-dữ-liệu-thay-thế NTFS). Chính-xác-một-lần đồng thời liên-host tới cùng một key đòi hỏi committer bền bỉ của Enterprise. Một root vốn là hoặc chứa thư mục tạm hệ thống sẽ ném InvalidArgumentException.
NextPDF\Pro\Stream\Commit\CommitReceipt
Phần tiêu đề “NextPDF\Pro\Stream\Commit\CommitReceipt”final readonly — jobId, OutputObjectKey $target, sha256, int<0, max> $bytesWritten, bool $idempotentReuse, DateTimeImmutable $committedAt. toArray() / fromArray() hoàn toàn có thể khứ hồi (đích có cấu trúc, không phải một URI có mất mát); fromArray() là nghiêm ngặt và ném InvalidArgumentException khi các trường bị thiếu hoặc dị dạng.
Checkpoint
Phần tiêu đề “Checkpoint”NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface
Phần tiêu đề “NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface”load(string $runId): ?RunCheckpoint và save(RunCheckpoint $checkpoint): void (bền bỉ và nguyên tử — một bên đọc không bao giờ thấy một checkpoint ghi dở).
NextPDF\Pro\Stream\Checkpoint\RunCheckpoint
Phần tiêu đề “NextPDF\Pro\Stream\Checkpoint\RunCheckpoint”final readonly — runId, int<0, max> $committedOffset, array $keyedState, DateTimeImmutable $updatedAt; SCHEMA_VERSION = '1.0'. Các factory start(runId, at) và advancedTo(committedOffset, keyedState, at). toArray()/toJson()/fromArray()/fromJson() tuần tự hóa nó; fromArray() đòi hỏi một run id không-rỗng và một updated_at hợp lệ, từ chối một schema_version không tương thích (không phải 1.x), và chuẩn hóa trạng thái có-khóa bằng cách loại bỏ mọi giá trị không-thể-tuần-tự-hóa-JSON ở mọi độ sâu nên trạng thái đã phục hồi luôn có thể được tuần tự hóa lại. Khi phục hồi, processor tua nhanh qua committedOffset và khôi phục trạng thái có-khóa; trạng thái bị biến đổi sau rào cản cuối cùng được tính lại tiến tới, không bao giờ là một lỗi, vì chính-xác-một-lần bền bỉ đến từ việc khử trùng lặp digest của committer.
NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore
Phần tiêu đề “NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore”final readonly, hiện thực CheckpointStoreInterface, DurableCapability. Một tệp JSON cho mỗi lượt chạy, được ghi một cách nguyên tử. Các run id phải khớp [A-Za-z0-9._-]+ và không chứa ..; một thư mục không tồn tại sẽ ném InvalidArgumentException.
Khử trùng lặp idempotency
Phần tiêu đề “Khử trùng lặp idempotency”NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface
Phần tiêu đề “NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface”isCommitted(IdempotencyKey $key): bool, markCommitted(IdempotencyKey $key, CommitReceipt $receipt): void, receiptFor(IdempotencyKey $key): ?CommitReceipt. Đường đi nhanh vốn đoản mạch trước khi kết xuất một lần phát lại; phép so sánh digest của committer vẫn là đảm bảo bền bỉ, nên một bản ghi bị mất tệ nhất chỉ lãng phí một lần kết xuất lại mà committer khử trùng lặp.
InMemoryIdempotencyStore— phạm vi đơn-lượt-chạy / test (mất khi có sự cố).FilesystemIdempotencyStore—DurableCapability; một tệp JSON nguyên tử cho mỗi key đã commit (receipt được tuần tự hóa), đặt tên theo một hash của giá trị key. Các mark là idempotent; một lần đánh-dấu-lại đồng thời chạy đua vô hại trên một tệp. Một thư mục không tồn tại sẽ némInvalidArgumentException.
Thử lại và dead-letter
Phần tiêu đề “Thử lại và dead-letter”NextPDF\Pro\Stream\Retry\RetryPolicy
Phần tiêu đề “NextPDF\Pro\Stream\Retry\RetryPolicy”final readonly — positive-int $maxAttempts, positive-int $baseDelayMs, positive-int $maxDelayMs. __construct(int $maxAttempts = 3, int $baseDelayMs = 100, int $maxDelayMs = 30000) với các bất biến maxAttempts >= 1 và 1 <= baseDelayMs <= maxDelayMs <= 7 days (nếu không thì InvalidArgumentException). Các factory default() và none() (một lần thử duy nhất). shouldRetry(int $attempt): bool. delayMsForAttempt(int $attempt): int<0, max> là backoff hàm mũ tất định baseDelayMs * 2^(attempt-1) được giới hạn ở maxDelayMs (không có jitter dựng sẵn; hãy áp dụng tại điểm gọi).
NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface
Phần tiêu đề “NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface”add(DeadLetterRecord $record): void, all(): list<DeadLetterRecord>, count(): int<0, max>.
NextPDF\Pro\Stream\Retry\DeadLetterRecord
Phần tiêu đề “NextPDF\Pro\Stream\Retry\DeadLetterRecord”final readonly — jobId, idempotencyKeyValue, positive-int $attempts, lastErrorCode, lastErrorMessage, DateTimeImmutable $failedAt, tùy chọn ?string $runId, tùy chọn int<1, max> $sourceOffset. dedupKey() là runId:sourceOffset khi cả hai đã biết, ngược lại là giá trị idempotency key. fromArray() phân tích failed_at một cách nghiêm ngặt theo ATOM (từ chối các biểu thức tương đối hoặc không-phải-ATOM) nên việc tuần-tự-hóa/giải-tuần-tự-hóa vẫn đối xứng.
InMemoryDeadLetterStore— phạm vi đơn-lượt-chạy / test.FilesystemDeadLetterStore—DurableCapability; một tệp JSON nguyên tử cho mỗi bản ghi, đặt tên theo một hash SHA-256 của dedup key (….dlq.json), nên việc thêm-lại cùng một item khi tiếp tục là idempotent.all()đọc các bản ghi theo thứ tự tất định (đã sắp xếp) và phơi bày một bản ghi hỏng bằng cách ném lỗi;count()là một phép đếm tệp rẻ tiền, không phải một phép kiểm tra tính hợp lệ.
Trạng thái có-khóa
Phần tiêu đề “Trạng thái có-khóa”NextPDF\Pro\Stream\State\KeyedStateStoreInterface
Phần tiêu đề “NextPDF\Pro\Stream\State\KeyedStateStoreInterface”has, get, put, remove, clear, cộng với snapshot(): array và restore(array $snapshot): void cho ranh giới checkpoint. Các giá trị phải có thể tuần tự hóa JSON. Với khối lượng công việc render-and-commit mặc định, không có trạng thái có-khóa nào được dùng; nó tồn tại cho các phần mở rộng aggregation/windowing. InMemoryKeyedStateStore là hiện thực đơn-lượt-chạy; việc mất nó khi phục hồi là một no-op về mặt ngữ nghĩa cho khối lượng công việc mặc định vì chính-xác-một-lần đến từ việc khử trùng lặp digest của committer.
NextPDF\Pro\Stream\State\KeySelector
Phần tiêu đề “NextPDF\Pro\Stream\State\KeySelector”final readonly, __construct(string $tenantField = 'tenant_id', string $documentField = 'document_id'). keyFor(RenderManifest $manifest): non-empty-string suy ra key phân vùng từ metadata của manifest dưới dạng rawurlencode(tenant):rawurlencode(document) (việc mã hóa ngăn ("a:b","c") va chạm với ("a","b:c")), lùi về job id khi một trong hai trường vắng mặt — nên mỗi manifest phân giải tới một key ổn định, không-rỗng.
Dấu hiệu bền bỉ và các ngoại lệ
Phần tiêu đề “Dấu hiệu bền bỉ và các ngoại lệ”NextPDF\Pro\Stream\DurableCapability là một interface đánh dấu cho bất kỳ store/committer nào có trạng thái sống sót qua một lần khởi động lại tiến trình. Một lượt chạy an toàn trước sự cố đòi hỏi mọi cộng tác viên đều hiện thực nó, nên nó thất bại nhanh thay vì hứa hẹn chính-xác-một-lần mà một kho in-memory không thể giữ.
Mọi ngoại lệ của subsystem đều hiện thực NextPDF\Pro\Stream\Exception\StreamException (mở rộng Throwable), nên một bên gọi có thể catch (StreamException) một cách đồng nhất:
RenderEngineException(RuntimeException) — executor vi phạm hợp đồng batch (unit không xác định, trùng lặp, hoặc bị thiếu; lỗi worker; timeout).CommitIntegrityException(RuntimeException) — sha-256 được khai báo không khớp payload; mã specSPEC-COMMIT-422.OutputCommitConflictException(RuntimeException) — các byte phân kỳ tại một key đã bị chiếm với overwrite bị tắt; mã specSPEC-COMMIT-409(phơi bày quaspecCode()).UnsupportedTargetException(InvalidArgumentException) — scheme đích mà một committer không thể phục vụ.
Tính phù hợp
Phần tiêu đề “Tính phù hợp”Engine xác thực các manifest theo mô hình manifest của Core và tạo ra các byte tất định cộng với các digest sha-256; committer thực thi các lần ghi nguyên tử, được kiểm tra toàn vẹn, chính-xác-một-lần. Module không thực hiện thao tác mã hóa nào ngoài các content digest sha-256 và không định nghĩa hành vi đặc thù FIPS nào.
Trường hợp ngoại lệ & lưu ý
Phần tiêu đề “Trường hợp ngoại lệ & lưu ý”renderBatch()không bao giờ hủy bỏ khi một manifest thất bại; hãy soi từngEngineRenderResult.ProcessPoolRenderUnitExecutortương quan nghiêm ngặt theo chỉ số và băm lại các byte của worker; một worker lỗi sẽ thất bại cứng thay vì làm hỏng đầu ra.LocalFilesystemCommitterlà đơn-host; chính-xác-một-lần liên-host cần committer bền bỉ của Enterprise.- Các lượt chạy an toàn trước sự cố phải dùng các kho
DurableCapability(filesystem) xuyên suốt, không phải các biến thể in-memory.
Ranh giới xuất bản
Phần tiêu đề “Ranh giới xuất bản”Trang này chỉ ghi lại hành vi có thể quan sát từ bên ngoài và bề mặt API công khai được hỗ trợ. Các đường dẫn namespace nội bộ, các lớp trợ giúp, các bảng cơ chế, các tên tệp runbook, và các tiền tố ticket đều nằm ngoài phạm vi.