سجل التطوير: ما الذي يكسره جدول بيانات مكون من 120,000 صف
جلسة عمل على جدول بيانات مكون من 121,254 صفًا و1.8 مليون خلية، والأشياء الخمسة المنفصلة التي كان يجب تغييرها قبل أن يتمكن تحليل جدول مشترك كبير من الانتهاء، والتحقق من مخرجاته، وإرجاع تقرير منسق قابل للاستخدام.
يتم اختبار معظم ميزات جداول البيانات على البيانات التي تناسب الشاشة. يغطي هذا السجل جلسة عمل في مصنف المبيعات باستخدام 121,254 صفًا عبر 15 عمودًا - ما يقرب من 1.8 مليون خلية - وطلبًا يبدو عاديًا: قم بدمج جداول المنتج والعميل والطلب والمبيعات، ثم قم بوضع علامة على المنتجات المتدهورة ومخاطر إعادة المخزون والعملاء ذوي القيمة المنخفضة.
لا يوجد شيء غريب في هذا الطلب. لقد فشل على أية حال، عدة مرات، لأسباب لا علاقة لها بالتحليل نفسه. وما يلي هو ما انكسر بالفعل وما تغير.
حد النظام الأساسي، وليس استعلامًا بطيئًا
بدا الفشل الأول وكأنه خطأ في نظام العمل الدائم. كان السبب الحقيقي هو قاعدة في Google Apps Script: لا يجوز للوظيفة الإضافية للمحرر إنشاء مشغل يعتمد على الوقت يتم تشغيله أكثر من مرة واحدة كل ساعة.
يفترض تصميم المهمة الخلفية تشغيلًا مدته دقيقة واحدة. استمر هذا الافتراض أثناء التطوير، حيث يمكن جدولة البرنامج النصي المرتبط بالحاوية بحرية، وتوقف عن الاستمرار في اللحظة التي تم فيها تشغيل نفس الكود كوظيفة إضافية مثبتة. لم يتدهور طلب تثبيت المشغل - فقد تم إنشاء المهمة، وتم إنشاء المهمة، وبالتالي لم يبدأ العمل أبدًا.
تم اتباع تغييرين. يعد تثبيت المشغل الآن هو أفضل جهد: فهو يحاول إيقاعًا مدته دقيقة واحدة، ويعود إلى كل ساعة، وفي النهاية لا يوجد مشغل على الإطلاق، ولا يتم إطلاقه أبدًا. ويتم الآن تشغيل خطوة المعالجة الأولى داخل نفس عملية التنفيذ التي أنشأت المهمة، بدلاً من إجراء مكالمة ثانية للبحث عن المهمة مرة أخرى.
هذه التفاصيل الثانية كانت أكثر أهمية مما تبدو. لا يمكن قراءة ما تكتبه خصائص Apps Script عبر عمليات التنفيذ، لذلك يمكن أن تعود المهمة المكتوبة قبل لحظات كـ "لم يتم العثور على المهمة" في المكالمة التالية.
إعداد التقارير عن التقدم ليس مثل الانتهاء
مع بدء المهمة أخيرًا، لم تنتهِ بعد. نفّذت الأداة خطوة واحدة، ثم أعادت حالة تفيد بأن العمل "يستمر في الخلفية".
تلك الجملة كانت خاطئة. مع عدم توفر مشغل كل ساعة، لا شيء يستمر في الخلفية. قرأ المساعد الحالة، وأرسل نسبة مئوية إلى المستخدم، ثم توقف، تاركًا مهمة متوقفة عند 34000 من 121253 صفًا إلى أجل غير مسمى.
يعمل وقت التشغيل الآن على دفع المهمة إلى الاكتمال بنفسها، ضمن ميزانية محدودة، وكل استدعاء حالة لاحق يؤدي إلى تقدم العمل بدلاً من مجرد قراءته. إذا تم استنفاد الميزانية، فإن نص الحالة يشير بوضوح إلى أن المهمة غير مكتملة وأنه لن يؤدي أي شيء آخر إلى تقدمها.
المبدأ يستحق الذكر مباشرة: التقرير المرحلي ليس من النتائج. طلب المستخدم جدولًا، وليس نسبة مئوية.
لا يمكن تقديم الطلب إلا من خلال الأدوات التي يمكن للنموذج رؤيتها
للحفاظ على دقة تحديد الأداة، يكشف GetSheetAI عن مجموعة فرعية من الأدوات الخاصة به في كل دورة بناءً على الطلب. تم إنشاء هذه الآلية حول مجموعة أدوات Excel، وتسجل الوظيفة الإضافية Google Sheets 22 أداة موجودة هناك فقط. تم تصفية هذه الأدوات من كل طلب.
كان التأثير محددًا ومن السهل تفويته. أدى طلب رسم بياني شريطي إلى الكشف عن 6 أدوات من أصل 44، وكانت أداة الرسم البياني من بين الأدوات المخفية. طلب فرز نطاق تم الكشف عنه 5 من 44، بدون أداة الفرز. لم يكن المساعد يرفض، فهو في الواقع لم يتمكن من رؤية الأداة التي تؤدي المهمة.
تحتوي جداول البيانات الآن على تعيين أداة خاص بها للحزمة، مما يعكس كل نظير من Excel، ويمر الفلتر عبر أي أداة ليس لديه رأي بشأنها بدلاً من إسقاطها. يقرأ الاختبار الآن أسماء الأدوات المسجلة مباشرة من المصدر، لذا فإن إضافة أداة دون تصنيفها يؤدي إلى فشل عملية الإنشاء بدلاً من جعلها غير قابلة للوصول بهدوء.
ظهرت نفس الفئة من الفجوة في الصياغة. لم يتطابق الطلب الصيني الذي يعني "إنشاء ورقة جديدة" مع أي قاعدة، لأن النمط لم يتعرف إلا على كلمة واحدة من الكلمتين الشائعتين للورقة. ظلت أداة إنشاء الورقة مخفية وأبلغ المساعد أن إنشاء ورقة عمل أمر مستحيل. لم يكن كذلك.
تعتبر رسائل الخطأ جزءًا من المنتج
تعود العديد من حالات الفشل إلى رسالة تشير إلى وجود مشكلة دون ذكر طريقة الحل.
تم إرجاع الكتابة إلى ورقة غير موجودة "المورد المطلوب غير موجود." والتي تبدو وكأنها وظيفة إضافية معطلة. تقول الآن أن الورقة غير موجودة، وأن أداة الكتابة لا تقوم بإنشاء أوراق، وما هي المكالمة التي تقوم بها.
رفض التصنيف على مستوى الصف على نطاق كبير جدًا بمثابة رفض صريح. تعمل تسمية النتيجة المجمعة بأي حجم، لذا تقوم الرسالة الآن بتسمية هذا المسار: المجموعة أولاً، ثم تطبيق قواعد التصنيف على النتيجة المجمعة.
لم يُرجع حارس الكتابة شيئًا سوى blocked: true، والذي يُقرأ على أنه فشل. ويوضح الآن أن الهدف يحتوي بالفعل على البيانات وكيفية المتابعة.
لا شيء من هذه الأمور تجميلية. في كل حالة، أنهت الرسالة السابقة مهمة كانت لا تزال مكتملة.
تحتاج التعبيرات الحتمية إلى المزيد من العمليات الحسابية
يتطلب اشتقاق سنة وشهر مثل 201707 من مفتاح تاريخ صحيح مثل 20170702 إما floor(x / 100) أو modulo. لا يوجد أي منهما. فشلت محاولتان وتم التخلي عن العمود المشتق.
تتضمن طبقة التعبير الآن floor، وround، وabs، وmod، ويسرد خطأ الوظيفة غير المدعومة المجموعة الكاملة ويعطي هذا التعبير الدقيق، بدلاً من تسمية ما تم رفضه فقط.
أين يقف
في نفس المصنف، يكتمل الآن المسار الدائم: تمت معالجة كافة الصفوف البالغ عددها 121,253، وتجميعها، وكتابتها، وتنسيقها، مع التحقق من كل مجموعة نتائج. في Excel، أنتج نفس الطلب تصنيفًا عبر جميع المنتجات البالغ عددها 397 - 132 بدون مبيعات حديثة، و101 تم وضع علامة عليها لمخاطر إعادة التخزين، و99 انخفاضًا، و65 عاديًا - تم حسابها باستخدام SUMIFS الأصلي مقابل الجدول المصدر بدلاً من نقل البيانات إلى أي مكان.
قيم التشغيل التي تستحق المعرفة:
- عتبة التوجيه الدائمة: أكثر من 100000 خلية؛
- تقسيم المصدر: القراءات المحددة، والتحقق من كل مقطع عند إعادة الكتابة؛
- تغطية الانحدار: 826 اختبارًا عبر وقت التشغيل المشترك؛
- التنفيذ في الخلفية على الوظائف الإضافية لجداول بيانات Google: كل ساعة في أحسن الأحوال، لذا يقوم الشريط الجانبي بتشغيل المهام الطويلة عندما يكون مفتوحًا.
هذه النقطة الأخيرة هي حد حقيقي وليس حدًا مؤقتًا. لا يمكن للوظيفة الإضافية المثبتة جدولة العمل بشكل متكرر، لذلك تتقدم مهمة كبيرة أثناء فتح الشريط الجانبي. إن عملية التدقيق الدائمة تعني أن إغلاقها لا يفقد أي عمل مكتمل، لكن الوصف الصادق هو أن العمل مدفوع وليس مجدولًا.
لم يكن الدرس الأوسع المستفاد من هذه الجلسة يتعلق بالحجم. كل واحدة من هذه الإخفاقات كانت نتيجة معرفة النظام بشيء لم يتمكن المستخدم من رؤيته: قاعدة النظام الأساسي، أو أداة مخفية، أو مسار مدعوم لم يذكر اسمه في أي مكان في الخطأ. كان الحجم هو ما جعلهم مرئيين جميعًا في وقت واحد.