Pro الإصدار
Stream — مرجع متعمّق
لمحة سريعة
قسم بعنوان «لمحة سريعة»توثّق هذه الصفحة العقود العامة، والأصناف، والطرائق، وأنماط الفشل لنظام NextPDF\Pro\Stream الفرعي على نحو يتجاوز صفحة النظرة العامة. وكلُّ نوع أدناه جزء من سطح Pro العام المُوثَّق.
التوفّر والترخيص
قسم بعنوان «التوفّر والترخيص»تُشحَن هذه القدرة في NextPDF Pro (nextpdf/pro) وتُفعَّل بمظروف ترخيص من فئة Pro. ولا يُحمِّل نشرٌ يفتقر إلى ذلك الاستحقاق أصنافَ هذه القدرة. قارِن الإصدارات واحصل على ترخيص.
لا تنطبق أي علامة ترخيص لكل ميزة؛ فالشيفرة تُشحَن مع إصدار Pro. وعدد العمّال، وحجم الدفعة، وميزانية إعادة المحاولة، والخلفية التخزينية للمخزن معامِلات وقت تشغيل.
المعمارية: وصلة المحرّك المُجمَّدة
قسم بعنوان «المعمارية: وصلة المحرّك المُجمَّدة»NextPDF\Pro\Stream\Engine\RenderEngineInterface هي العقد بين محرّك الإنتاجية ومُعالِج تدفّق مهامّ المستندات. ويُنفِّذها المحرّك (مالكًا التزامنَ، ودورةَ حياة مجمَّع العمّال، والضغط الراجع، والذاكرةَ المحدودة)؛ ويستهلكها مُعالِج التدفّق (مالكًا الحالةَ المُفتَّحة، وإزالة التكرار، وإعادة المحاولة، ونقطة التفتيش، والالتزام مرّة واحدة بالضبط). ويُرجِع المحرّك بايتات مع sha-256، ولا يُرجِع موقعًا ملتزَمًا به أبدًا — وحرّيّة الآثار الجانبية تلك هي ما يتيح للمُعالِج التحضيرَ، والالتزام، والتفتيش مرّة واحدة بالضبط.
public function renderBatch(array $manifests, array $variablesByJobId = []): array; // list<EngineRenderResult>, input orderpublic function maxBatchSize(): int; // int<1, max> backpressure hintpublic function isAvailable(): bool;$manifests هو list<RenderManifest> بحجم لا يتجاوز maxBatchSize()؛ ويُسنِد $variablesByJobId معرّف المهمّة إلى متغيّرات قالب array<string, scalar>. وفشلٌ لكل بيانات وصفية هو نتيجة Failed/Timeout لكل عنصر ولا يُجهِض الدفعة أبدًا.
المحرّكات
قسم بعنوان «المحرّكات»NextPDF\Pro\Stream\Engine\InProcessRenderEngine
قسم بعنوان «NextPDF\Pro\Stream\Engine\InProcessRenderEngine»خطّ مرجعي متزامن أحادي العملية. يتحقّق من كلّ بيانات وصفية تحقُّقًا مُغلَقًا بأمان عبر RenderManifestValidator (سقف حمولة سطرية 16 MiB، وقوائم سماح للمطابقة/التوقيع، وصيغة بصمة محتوى sha-256، وبنية لغة BCP-47) قبل التصيير عبر SingleDocumentRenderer في Core. ويختصر خطأُ تحقُّقٍ حاجبٌ الدائرةَ إلى EngineRenderResult::failed(jobId, 'SPEC-MANIFEST-INVALID', ...)؛ ويصير استثناء التصيير 'SPEC-RENDER-EXCEPTION'. البنّاء: __construct(SingleDocumentRenderer $renderer, int $maxBatchSize = 64, ?RenderManifestValidator $validator = null) — يرمي maxBatchSize < 1 استثناء InvalidArgumentException. وisAvailable() دائمًا true.
NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine
قسم بعنوان «NextPDF\Pro\Stream\Engine\ConcurrentRenderEngine»final readonly، __construct(RenderUnitExecutorInterface $executor). يلفّ كلَّ بيانات وصفية في RenderUnit مُفهرَسة، ويُمرّرها عبر المُنفِّذ، ويعيد فرز الإكمالات بحسب الفهرس فيكون المخرَج متطابقًا بايتيًا مع تصيير متسلسل. وفهرس إكمال خارج [0, count) يرمي RenderEngineException::unknownUnit()؛ وفهرس مكرَّر يرمي duplicateResult()؛ وفهرس مفقود يرمي missingResult(). ويفوِّض maxBatchSize() وisAvailable() إلى المُنفِّذ.
المُنفِّذات
قسم بعنوان «المُنفِّذات»NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface
قسم بعنوان «NextPDF\Pro\Stream\Engine\RenderUnitExecutorInterface»public function execute(array $units): iterable; // iterable<CompletedRenderUnit>, any orderpublic function maxBatchSize(): int;public function isAvailable(): bool;قد تُنتِج التنفيذات الإكمالات بأي ترتيب؛ ويستعيد ConcurrentRenderEngine الترتيبَ بحسب الفهرس.
NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor
قسم بعنوان «NextPDF\Pro\Stream\Engine\InlineRenderUnitExecutor»final readonly، __construct(RenderEngineInterface $inner). يُصيِّر كلَّ وحدة بالترتيب عبر المحرّك الداخلي — المرجع الحتمي للصحّة الذي يجب أن يطابقه مُنفِّذ موازٍ بايتًا ببايت. لا وقت، ولا عمليات، ولا خيوط، ولا عشوائية.
NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor
قسم بعنوان «NextPDF\Pro\Stream\Engine\ProcessPoolRenderUnitExecutor»final readonly. يُوزِّع دفعةً على عدد يصل إلى maxWorkers من العمليات الفرعية العاملة php (شريحة لكلّ واحدة) التي تُصيِّر بالتوازي؛ والمخرَج متطابق بايتيًا مع الخطّ المرجعي السطري. البنّاء:
__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)عقد المتانة:
- خالٍ من التجمّد، آمن على Windows. تنتقل حمولات الوحدات ونتائجها عبر ملفات مؤقّتة، لا عبر الأنابيب؛ ويستطلع الأبُ
proc_get_status()ولا يستنزف أنبوبًا حتى EOF إلّا بعد خروج العامل، فلا يستطيع عامل أن يُعلِّق الأبَ. - انتظار محدود. تحدّ
timeoutSecondsالتصييرَ الموازي بأكمله؛ وعند انتهاء المهلة يُنهَى كلُّ عامل ما زال يعمل ويُرمىRenderEngineException. - نظافة الموارد. يُغلِق
finallyالأنابيبَ، ويبذل محاولة إنهاء-وحصاد محدودة على العمّال الباقين (إنهاء لطيف ← قتل قسري ← حصاد؛ والطفل الذي لا يُلاحَظ توقّفه خلال المهلة المحدودة يُهجَر بدلًا من المخاطرة بحجب غير محدّد)، ويفكّ ارتباط كلِّ ملفّ مؤقّت على جميع المسارات. - ترابط موثوق. يجب أن يُرجِع كلُّ عامل مجموعة الفهارس المُسنَدة إليه بالضبط (من دون فهرس مفقود أو مكرَّر أو غريب)؛ وتُعاد بصمة بايتات كلِّ نتيجة مُصيَّرة ومطابقتها مع sha-256 التي يُبلِّغ بها العامل، وأيُّ حالة غير
rendered/failedتفشل فشلًا صارمًا. وفشلُ تصيير لكل بيانات وصفية هو نتيجةFailedلكل وحدة؛ ولا يفشل المُنفِّذُ فشلًا صارمًا إلّا بعيب بنيوي (خروج غير صفري، مخرَج غير قابل للقراءة/مُشوَّش، انتهاء مهلة).
يتطلّب isAvailable() وجودَ كلٍّ من ملفّ التحميل التلقائي وبرنامج العامل النصّي. وحدٌّ غير موجب أو مهلة سالبة يرمي InvalidArgumentException.
وحدات التصيير ونتائجها
قسم بعنوان «وحدات التصيير ونتائجها»NextPDF\Pro\Stream\Engine\RenderUnit
قسم بعنوان «NextPDF\Pro\Stream\Engine\RenderUnit»final readonly — int<0, max> $index، وRenderManifest $manifest، وarray<string, scalar> $variables. والترابط بحسب index، لا بحسب معرّف المهمّة أبدًا (معرّفات المهامّ ليست مضمونة الفرادة داخل دفعة).
NextPDF\Pro\Stream\Engine\CompletedRenderUnit
قسم بعنوان «NextPDF\Pro\Stream\Engine\CompletedRenderUnit»final readonly — int $index (غير موثوق، يتحقّق منه المحرّك)، وEngineRenderResult $result.
NextPDF\Pro\Stream\Engine\EngineRenderResult
قسم بعنوان «NextPDF\Pro\Stream\Engine\EngineRenderResult»final readonly. الحقول: jobId، وEngineRenderStatus $status، و?string $bytes، و?string $sha256، وint $pageCount، و?string $errorCode، و?string $errorMessage، وarray<non-empty-string, float> $timings. المصانع: rendered(jobId, bytes, sha256, pageCount, timings = [])، وfailed(jobId, errorCode, errorMessage)، وtimedOut(jobId, errorMessage) (الرمز SPEC-ENGINE-TIMEOUT). ويُبلِّغ isRendered() عن الحالة. وتحمل النتيجة المُصيَّرة بايتاتٍ وبصمةً، ولا تحمل موقعًا ملتزَمًا به أبدًا.
NextPDF\Pro\Stream\Engine\EngineRenderStatus
قسم بعنوان «NextPDF\Pro\Stream\Engine\EngineRenderStatus»تعداد مدعوم بسلسلة نصّية: Rendered، وFailed، وTimeout. وisRetryable() يكون true فقط لـTimeout، فيصنّف المُستدعي انتهاء المهلة كعابر من دون إعادة فحص الخطأ.
الالتزام
قسم بعنوان «الالتزام»NextPDF\Pro\Stream\Commit\OutputCommitterInterface
قسم بعنوان «NextPDF\Pro\Stream\Commit\OutputCommitterInterface»public function commit( string $jobId, OutputObjectKey $target, string $bytes, string $sha256, bool $overwrite = false,): CommitReceipt;نشر مرّة واحدة بالضبط: ذرّيّ، وبخاصية العدم التأثيرية (إعادة الالتزام المتطابقة بايتيًا لا تنفّذ أي كتابة وتُرجِع CommitReceipt بقيمة idempotentReuse = true — إيصال جديد، لا الأصلي؛ وcommittedAt الخاصّ به هو الساعة الحالية)، ومن دون طمس صامت، ومُتحقَّق من سلامته (يعيد المُلتزِم حساب البصمة). أنماط الفشل: CommitIntegrityException (لا تطابق sha-256 المعلنة البايتات)، وOutputCommitConflictException (بايتات متباعدة عند مفتاح مشغول مع overwrite = false)، وUnsupportedTargetException (مخطّط هدف غير مدعوم).
NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter
قسم بعنوان «NextPDF\Pro\Stream\Commit\LocalFilesystemCommitter»final readonly، يُنفِّذ OutputCommitterInterface, DurableCapability. __construct(string $rootDirectory, ?AtomicFileWriter $writer = null, ?ClockInterface $clock = null). يخدم مخطّط file فقط؛ ويحلّ كلَّ هدف تحت جذر واحد مُهيَّأ ويكتب عبر كاتب ذرّيّ (ملفّ مؤقّت O_EXCL ← fsync ← إعادة تسمية على المجلّد نفسه). ويعمل القسم الحرج بكامله (بما في ذلك إنشاء المجلّد الأب) تحت flock حصري على ملفّ قفل لكلّ جذر يُحفَظ خارج فضاء مفاتيح المخرَجات، ويكون الالتزام مُغلَقًا بأمان إن تعذّر فتح القفل أو الحصول عليه. ويرفض المكوّنات النهائية ذات الروابط الرمزية وأيَّ مفتاح يحتوي على نقطتين (متّجه تدفّق البيانات البديل في NTFS). والمرّة الواحدة بالضبط المتزامنة عبر مضيفين متعدّدين إلى المفتاح نفسه تتطلّب مُلتزِم Enterprise الدائم. وجذرٌ هو دليل النظام المؤقّت أو يحتويه يرمي InvalidArgumentException.
NextPDF\Pro\Stream\Commit\CommitReceipt
قسم بعنوان «NextPDF\Pro\Stream\Commit\CommitReceipt»final readonly — jobId، وOutputObjectKey $target، وsha256، وint<0, max> $bytesWritten، وbool $idempotentReuse، وDateTimeImmutable $committedAt. وtoArray() / fromArray() قابلان للالتفاف ذهابًا وإيابًا بالكامل (الهدف مُنظَّم، لا URI ضائع)؛ وfromArray() صارم ويرمي InvalidArgumentException على الحقول المفقودة أو المشوَّهة.
نقطة التفتيش
قسم بعنوان «نقطة التفتيش»NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface
قسم بعنوان «NextPDF\Pro\Stream\Checkpoint\CheckpointStoreInterface»load(string $runId): ?RunCheckpoint وsave(RunCheckpoint $checkpoint): void (دائم وذرّيّ — لا يرى قارئٌ أبدًا نقطة تفتيش مكتوبة نصفيًا).
NextPDF\Pro\Stream\Checkpoint\RunCheckpoint
قسم بعنوان «NextPDF\Pro\Stream\Checkpoint\RunCheckpoint»final readonly — runId، وint<0, max> $committedOffset، وarray $keyedState، وDateTimeImmutable $updatedAt؛ وSCHEMA_VERSION = '1.0'. المصانع start(runId, at) وadvancedTo(committedOffset, keyedState, at). وtoArray()/toJson()/fromArray()/fromJson() تُسلسِلها؛ ويتطلّب fromArray() معرّف تشغيل غير فارغ وupdated_at صالحًا، ويرفض schema_version غير المتوافق (غير 1.x)، ويُسوّي الحالة المُفتَّحة بإسقاط أي قيم غير قابلة للتسلسل بـJSON على كلّ عمق فتكون الحالة المُستعادة دائمًا قابلة لإعادة التسلسل. وعند الاستعادة يتقدّم المُعالِج سريعًا متجاوزًا committedOffset ويستعيد الحالة المُفتَّحة؛ والحالة المُعدَّلة بعد الحاجز الأخير يُعاد حسابها تقدُّمًا، لا تكون خطأً أبدًا، لأنّ المرّة الواحدة بالضبط الدائمة تأتي من إزالة تكرار بصمة المُلتزِم.
NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore
قسم بعنوان «NextPDF\Pro\Stream\Checkpoint\FilesystemCheckpointStore»final readonly، يُنفِّذ CheckpointStoreInterface, DurableCapability. ملفّ JSON واحد لكلّ تشغيل، يُكتَب ذرّيًّا. ويجب أن تطابق معرّفات التشغيل [A-Za-z0-9._-]+ وألّا تحتوي على ..؛ ودليل غير موجود يرمي InvalidArgumentException.
إزالة تكرار خاصية العدم التأثيرية
قسم بعنوان «إزالة تكرار خاصية العدم التأثيرية»NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface
قسم بعنوان «NextPDF\Pro\Stream\Dedup\IdempotencyStoreInterface»isCommitted(IdempotencyKey $key): bool، وmarkCommitted(IdempotencyKey $key, CommitReceipt $receipt): void، وreceiptFor(IdempotencyKey $key): ?CommitReceipt. المسار السريع الذي يختصر الدائرة قبل تصيير إعادة تشغيل؛ وتبقى مقارنة بصمة المُلتزِم هي الضمانة الدائمة، فيُهدِر فقدان سجلّ في أسوأ الأحوال إعادة تصيير يُزيل المُلتزِم تكرارها.
InMemoryIdempotencyStore— نطاق تشغيل واحد / اختبار (يُفقَد عند العطل).FilesystemIdempotencyStore—DurableCapability؛ ملفّ JSON ذرّيّ واحد لكلّ مفتاح ملتزَم به (الإيصال المُسلسَل)، مُسمّى ببصمة قيمة المفتاح. والعلامات ذات خاصية عدم تأثيرية؛ وإعادة وسم متزامنة تتسابق على ملفّ واحد بلا ضرر. ودليل غير موجود يرميInvalidArgumentException.
إعادة المحاولة والرسائل الميتة
قسم بعنوان «إعادة المحاولة والرسائل الميتة»NextPDF\Pro\Stream\Retry\RetryPolicy
قسم بعنوان «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) بثوابت maxAttempts >= 1 و1 <= baseDelayMs <= maxDelayMs <= 7 days (وإلّا InvalidArgumentException). المصانع default() وnone() (محاولة واحدة). وshouldRetry(int $attempt): bool. وdelayMsForAttempt(int $attempt): int<0, max> تراجع أُسّيّ حتميّ baseDelayMs * 2^(attempt-1) محدودًا عند maxDelayMs (لا اهتزاز مُدمَج؛ طبِّقه عند موقع الاستدعاء).
NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface
قسم بعنوان «NextPDF\Pro\Stream\Retry\DeadLetterStoreInterface»add(DeadLetterRecord $record): void، وall(): list<DeadLetterRecord>، وcount(): int<0, max>.
NextPDF\Pro\Stream\Retry\DeadLetterRecord
قسم بعنوان «NextPDF\Pro\Stream\Retry\DeadLetterRecord»final readonly — jobId، وidempotencyKeyValue، وpositive-int $attempts، وlastErrorCode، وlastErrorMessage، وDateTimeImmutable $failedAt، واختياريًا ?string $runId، واختياريًا int<1, max> $sourceOffset. وdedupKey() هو runId:sourceOffset حين يكون كلاهما معلومًا، وإلّا فقيمة مفتاح خاصية العدم التأثيرية. ويحلّل fromArray() القيمةَ failed_at بصرامة بصيغة ATOM (رافضًا التعابير النسبية أو غير ATOM) فيبقى التسلسل/فكّ التسلسل متناظرًا.
InMemoryDeadLetterStore— نطاق تشغيل واحد / اختبار.FilesystemDeadLetterStore—DurableCapability؛ ملفّ JSON ذرّيّ واحد لكلّ سجلّ، مُسمّى ببصمة SHA-256 لمفتاح إزالة التكرار (….dlq.json)، فتكون إعادة إضافة العنصر نفسه عند الاستئناف ذات خاصية عدم تأثيرية. ويقرأall()السجلّات بترتيب حتميّ (مفروز) ويُظهِر سجلًّا فاسدًا بالرمي؛ وcount()عدُّ ملفّات رخيص، لا فحص صلاحية.
الحالة المُفتَّحة
قسم بعنوان «الحالة المُفتَّحة»NextPDF\Pro\Stream\State\KeyedStateStoreInterface
قسم بعنوان «NextPDF\Pro\Stream\State\KeyedStateStoreInterface»has، وget، وput، وremove، وclear، إضافةً إلى snapshot(): array وrestore(array $snapshot): void لحدّ نقطة التفتيش. ويجب أن تكون القيم قابلة للتسلسل بـJSON. ولعبء عمل التصيير-والالتزام الافتراضي لا تُستخدَم أي حالة مُفتَّحة؛ فهي موجودة لامتدادات التجميع/التنويف. وInMemoryKeyedStateStore هو التنفيذ أحادي التشغيل؛ وفقدانه عند الاستعادة هو لا-عمل دلاليّ لعبء العمل الافتراضي لأنّ المرّة الواحدة بالضبط تأتي من إزالة تكرار بصمة المُلتزِم.
NextPDF\Pro\Stream\State\KeySelector
قسم بعنوان «NextPDF\Pro\Stream\State\KeySelector»final readonly، __construct(string $tenantField = 'tenant_id', string $documentField = 'document_id'). ويشتقّ keyFor(RenderManifest $manifest): non-empty-string مفتاحَ التقسيم من البيانات الوصفية للبيان الوصفي بصيغة rawurlencode(tenant):rawurlencode(document) (يمنع الترميزُ تصادمَ ("a:b","c") مع ("a","b:c"))، متراجعًا إلى معرّف المهمّة حين يغيب أيُّ حقل — فيحلّ كلُّ بيانات وصفية إلى مفتاح ثابت غير فارغ.
علامة الديمومة والاستثناءات
قسم بعنوان «علامة الديمومة والاستثناءات»NextPDF\Pro\Stream\DurableCapability هي واجهة علامة لأي مخزن/مُلتزِم تنجو حالته من إعادة تشغيل عملية. ويتطلّب التشغيل الآمن عند الأعطال أن يُنفِّذها كلُّ متعاون، فيفشل سريعًا بدلًا من الوعد بمرّة واحدة بالضبط لا يستطيع مخزن في الذاكرة الحفاظ عليها.
تُنفِّذ كلُّ استثناءات النظام الفرعي NextPDF\Pro\Stream\Exception\StreamException (تمدّد Throwable)، فيستطيع المُستدعي catch (StreamException) بصورة موحَّدة:
RenderEngineException(RuntimeException) — انتهك المُنفِّذُ عقدَ الدفعة (وحدة مجهولة أو مكرَّرة أو مفقودة؛ عيب عامل؛ انتهاء مهلة).CommitIntegrityException(RuntimeException) — لا تطابق sha-256 المعلنة الحمولةَ؛ رمز المواصفةSPEC-COMMIT-422.OutputCommitConflictException(RuntimeException) — بايتات متباعدة عند مفتاح مشغول مع تعطيل الكتابة فوقه؛ رمز المواصفةSPEC-COMMIT-409(مكشوف عبرspecCode()).UnsupportedTargetException(InvalidArgumentException) — مخطّط هدف لا يستطيع مُلتزِمٌ خدمته.
المطابقة
قسم بعنوان «المطابقة»يتحقّق المحرّك من البيانات الوصفية مقابل نموذج البيانات الوصفية في Core ويُنتِج بايتات حتمية مع بصمات sha-256؛ ويفرض المُلتزِم كتابات ذرّية ومُتحقَّقًا من سلامتها ومرّة واحدة بالضبط. ولا تؤدّي الوحدة أي عمليات تشفير تتجاوز بصمات محتوى sha-256 ولا تُعرِّف أي سلوك خاصّ بـFIPS.
الحالات الحدّية والمزالق
قسم بعنوان «الحالات الحدّية والمزالق»- لا يُجهِض
renderBatch()أبدًا على فشل لكل بيانات وصفية؛ افحص كلَّEngineRenderResult. - يترابط
ProcessPoolRenderUnitExecutorبصرامة بحسب الفهرس ويعيد بصمة بايتات العامل؛ وعامل معيب يفشل فشلًا صارمًا بدلًا من إفساد المخرَج. LocalFilesystemCommitterأحادي المضيف؛ والمرّة الواحدة بالضبط عبر مضيفين متعدّدين تحتاج مُلتزِم Enterprise الدائم.- يجب أن تستخدم عمليات التشغيل الآمنة عند الأعطال مخازن
DurableCapability(نظام الملفات) في كلّ مكان، لا النسخ في الذاكرة.
حدّ النشر
قسم بعنوان «حدّ النشر»توثّق هذه الصفحة السلوكَ القابل للملاحظة خارجيًا وسطحَ API العام المدعوم فقط. أمّا مسارات فضاء الأسماء الداخلية، والأصناف المساعدة، وجداول الآليات، وأسماء ملفّات كتيّبات التشغيل، وبادئات التذاكر فخارج النطاق.