عقد الأكواد تتجمد

تجميد عُقد الكود

وصف المشكلة/الخطأ/السؤال

سير عملي يعمل بشكل مثالي، لكن عندما أرفق الذاكرة بـ LLM (OpenAI)، وهي موجودة تقريباً في منتصف سير العمل، تتجمد العديد من عُقد الكود التي تسبق عقدة HTTP (لإرسال البيانات إلى لوحة التحكم)

أواجه مشكلة حادة في الأداء حيث تتجمد عُقد الكود لدي وتنتهي بانتهاء المهلة الزمنية، لكن فقط عندما تكون ذاكرة LLM موجودة في سير العمل.

سير عملي يعالج بيانات JSON الواردة باستخدام عدة عُقد كود قياسية (تنفيذ تنظيف البيانات والتحقق من صحتها). في مكان لاحق من سير العمل، لدي عقدة LLM (OpenAI) مع مكون ذاكرة مرفق.

عندما أشغل سير العمل بدون ذاكرة LLM، كل شيء ينفذ بشكل مثالي وفوري. ومع ذلك، في اللحظة التي أرفق فيها الذاكرة بـ LLM، تتعطل عدة عُقد كود تُنفذ قبل عقدة طلب HTTP في تعليق لا نهائي.

ما رسالة الخطأ (إن وجدت)؟

شيء من هذا القبيل: لا توجد رسالة خطأ بعد الآن، فقط تنفيذ لا نهائي. الخطأ:
انتهت مهلة تنفيذ المهمة بعد 300 ثانية
كان عامل المهام يستغرق وقتاً طويلاً في هذه المهمة، لذا تم الاشتباه بأنه غير مستجيب وتم إعادة تشغيله، وتم إلغاء المهمة. يمكنك تجربة ما يلي: 1. حسّن السكريبت الخاص بك لمنع المهام التي تستغرق وقتاً طويلاً، على سبيل المثال بمعالجة البيانات على دفعات أصغر. 2. تأكد من أن جميع المسارات في السكريبت الخاص بك قادرة على الإنهاء، أي لا توجد حلقات لا نهائية. 3. إذا كانت مهمتك يمكن بشكل معقول أن تستغرق أكثر من 300 ثانية، فقم بزيادة المهلة الزمنية باستخدام متغير البيئة N8N_RUNNERS_TASK_TIMEOUT.

معلومات حول إعداد n8n الخاص بك

  • إصدار n8n: 2.11.3
  • قاعدة البيانات (الافتراضية: SQLite): الافتراضية
  • إعداد n8n EXECUTIONS_PROCESS (الافتراضي: own, main): الافتراضي
  • تشغيل n8n عبر (Docker, npm, n8n cloud, desktop app): Dockers
  • نظام التشغيل: Window

يا @sherazbintahir، بينما تنتظر الرد، إليك بعض الأشياء التي قد تساعدك:

الموارد المقترحة

تم مطابقتها تلقائياً مع سؤالك.

المستندات:

المنتدى:

@Fabian_Hagen، @aseefdurrani، @Anshul_Namdev - لقد ساعدتم في مشاكل مماثلة من قبل، هل يمكنكم الاطلاع على هذا؟

مقترح تلقائياً من قبل بوت المجتمع n8n. إنه تجريبي - يرجى مشاركة ملاحظاتك هنا.

هذا إجراء حماية محدد في n8n. يعني أن كود JavaScript داخل عُقد الكود الخاصة بك يعمل لأكثر من 300 ثانية، مما يجعل n8n Task Runner يفترض أنه عالق في حلقة لا نهائية أو يعالج مهمة مستحيلة، فيقوم بإيقافه قسراً.

بما أن هذا فقط يحدث عندما تضيف الذاكرة إلى نموذج اللغة، فإن مكون الذاكرة يغير بشكل أساسي هيكل البيانات أو حجمها أو سلوك البيانات المتدفقة إلى عُقد الكود اللاحقة لك.

عند إضافة الذاكرة، قد تمرر عُقدة نموذج اللغة (أو السلسلة/الوكيل الذي تكون جزءاً منه) سجل المحادثة الكامل أو كائن حالة ذاكرة كبير إلى تيار البيانات الرئيسي، بدلاً من مجرد الرد الأخير من الذكاء الاصطناعي.

  • المشكلة: إذا كانت عُقد الكود الخاصة بك تحاول معالجة أو تنظيف أو JSON.stringify() إدخال يحتوي الآن على مئات أو آلاف الرسائل التاريخية، فسيتجاوز بسهولة مهلة المعالج المركزي البالغة 300 ثانية.
  • الحل: تحتاج إلى تقليل البيانات إلى ما يحتاجه لوحة التحكم فقط مباشرة بعد عُقدة نموذج اللغة.
    • أضف عُقدة كود مؤقتة مباشرة بعد عُقدة نموذج اللغة باستخدام هذا الكود لترى ما يتم تمريره بالفعل:
// تحقق من عدد العناصر وحجم البيانات
const items = $input.all();
console.log("إجمالي العناصر:", items.length);
console.log("مفاتيح العنصر الأول:", Object.keys(items[0].json));
return items;
  • إذا رأيت مصفوفة messages ضخمة أو كائن ذاكرة، حدّث عُقد الكود اللاحقة الخاصة بك لاستخراج الحقل المحدد فقط الذي تحتاجه (على سبيل المثال، item.json.message.content أو item.json.text) وتجاهل الباقي قبل المعالجة.

قد تحتوي كائنات الذاكرة في n8n (خاصة عند التعامل مع تكاملات LangChain) على مراجع دائرية (حيث يشير الكائن إلى نفسه).

  • المشكلة: إذا كانت عُقد الكود الخاصة بك تستخدم JSON.stringify($input.all()) أو تمرر كائن الإدخال الكامل إلى دالة تحليل مخصصة، فإن المرجع الدائري قد يسبب محرك JavaScript في الدخول في حلقة لا نهائية محاولاً تسلسل الكائن، مما ينتج عنه انتهاء مهلة 300 ثانية.
  • الحل: لا تقم أبداً بتسلسل $input أو $input.all() الكاملة إذا كانت تحتوي على مخرجات نموذج اللغة/الذاكرة. استخرج دائماً قيم السلاسل البدائية أولاً:
  // خطأ: قد يتعطل إذا كانت هناك مراجع دائرية
  // const payload = JSON.stringify($input.all()); 

  // صحيح: استخرج البيانات البدائية فقط التي تحتاجها
  const cleanData = $input.all().map(item => ({
    response: item.json.message?.content || item.json.text,
    // أضف الحقول المحددة الأخرى هنا
  }));
  const payload = JSON.stringify(cleanData);

إذا كانت عُقد الكود الخاصة بك تستخدم حلقات while أو دوال عودية أو طرق .reduce() تعتمد على هيكل JSON الوارد، فقد تكون الذاكرة قد غيرت هذا الهيكل.

  • المشكلة: على سبيل المثال، إذا كان لديك حلقة while تعالج مصفوفة حتى تصبح فارغة، لكن مكون الذاكرة يحقن عن طريق الخطأ مصفوفة متداخلة تستمر في إعادة التوليد أو لا تستوفي شرط الخروج، فستعمل الحلقة للأبد.
  • الحل: راجع جميع حلقات while في عُقد الكود الخاصة بك. أضف “عداد السلامة” لفرض توقفها إذا تجاوزت عدداً معقولاً من التكرارات:
let safetyCounter = 0;
while (myCondition && safetyCounter < 1000) {
    // منطقك
    safetyCounter++;
}

هل هذا يساعد؟

كما قلت، الذاكرة المرفقة باللغة LLM توجد في منتصف سير العمل.

وبمجرد إرفاق الذاكرة، واجهت مشاكل مع عدة عقد أكواد، وبعض عقد الأكواد موجودة في بداية سير العمل (قبل أن ينفذ عقدة ذاكرة llm حتى).

بدون ذاكرة، ينتهي تنفيذ سير العمل بدون مشاكل، لكن مع الذاكرة، يبدأ نفس سير العمل في حدوث مشكلة عند عقدة الكود

بما أنك لم تصرح بوضوح، أفترض أن هذا حدث بعد وكيل الذكاء الاصطناعي

هذا أوضح. يبدو لي أنها مشكلة انحدار في الذاكرة

هل يساعد التحديث إلى آخر إصدار مستقر من n8n؟

مرحباً @sherazbintahir
عُقد الكود التي تتعلق فقط بوجود عُقدة فرعية، بما في ذلك تلك التي تعمل قبلها، هي مؤشر على فشل مشغّل المهام في حل نوع تلك العُقدة الفرعية. أي شيء يجعل عُقدة الكود تطلب من العملية الرئيسية سياقاً إضافياً، مثل مرجع $('Node Name') أو $node["Node Name"] أو require() لوحدة خارجية، يأخذ المشغّل للخلف لإعادة بناء سير العمل، وعندما لا يتمكن من حل نوع عُقدة فرعية يترك الطلب بدون إجابة حتى ينقضي الـ 300 ثانية. ستظهر سجلات حاوية n8n الخاصة بك رسالة “Unrecognized node type: …” في اللحظة التي يتوقف فيها.
أعد كتابة عُقد الكود هذه لاستخدام $input و $json فقط، ونقل أي شيء تحتاجه من عُقدة سابقة إلى المسار الرئيسي باستخدام عُقدة Set أولاً. إيقاف المشغّل ليس خياراً على الإصدار 2.11.3، N8N_RUNNERS_ENABLED مُهمل من الإصدار 2.0 وكل تنفيذ عُقدة كود يعمل على مشغّل.

شكراً، سيساعد كثيراً. لكنني مرتبك هنا لأن سير العمل الكامل لدي (120+ عقدة) يعمل بشكل مثالي بدون أي خطأ، لكن عندما أرفق الذاكرة مع LLM (عقدة وكيل ذكاء اصطناعي مع OpenAI + الذاكرة) أواجه هذه المشكلة.
للمزيد من المعلومات، في سير العمل بدون ذاكرة، أستخدم عقدة OpenAI مباشرة. وأنا لا أواجه هذه المشكلة على جميع عقد الكود لكن على عدد قليل منها.

الصندوق الأصفر: حيث أرفق الذاكرة مع LLM.
النقاط الحمراء: حيث أواجه مشاكل في عقد الكود. معظم العقد هي تلك التي أقوم فيها ببناء/تحضير الحمل المراد إرساله على لوحة التحكم.

مرحبا @sherazbintahir

هل حاولت التبديل إلى PostgreSQL لاستبعاد SQLite Database Locking ؟

services:
  postgres:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=n8n_user
      - POSTGRES_PASSWORD=n8n_password
      - POSTGRES_DB=n8n_db
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n_user -d n8n_db"]
      interval: 5s
      timeout: 5s
      retries: 5

  n8n:
    image: n8nio/n8n:2.11.3
    environment:
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n_db
      - DB_POSTGRESDB_USER=n8n_user
      - DB_POSTGRESDB_PASSWORD=n8n_password
      - EXECUTIONS_PROCESS=own
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:

مرحبا @sherazbintahir هذا ليس بطء، عُقد الكود الخاصة بك مُتوقفة، وليست مشغولة.

منذ الإصدار v2.0، تعمل جميع عُقد الكود في عملية runner منفصلة. إذا كانت البرنامج النصي يستخدم فقط `input’/‘input` / ` input’/'json`، فإنها تحصل على حمولة نحيفة وتعمل بسرعة. لكن إذا استخدمت `(′NodeName′)‘or’(‘Node Name’)` أو ` (′NodeName′)'or’node[‘Node Name’]`، يجب على runner أن يطلب سير العمل المسلسل بالكامل من n8n ويعيد بناؤه، وهذا يتطلب حل كل نوع عُقدة على القماش، بما في ذلك العقد الفرعية. إذا أضفت العُقدة الفرعية للذاكرة والدّاعم يصل إلى نوع لا يستطيع حله، الطلب لا يعود أبدا، وعُقدة الكود الخاصة بك تنتظر إلى الأبد حتى يقتلها حارس الـ 300 ثانية. نفس الشيء مثل #20752.

هذا يشرح أيضا لماذا فقط بعض عُقد الكود الخاصة بك تنقطع — العاملة منها هي التي لا تصل أبدا خارج مدخلاتها الخاصة.

هل يمكنك التحقق من شيئين؟

  1. قم بتشغيله مع الذاكرة المرفقة و grep سجلاتك:
   docker logs -f <n8n-container> | grep -i "unrecognized node type"
  1. افتح إحدى عُقد الكود المُجمدة — هل تحتوي على $('...') أو $node[...] في أي مكان؟

إذا كانت الإجابة نعم على كليهما، الحل سريع: ضع عُقدة Set أمامها وأمرر القيمة كتعبير (={{ $('Clean JSON').first().json.config }} — التعبيرات في العُقد العادية تعمل في العملية الرئيسية وغير متأثرة)، ثم اقرأها من `$input` داخل عُقدة الكود. الذاكرة تبقى حيث هي بالضبط.

أرسل لي ما تقول سطر السجل وسأعطيك إعادة الكتابة الدقيقة لعُقدتك.

@sherazbintahir الـ variable ليس memory — إنه node swap. بدون memory استخدمت عقدة OpenAI العادية. لإرفاق memory كان عليك الانتقال إلى AI Agent، وهو جذر مجموعة LangChain يسحب العُقد الفرعية على لوحة الرسم (Chat Model و Memory و أداتك search_workwell_memory). عقدة OpenAI تُحل بشكل جيد في مُشغّل المهام؛ عقد Agent الفرعية غالباً لا تحل.

لماذا فقط بعض عُقد Code: منذ v2.0 جميع عُقد Code تعمل في عملية مُشغّل منفصلة.

  • تستخدم فقط $input / $json → حمولة نحيفة، فورية. نعم (عُقد التنظيف/التحقق الخاصة بك)
  • تستخدم $('Node') / $node['Node'] / $items() - يطلب المُشغّل سير العمل المسلسل بأكمله مرة أخرى وإعادة بنائه، مما يعني حل كل نوع عقدة على لوحة الرسم ذات 120 عقدة، بما في ذلك العُقد الفرعية. نوع واحد غير قابل للحل - الطلب لا يعود أبداً - تعليق حتى يطلق حارس 300s الثاني. لا (منشئو الحمولة الخاصة بك — النقاط الحمراء)

لاحظ أن عقدة الأداة الفرعية يمكن أن تسبب هذا وحدها أيضاً: #20752 كان postgrestool، #20132 Apify/Perplexity — هناك تعلقت حتى لو لم يتم تنفيذ Agent.

أكد في 30 ثانية — اترك memory مرفقاً، عطّل عقدة واحدة مجمدة:

// const cfg = $('Prepare Normal Formatter Evidence').first().json;
const cfg = { test: true };

يعمل بشكل فوري → تم التأكيد.

أفضل إصلاح أولاً:

  1. دمج العقدة في عقدة Code، ثم اقرأ $input.all(). الأنظف بحجمك.
  2. عيّن العقدة في الأمام، حل القيم كتعبيرات: ={{ $('Parse Extraction').first().json.score }} التعبيرات في العُقد العادية تُقيّم في العملية الرئيسية، لذا فهي محصنة.
  3. تخطّ عقدة Code — بناء جسم JSON مباشرة في عقدة HTTP Request مع التعبيرات.

احتفظ بـ pairedItem: { item: index } على العناصر المُرجعة، وإلا فإن التعبيرات الموجودة بعد ذلك تُعيد تقديم المشكلة. يبقى Memory مرفقاً في جميع الحالات الثلاث.

لن يساعد: رفع N8N_RUNNERS_TASK_TIMEOUT (الانتظار غير محدود)، أو N8N_RUNNERS_ENABLED=false (مُتجاهل في 2.x).

هل يمكنك نشر مخرجات docker logs -f <n8n-container> | grep -i "unrecognized" أثناء التشغيل مع توصيل Agent؟ سيوضح ما إذا كانت المشكلة في memory أو الأداة.