تخطَّ إلى المحتوى
getnextpdf.com

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 order
public function maxBatchSize(): int; // int<1, max> backpressure hint
public function isAvailable(): bool;

$manifests هو list<RenderManifest> بحجم لا يتجاوز maxBatchSize()؛ ويُسنِد $variablesByJobId معرّف المهمّة إلى متغيّرات قالب array<string, scalar>. وفشلٌ لكل بيانات وصفية هو نتيجة Failed/Timeout لكل عنصر ولا يُجهِض الدفعة أبدًا.

خطّ مرجعي متزامن أحادي العملية. يتحقّق من كلّ بيانات وصفية تحقُّقًا مُغلَقًا بأمان عبر 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 order
public 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.

final readonlyint<0, max> $index، وRenderManifest $manifest، وarray<string, scalar> $variables. والترابط بحسب index، لا بحسب معرّف المهمّة أبدًا (معرّفات المهامّ ليست مضمونة الفرادة داخل دفعة).

final readonlyint $index (غير موثوق، يتحقّق منه المحرّك)، وEngineRenderResult $result.

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() عن الحالة. وتحمل النتيجة المُصيَّرة بايتاتٍ وبصمةً، ولا تحمل موقعًا ملتزَمًا به أبدًا.

تعداد مدعوم بسلسلة نصّية: 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.

final readonlyjobId، و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 (دائم وذرّيّ — لا يرى قارئٌ أبدًا نقطة تفتيش مكتوبة نصفيًا).

final readonlyrunId، و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 — نطاق تشغيل واحد / اختبار (يُفقَد عند العطل).
  • FilesystemIdempotencyStoreDurableCapability؛ ملفّ ⁨JSON⁩ ذرّيّ واحد لكلّ مفتاح ملتزَم به (الإيصال المُسلسَل)، مُسمّى ببصمة قيمة المفتاح. والعلامات ذات خاصية عدم تأثيرية؛ وإعادة وسم متزامنة تتسابق على ملفّ واحد بلا ضرر. ودليل غير موجود يرمي InvalidArgumentException.

إعادة المحاولة والرسائل الميتة

قسم بعنوان «إعادة المحاولة والرسائل الميتة»

final readonlypositive-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>.

final readonlyjobId، وidempotencyKeyValue، وpositive-int $attempts، وlastErrorCode، وlastErrorMessage، وDateTimeImmutable $failedAt، واختياريًا ?string $runId، واختياريًا int<1, max> $sourceOffset. وdedupKey() هو runId:sourceOffset حين يكون كلاهما معلومًا، وإلّا فقيمة مفتاح خاصية العدم التأثيرية. ويحلّل fromArray() القيمةَ failed_at بصرامة بصيغة ⁨ATOM⁩ (رافضًا التعابير النسبية أو غير ⁨ATOM⁩) فيبقى التسلسل/فكّ التسلسل متناظرًا.

  • InMemoryDeadLetterStore — نطاق تشغيل واحد / اختبار.
  • FilesystemDeadLetterStoreDurableCapability؛ ملفّ ⁨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 هو التنفيذ أحادي التشغيل؛ وفقدانه عند الاستعادة هو لا-عمل دلاليّ لعبء العمل الافتراضي لأنّ المرّة الواحدة بالضبط تأتي من إزالة تكرار بصمة المُلتزِم.

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⁩ العام المدعوم فقط. أمّا مسارات فضاء الأسماء الداخلية، والأصناف المساعدة، وجداول الآليات، وأسماء ملفّات كتيّبات التشغيل، وبادئات التذاكر فخارج النطاق.