خان المُبرمجين (علي فاضل)
543 subscribers
93 photos
9 videos
116 links
قناة أنشر فيها ما أتعلمه خلال عملي على مشاريعي الخاصة 👀
Download Telegram
من مميزات منصة باحث أنها تسمحلك بالبحث بالمعنى في الأحاديث النبوية والمكتبة الشاملة. البحث بالمعنى أو Semantic Search يعطيك الإمكانية للبحث من خلال طرح الأسئلة أو الأفكار العامة بدلا من كتابة النص كما هو في الحديث أو الكتاب. على سبيل المثال، ممكن تكتب "هل يجوز زيارة القبور؟" والنتائج من المفترض أن تحتوي على الأحاديث اللي فيها جواب سؤالك. أو ممكن تبحث عن "من هو الصحابي الذي تعلم لغة اليهود؟" والنتائج من المفترض أن يظهر فيها صفحات من كتب المكتبة الشاملة تحمل جواب لسؤالك. شرح أكثر عن المنصة في هذا المقطع:
https://youtu.be/vl90LkLgfE4

طيب، أين تقع المشكلة؟ المشكلة أن المكتبة الشاملة فيها أكثر من 8 آلاف كتاب وأكثر من 3 آلاف مؤلّف، وانت محتاج تعطي للمستخدم طريقة لتحديد نطاق البحث داخل الكتب والمؤلفين، وهذا يتضمن إما: 1) إظهار قائمة منسدلة Dropdown فيها كل أسماء الكتب أو المؤلفين والمستخدم يبحث ويختار نطاق البحث اللي محتاجه، أو 2) ممكن تعمل مربع للإدخال ويكون عليه خاصية تكملة تلقائية Autocomplete بدلا من إظهار كل أسماء الكتب والمؤلفين في الصفحة.

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

#الجزء_الأول

أكمل من هنا 😁
2
من كم يوم خطرلي أستخدم ميزة من مميزات إطار عمل Ruby on Rails لإيجاد حل وسط بين الطريقتين وهي ميزة Lazy Turbo Frames واللي ممكن تقرأ عنها أكثر من هذا الرابط:
https://turbo.hotwired.dev/reference/frames

الميزة مش اختراع من Rails ولكن تطبيقها في Rails حسيته مباشر وبدون تعقيدات. كل الفكرة انك تعمل Route انت بدك تجيب المحتوى تبعه بعد ما الصفحة تظهر للمستخدم، وتعمل turbo_frame_tag داخل الصفحة تحكيله لما الصفحة تنتهي من التحميل وتظهر للمستخدم، انت جيب محتواك من هذا الـ Route واعرضه براحتك، الكود حرفيا سطر:

turbo_frame_tag('shamela-search-filters', lazy: true, src: shamela_filters_path)


ببساطة هذا السطر لما الصفحة تنتهي من التحميل بيبعث طلب للـ Route اللي اسمه shamela_filters_path وبيجيب المحتوى وبيعرضه.

هذا التعديل البسيط نزّل زمن الاستجابة للصفحة الرئيسية للمنصة من متوسط 150ms إلى متوسط 20ms زي ماهو موضّح في الصورة.

بهذه الطريقة المستخدم عنده كل أسماء الكتب والمؤلفين، وانا ما اضطريت أعدّل كود كثير، وزمن الاستجابة نزل، والعصافير تزقزق والحمدلله والسلام عليكم 👋🏻

#الجزء_الثاني

الجزء الأول من هنا 😁
3
تجربتي مع pgvector و ChromaDB 🥲

لتمكين البحث بالمعنى Semantic search في منصة باحث، كنت أبحث عن Vector DB تخدم هذا الهدف على مجموعات ضخمة من الـ Vectors.

بحكم استخدامي لـ PostgreSQL في باحث، فكان الخيار الأول هو pgvector واللي بتستخدم HNSW index واللي هو عبارة عن Index تقريبي أو Approximate لإيجاد الـ Vectors القريبة أثناء البحث بشكل سريع، ولكن التجربة من ناحية الاستخدام ما كانت ألطف شيء، والنتائج ما كانت جيدة مقارنة بالبحث الغير تقريبي اللي كنت كتبته يدويا لاختبار الفكرة قبل تطبيقها على المنصة.

فبدأت رحلة البحث عن Vector DB تحقق الشروط التالية:
- سهلة الاستخدام، يُفضّل تكون مجرد Docker container
- ممكن تتعامل مع عدد كبير من الـ Vectors
- تدعم الفرز أو Filters

ووقتها لقِلّة الخبرة، تحمست لـ ChromaDB وقررت استخدامها.

تجربة الاستخدام سلسة، خصوصا مع وجود مكتبة Ruby غير رسمية خاصة بها، والنتائج جيدة ومش بعيدة عن البحث الغير تقريبي (ممكن كان عندي مشكلة خلال استخدامي لـ pgvector وظلمتها بالنسبة للنتائج 🤔)، وخلال عملي كتبت مكتبة Rails منبية على مكتبة Ruby بحيث تسهل الاستخدام:
https://github.com/AliOsm/chromable

وفعلا، حطيت ChromaDB على باحث ودخّلت فيها أكثر من 330 ألف حديث (حاليا الأحاديث في المنصة أقل) وكانت تعمل بشكل جيد، مع بطئ في عملية الفرز أحيانا.

بعد فترة، قررت إضافة البحث بالمعنى في المكتبة الشاملة على منصة باحث، والخطة كانت واضحة، فقط حط البيانات في PostgreSQL ومكتبة chromable المفروض تنقلهم إلى ChromaDB والأمور سهلة.

فعلا بدأت العملية واستغرقت وقت طويل بسبب استخدام GPU واحد لتحويل المكتبة الشاملة إلى Embeddings، ولما انتهت العملية كانت المفاجأة 🎉

البحث والفرز باستخدام ChromaDB بطيئ لأبعد الحدود وأحيانا يُعطي Timeouts. عشان تكون في الصورة، الـ Index الخاص بالمكتبة الشاملة كان فيه أكثر من 11 مليون Vector، وهو رقم يُعتبر كبير لما نحكي عن Vector DBs.

من وقت إضافة هذه الميزة إلى المنصة من 8 شهور، والوضع كان سيئ من ناحية زمن الاستجابة، وحاولت حلّه بأكثر من طريقة وتواصلت مع فريق ChromaDB على Discord ولكن بدون حل مُجدي.

حاليا بختبر بقاعدة بيانات ثانية للـ Vectors وهي Qdrant ويبدو أنها أفضل وتدعم أمور أكثر زي الـ Multiple vectors لكل مستند أو Document ودعم ColBERT vectors والـ Sparse vectors والـ Fusion وكذلك الـ API الخاص بالبحث مرن جدا.

أحد الخيارات المطروحة كان قاعدة بيانات Vespa ولكن بعد القراءة عنها وجدت انها معقدة أكثر من اللازم بالنسبة للحالة الخاصة بمنصة باحث، فاستثنيتها.

إذا خطر ببالك سؤال شو يعني HNSW أو ColBERT أو Sparse أو Fusion أو ليش في أكثر من Vector لكل مستند، وغيرها من الأسئلة، فممكن تبحث عن الجواب، أو تنتظر المنشورات المستقبلية 😁

أما شو هي منصة باحث، فممكن تعرف من هون:
https://youtu.be/vl90LkLgfE4

وإذا كان عندك تجربة سيئة/جيدة مع قاعدة بيانات من القواعد المذكورة ياريت تشاركها 👀

والسلام عليكم 👋🏻
3
كيف تبدأ المشاريع مفتوحة المصدر ؟.؟

بدايةً أنا مش التنين المُجنّح صاحب المشاريع مفتوحة المصدر كثيرة النجوم والمستخدمين، وإنما أدّعي إنشائي لبعض المشاريع مفتوحة المصدر، عشان نكون على بيّنة 👀

طُرق بداية المشاريع مفتوحة المصدر كثيرة، قد تكون مُجرّد فكرة خطرت لك أو مشروع داخلي في شركة ما تم نشره للناس أو غيرها، ولكن من الطُّرق المُلهمة بالنسبة لي هي استخراج المشروع مفتوح المصدر من مشروع أساسي أكبر منه، ومن أكثر الناس تطبيقًا لهذا المبدأ هم الناس في 37Signals واللي هما أصحاب basecamp و hey.com وبشتغل معهم DHH اللي عامل Ruby on Rails (ذكرنا Rails في المنشور كالعادة 😂)

هذا الأمر حدث معي 4 مرات في آخر سنتين، 3 منهم مُتعلّقين بمنصة باحث وهما اللي ممكن أذكرهم كأمثلة:

* تفريغ

فكرة منصة باحث في الأساس هي تفريغ الدروس الشرعية إلى نصوص وتمكين المستخدمين من البحث داخلها والوصول إلى المعلومات بسرعة، وزي ما هو متوقع، محتاجين أداة لتحويل هذه الدروس من صوت إلى نص، وهنا تأتي مهمة تفريغ. تفريغ كان عبارة عن Script كبداية، ثم تحوّل إلى مكتبة مكتوبة بلغة Python تم تنزيلها أكثر من 40 ألف مرة وفَرّغت أكثر من 150 ألف ساعة وبُنِيت عليها مشاريع أخرى.

الرابط: https://github.com/ieasybooks/tafrigh

* Chromable

هذه ذكرتها في منشوري السابق، ولكن سريعًا، Chromable كانت مجرد module يُساعد في ربط قاعدة البيانات الأساسية بقاعدة بيانات الـ Vectors لتمكين البحث بالمعنى في باحث، ثم أتت الفكرة لتحويلها إلى مكتبة وفتح مصدرها من باب الفائدة وتقليل الكود الموجود داخل المشروع. المكتبة عبارة عن ملف واحد فيه تقريبا 125 سطر كود، ولكن سهّل استخدامي الشخصي لها وساعد "القليل" من الناس 😁

ملاحظة: إذا قرأت منشوري السابق فانت عارف انك مش لازم تستخدمها 😂

الرابط: https://github.com/AliOsm/chromable

* PhlexIcons

تُكتب الواجهات في Rails بتنسيق ERb أو Embedded Ruby. على سبيل المثال، بهذه الطريقة ممكن تلف حَلقة لعرض عناوين المقالات:

<%= @posts.each do |post| %>
<h1><%= post.title %></h1>
<% end %>


وبعد سنوات من العناء مع هذا التنسيق، اكتشفت وجود مكتبة اسمها Phlex، هي شيئ شبيه بـ JSX ولكن لـ Ruby، بحيث تقدر تكتب HTML باستخدام Ruby وتبني من خلالها Components ويتم تحويل اللي كتبته خلال التشغيل إلى HTML. المكتبة لطيفة ولكن واجهتني مشكلة وهي تحويل أيقونات SVG من HTML إلى Phlex لإضافتها داخل الموقع.

في البداية كنت أحوّل الأيقونات وأضعها داخل باحث، ثم ظهرت فكرة إنشاء مكتبة أيقونات خاصة بـ Phlex تضم داخلها أشهر مكتبات الأيقونات جاهزة للإستخدام. والحمدلله حاليا PhlexIcons تحوي داخلها 7 مكتبات للأيقونات بمجموع يتجاوز الـ 12 ألف أيقونة ولها موقع لعرض الأيقونات والبحث فيها ونسخ الكود لاستخدامه بسهولة داخل مشروعك.

الرابط: https://github.com/AliOsm/phlex-icons

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

وإن كنت ستسأل ما هي منصة باحث، فممكن تعرف من هنا:
https://youtu.be/vl90LkLgfE4

والسلام عليكم 👋🏻
5👍1
كيف نقيس أداء النظام باستخدام الـ Percentiles؟ 🤔

كثير ما نسمع عن p50 و p90 و p95 و p99 في سياق قياس أداء الأنظمة، ولكن شو يعني هذا الكلام وليش بنستخدمه؟

أولا خلينا نفهم شو هو الـ Percentile: ببساطة، الـ Percentile هو قيمة تخبرك أن نسبة معينة من البيانات أقل من أو تساوي قيمة معينة. على سبيل المثال، إذا كان p90 يساوي 100 فهذا يعني أن 90% من البيانات أقل من أو تساوي هذه القيمة و 10٪ أكبر من أو هذه القيمة.

طيب، ليش بنستخدم الـ Percentiles بدل المتوسط؟ 🤨

تخيل معي التالي: عندك نظام وبدك تقيس زمن الاستجابة فيه، وعندك 100 طلب وصلو للنظام:
- 90 طلب استغرقوا 100ms
- 9 طلبات استغرقوا 200ms
- طلب واحد استغرق 10 ثواني (أو 10000ms)

المتوسط في هذه الحالة: ((90 * 100) + (9 * 200) + (1 * 10000)) / 100 = 290ms

هل هذا الرقم يعكس واقع النظام؟ أكيد لا! لأن المتوسط يتأثر بشكل كبير بالقيم المُتطرّفة أو الـ Outliers، وفي حالتنا 99% من المستخدمين ما شافوا هذا الزمن أصلا 😅

هون بتيجي أهمية الـ Percentiles وفي حالة النظام السابق هي كالتالي:

- p50 (في الغالب هو نفسه الوسيط أو Median): 100ms
يعني أن 50% من الطلبات كانت أسرع من أو تساوي 100ms و50% كانت أبطأ.

- p90: 200ms
يعني أن 90% من الطلبات كانت أسرع من أو تساوي 200ms و10% فقط كانت أبطأ.

- p99: 10000ms
يشير إلى أسوأ 1% من الطلبات، والتي كانت بطيئة للغاية.

هذه الأرقام تعطيك صورة أوضح عن أداء النظام، وتقدر تحدد وين المشكلة بالضبط حسب نوعية الطلبات في كل شريحة من شرائح الـ Percentile.

طيب، كيف نحسب الـ Percentiles في SQL على جدول كبير؟ 🤓

في PostgreSQL عندك دالة جاهزة اسمها percentile_cont، استخدامها سهل:

SELECT
percentile_cont(0.5) WITHIN GROUP (ORDER BY response_time) as p50,
percentile_cont(0.9) WITHIN GROUP (ORDER BY response_time) as p90,
percentile_cont(0.95) WITHIN GROUP (ORDER BY response_time) as p95,
percentile_cont(0.99) WITHIN GROUP (ORDER BY response_time) as p99
FROM requests;


ولكن المشكلة أن هذه الدالة بتحتاج تقرأ كل البيانات وترتبهم، وهذا مش عملي على الجداول الكبيرة.

الحل؟ استخدام تقريب أو Approximation مع دالة percentile_disc:

SELECT
percentile_disc(0.5) WITHIN GROUP (ORDER BY response_time) as p50,
percentile_disc(0.9) WITHIN GROUP (ORDER BY response_time) as p90,
percentile_disc(0.95) WITHIN GROUP (ORDER BY response_time) as p95,
percentile_disc(0.99) WITHIN GROUP (ORDER BY response_time) as p99
FROM (
SELECT response_time
FROM requests
TABLESAMPLE SYSTEM(1)
) as sample;


هذا الكود بياخذ عينة عشوائية 1% من البيانات وبحسب عليها الـ Percentiles. النتيجة مش دقيقة 100% ولكنها كافية في معظم الحالات إذا كان الجدول كبير والبيانات متجانسة.

متى نستخدم كل Percentile؟
- p50 يعطيك الصورة العامة للأنظمة في الوضع الطبيعي
- p90 و p95 يساعدان في تحديد المشاكل المحتملة قبل أن تتأثر الغالبية العظمى من المستخدمين
- p99 لضمان تجربة جيدة حتى للمستخدمين في الحالات الشاذة داخل نظامك

نصيحة: لا تكتفي بمراقبة المتوسط، استخدم الـ Percentiles لفهم أعمق لأداء نظامك 🎯

والسلام عليكم 👋🏻
2
من فترة بسيطة تعرّفت على موقع Anna's Archive، وهذا رابطه:
https://annas-archive.li

الموقع عليه ملايين الكتب والأوراق العلمية وممكن تنزلها بصِيغ PDF أو EPUB، وخلال تجربتي وجدت عليه أحدث الإصدارات من كتب مختلفة (في مجال التقنية على الأقل).

أنا هنا لا أناقش حِل أو حُرمانية استخدام الموقع، فهذه كل إنسان يستفتي فيها عالم يثق فيه وفي علمه، ولكن استخدامي الشخصي للموقع حاليا هو التعرّف على محتويات الكتاب بشكل أفضل قبل شراءه، وهذا ما تفعله عند زيارة المكتبات بشكل عام.

كمشتري من أي مكتبة، لك إمكانية تصفح محتويات الكتاب قبل شراءه منها، وهذا يختلف عن العينة أو الـ Sample اللي توفره مواقع زي أمازون، فهي تتيح مقدمة صغيرة من الكتاب والفهرس في غالب الأحيان.

والسلام عليكم 👋🏻
3
علامات التعجب والاستفهام في نهاية دوال لغة Ruby 🤔❗️

من الأمور المميزة في لغة Ruby هو إمكانية إنهاء أسماء الدوال بعلامة التعجّب (!) أو علامة الاستفهام (؟)، هذه الميزة مش لتزيين الدوال أكيد، ولكن لها دلالات مهمة تساعد المبرمجين على فهم سلوك الدالة بشكل أفضل.

🔹 الدوال المنتهية بعلامة الاستفهام (؟) عادةً ما تُستخدم مع الدوال اللي بترجّع قيمة منطقية (true/false)، على سبيل المثال:

10.odd? # => false
"hello".include?("h") # => true


هذه التسمية بتخلي الكود أكثر قابلية للقراءة، فلما تشوف الدالة تنتهي بعلامة استفهام بتعرف مباشرة أنك تتعامل مع قيَم منطقية.

🔸 الدوال المنتهية بعلامة التعجّب (!) تُستخدم غالباً للإشارة إلى أن الدالة قد تكون "خطرة" أو أنها تُعدّل الكائن الأصلي، على سبيل المثال:

string = "hello"
string.upcase # => "HELLO" (لم يتغيّر المُتغَيّر)
string.upcase! # => "HELLO" (تغيّر المُتغَيّر)


الفرق هنا أن upcase مع علامة التعجّب تُعدّل الكائن الأصلي، بينما upcase بدون علامة التعجّب تُرجع نسخة جديدة دون تعديل الأصل.

💡 لماذا هذا مفيد؟
- وضوح الكود: بتقدر تفهم سلوك الدالة من اسمها مباشرة
- الأمان: بتقدر توصّل رسائل للمبرمجين خلال كتابتهم للكود أن الدالة قد تُغير حالة الكائن مثلا
- اتساق التصميم: كل مكتبات اللغة تتبع نفس الأسلوب وهذا يُعطيك أريحية في قراءة الكود وفهمه بشكل أكبر

🔍 ملاحظة مهمة: هذه الاصطلاحات مش إجبارية في Ruby، بس هي ممارسات جيدة متفق عليها في المجتمع بشكل عام، واستخدامها بالطريقة الصحيحة يجعل الكود أكثر وضوحاً وسهولة في التتبّع.

هل مر عليك ميزة شبيهة في لغات ثانية ؟.؟ وهل استخدمت هذه الميزة في Ruby من قبل؟

والسلام عليكم 👋🏻
👍21
ميزة method_missing في Ruby من الميزات اللي بتخليك تحب اللغة أكثر 🤩

تخيّل معي الموقف التالي: عندك object أو كائن ما وحاولت تستدعي دالة غير موجودة عليه، شو بصير؟ في معظم لغات البرمجة رح تشوف error يقولك إنه الـدالة مش موجودة أو MethodNotFound.

في Ruby الموضوع مختلف، لما تستدعي دالة غير موجودة على كائن معيّن، Ruby بتدور على دالة اسمها method_missing على نفس الـكائن، وإذا لقتها بتستدعيها وبتمرر معها اسم الدالة اللي حاولت تستدعيها والـ arguments اللي مررتها.

مثال بسيط:

class User
def method_missing(method_name, *args)
puts "You called #{method_name} with #{args}"
end
end

user = User.new
user.hello("world") # => You called hello with ["world"]


هذه الميزة بتفتح مجال واسع لما يسمّى metaprogramming. على سبيل المثال، إطار العمل Rails يستخدم هذه الميزة في ActiveRecord ORM أو Object Relational Mapper لتمكين البحث في قاعدة البيانات باستخدام أسماء الأعمدة بشكل مباشر. لنفترض أن عندك جدول users فيه عمود name، فممكن تكتب التالي:

User.find_by_name("أحمد") # => يبحث عن المستخدم اللي اسمه أحمد


الدالة اللي اسمها find_by_name مش موجودة أصلا! ولكن Rails يستخدم method_missing لتحليل اسم الدالة وتحويله إلى query على قاعدة البيانات 🪄

تعرّفت على هذه الميزة لأول مرة من خلال كتاب Metaprogramming Ruby للكاتب Paolo Perrotta، وهو من أفضل الكتب اللي قرأتها عن Ruby. الكتاب بشرح كيف Ruby تعمل من الداخل وكيف تقدر تستغل مميزاتها بأفضل طريقة.

نصيحتي لأي شخص مهتم بـ Ruby: اقرأ هذا الكتاب، رح يغيّر نظرتك للغة وطريقة كتابتك للكود 📚

هل مر عليك ميزة شبيهة في لغات ثانية ؟.؟ وهل استخدمت هذه الميزة في Ruby من قبل؟ شاركنا تجربتك 👇

والسلام عليكم 👋🏻
3👍2
كيف تستفيد من Google Colab بعيدًا عن الذكاء الاصطناعي وهمومه 🤔😂

من الاختراعات الجميلة اللي عملتها البشرية هو Google Colab، مفيد جدا في تجربة أفكار مختلفة بشكل سريع وخصوصا لما تحتاج معالج رسومي أو GPU بذاكرة عالية شويتين زي A100 أو T4 مثلا.

ولكن في آخر سنتين بدأت أستخدمه استخدام مختلف قليلا من خلال توفير واجهة للناس لاستخدام بعض المكتبات اللي بعملها أو مشاريع ثانية مفيدة ولكن ما لها واجهة سهلة للاستخدام إلا من خلال الكود أو CLI، بحيث ما أضطر أعمل موقع مثلا وأحطه على خادم وتكاليف ومتابعة وفي نفس الوقت أوصّل الفائدة للمستخدمين.

هذا الأمر عملته إلى الآن مع مكتبتين: تفريغ وتحويل (أنا في الأسماء مُبدِع إبداع رهيب)

تفريغ مهمتها تحويل المواد المرئية والمسموعة إلى نصوص من خلال الذكاء الاصطناعي باستخدام نماذج Whisper أو الـ APIs الخاصة بـ wit.ai.

تفريغ مكتوبة بـ Python وممكن استخدامها من خلال الكود أو CLI، ولكن المستخدم العادي لا يعرف يكتب كود ولا يعرف يستخدم CLI، وأنا ما عندي القدرة على إنشاء SaaS ومتابعتها لتوفير هذه الخدمة للناس.

فكان الحل إنشاء Google Colab Notebook لها واجهة تقبل من المستخدم رابط مادة من YouTube وبعض الإعدادات وتقوم بتحميل المادة وتفريغها وتنزيل المخرجات على جهاز المستخدم مباشرةً.

ممكن تشوف الـ Notebook وكيفية استخدامها من الرابطين التاليين:
- https://tafrigh.ieasybooks.com
- https://youtu.be/qFsUwp5iomU

نفس الفكرة طبَّقتها مع تحويل وهي أداة مهمتها تحويل الكتب من صيغة PDF إلى TXT/DOCX باستخدام Google Drive APIs، ونفس الأمر تكرر، تحويل مكتوبة بـ Python وممكن تستخدمها من خلال الكود أو الـ CLI، ولكن المستخدم العادي...

فكان الحل...

وممكن تشوف الـ...:
- https://tahweel.ieasybooks.com
- https://youtu.be/MsLRFT50pNo

هل هذه الطريقة ناجحة؟ إلى الآن تفريغ تم تنزيلها أكثر من 40 ألف مرة وتحويل أكثر من 12 ألف مرة، وهذا يعطينا تلميح أن الناس قادرة تستخدم الـ Notebooks لما يكون لها واجهة مع وجود شرح بسيط لطريقة الاستخدام.

الخطوة القادمة بإذن الله هي إنشاء Notebooks أو "كُنَّاشات" أكثر لإتمام مهام مختلفة وهذا ما سيتم في هذا المستودع بإذن الله:
https://github.com/ieasybooks/kunnashat

والكُنَّاشة من تعاريفها "الأوراقُ تُجْعَلُ كالدَّفْتَر تُقيَّدُ فيها الفوائدُ والشوارد" حسب موقع المعاني 😁

فمن الكُنَّاشات اللي بفكر أعملها:
- تقطيع لتقطيع المواد المرئية والمسموعة
- تفريق لإزالة الموسيقى عن الصوت
- تنقية لإزالة السكتات من الصوت
- تلخيص لتلخيص النصوص
- تعتيم لتعتيم الوجوه والمشاهد غير الشرعية في المواد
- شعر لإنشاء الشعر العربي
- تشكيل لتشكيل النصوص العربية

كل هذه ممكن تكون مكتبات يُنشأ لها كُنَّاشات أو مجرد كُنَّاشات مبعثرة يستفيد منها الناس.

إذا حاب تساهم ممكن تفتح PR على المستودع وسأكون أكثر من سعيد لمراجعتها، أو ممكن تشاركنا أفكار أخرى لكُنَّاشات يمكن إضافتها.

والسلام عليكم 👋🏻
👍3❤‍🔥111
تطبيقات الهاتف وعبء تطويرها 😪

من الأشياء اللي كانت مطلوبة بكثرة من مستخدمي منصة باحث هي تطبيقات الهاتف للـ Android والـ iOS، وبما اني ما اشتغلت تطبيقات في حياتي إلا مشاريع الجامعة وما عندي ميزانية أجيب مطوّر يشتغلها وما عندي صديق يشتغل التطبيقات (وأنا كسول وما بدي أعمل APIs 😂) فكنت دائما أبتعد عن هذا الأمر.

مع بداية المنصة وفّرت PWA (زي ما هو الوضع في #قبيلة حاليا) ولكن المستخدم العادي ما بيعرف شو هو الـ PWA ولا كيف يثبته على الهاتف، وهذا من أكبر أسباب عدم انتشار الـ PWAs خارج نطاق المنتجات التقنية على حد علمي، وحتى المنتجات التقنية في الغالب تبدأ بـ PWA ثم تنتقل إلى تطبيق هاتف متكامل زي ما صار مع Linear مثلا.

إلى أن أتى الله بالفرَج على يد Rails 😎

تاريخيًّا، Rails فيها ميزة شغالة بشكل تلقائي اسمها Turbolinks، مهمتها انك بمجرد ما تكبس على رابط هي تجيب محتويات الصفحة اللي انت طلبتها وتستبدل الـ Body الخاص بالصفحة الحالية بالـ Body الجديد وتدمج الـ Head الحالي بالـ Head الجديد، فانت بتاخذ تأثير Single Page Application مجانا.

مع إطلاق الإصدار السابع من Rails، أُلغي الدعم عن Turbolinks في مقابل إصدار مكتبة Turbo واللي فيها نفس مميزات Turbolinks مع أشياء إضافية زي ميزة Prefetch بحيث ان المستخدم بمجرد ما يعمل Hover على رابط، Turbo بتعمله Prefetch ولما يضغط عليه، الصفحة بتتغير مباشرة بدون ما ينتظر، وهذا بيعطي إيحاء أن الموقع يستجيب بسرعة.

مكتبة Turbo كانت واحدة من 3 مكتبات أُطلقت تباعا مع الإصدار السابع من Rails وهي Turbo و Stimulus و Native. بطلة المنشور هي مكتبة Native واللي بناء على مميزات Turbo بتسمحلك تبني تطبيقات هجينة أو Hybrid بين الـ WebView والـ Native. بناء على مكتبة Native عملت تطبيقات باحث بأقل القليل من المعرفة في برمجتها واللي ممكن توصلها من هون:
- Android: https://bit.ly/baheth-google-play
- iOS: https://bit.ly/baheth-app-store

المميز إني مش محتاج أفتح APIs وكل التعديلات اللي بعملها على المنصة بتوصل للمستخدمين بدون ما أحتاج أرفع تحديث على المتاجر وقادر أدمج مميزات Native في التطبيقات زي الزر اللي بيفتح القائمة الجانبية أو أفتح نوافذ سفلية أو Bottom Sheets.

الزر على سبيل المثال هو Native ولكن بيفتح القائمة الموجودة في الـ WebView. طريقة الدمج بين المكونات الـ Native والـ WebView سهلة وما فيها تعقيدات كبيرة، ممكن تقرأ عنها من هون:
https://native.hotwired.dev/ios/bridge-components

بهذه الطريقة انت ممكن تطلع بتطبيق لشركتك أو مشروعك الشخصي بدون ما تتكلف تكاليف إضافية أو تجيب مطورين للهاتف ثم مع الوقت ممكن تتحول من الـ Hybrid إلى Native بالكامل، خصوصا وأن المكتبة نفسها تدعم الانتقال من الصفحات الـ Native إلى الـ WebView والعكس.

إذا حاب تشوف تطبيقات ثانية بتشتغل بنفس التقنية ممكن تشوف هذا الموقع:
https://turbonative.directory

والسلام عليكم 👋🏻
5
لا تضع افتراضات غير مدروسة وإلا ستندم 🙂

كان هذا شعار أحد الليالي وأنا في إجازة من العمل مع عدم وجود اتصالٍ جيدٍ بالانترنت 😂

يوجد مكتبة باسم Notable لإطار عمل Ruby on Rails مهمتها حفظ ومتابعة الأخطاء التي قد تحدث أثناء استخدام الموقع أو في الـ Background Jobs من خلال تخزين الخطأ وكل المعلومات المتعلقة به في قاعدة البيانات بشكل تلقائي، كل ما عليك فعله هو تثبيت المكتبة وإنشاء الجداول الخاصة بها في قاعدة البيانات.

بتاريخ 7 من شهر 4 سنة 2024 أضفت ميزة تسجيل الدخول باستخدام حساب Google لمنصة باحث، وكان هذا إنجازا بالنسبة لي لأنها المرة الأولى التي أعمل على شيء من هذا النوع في موقع من المواقع التي أبرمجها. إنتهيت من الميزة الجديدة وأعلنت عنها في مواقع التواصل الاجتماعي المرتبطة بمنصة باحث وانتهى الأمر.

بعد ذلك بخمسة أيام، تحديدا بتاريخ 12 من شهر 4 سنة 2024، وبكل براءة، دخلت على لوحة متابعة قاعدة البيانات الخاصة بمنصة باحث من باب الاطلاع على حجمها والتأكد من أن قاعدة البيانات في حالة جيدة، وكانت المفاجأة! حجم قاعدة البيانات تجاوز الـ 100GB على الرغم من أنها كانت أقل من 10GB قبل أيام قليلة.

المشكلة أن حجم قاعدة البيانات كان يزداد والمساحة التخزينية المتوفرة على الخادم تقل، وكنت أخشى أن لا أتمكن من الدخول عليه من خلال SSH بسبب الخطأ المشهور "No space left on device" 🥲 فكنت أفكر ما الذي حدث وأحاول تصفح باقي لوحات المتابعة في المنصة باتصال انترنت بطيئ، ولكن بدون أي تطوّر.

ثم قررت الهدوووء والبدء بالبديهيات، كم عدد الصفوف في كل جدول من جداول قاعدة البيانات؟ وكانت المفاجأة أن الصفوف في جدول مكتبة Notable تجاوزت عشرات الملايين، ويزداد بسرعة كبيرة جدا!

فتحت الـ Logs الخاصة بالمنصة ووجدت خطأً متكررا بكثرة وهو أن أحد المستخدمين يحاول تسجيل حساب جديد ولكن بدون تحديد الاسم الأول والاسم الأخير (وهي حقول مطلوبة) مما يتسبب في إضافة صف إلى جدول مكتبة Notable على أنه خطأ.

المشكلة الآن كيف يحدث هذا الخطأ؟ الـ Model الخاصة بالمستخدمين في المنصة بها خطوة للتحقق من وجود الحقول المطلوبة ويتم التعامل مع عدم وجودها بشكل صحيح من خلال الـ Controller، فمن أين يأتي هذا الخطأ؟ وكان رد الفعل الطبيعي هو مراجعة التعديلات الخاصة بميزة تسجيل الدخول باستخدام حساب Google 😁

عند تسجيل الدخول باستخدام OmniAuth، يُعطيك الـ Provider (في حالتنا Google) بيانات المستخدم التي طلبتها كالاسم الأول والأخير والبريد الالكتروني. كنت أستخدم هذه البيانات لإنشاء حساب المستخدم وتسجيل دخوله بشكل تلقائي في منصة باحث، وكنت "أفترض" أن الاسم الأول والأخير دائما موجودين في البيانات، وهنا كان الخطأ!

الاسم الأول والاسم الأخير قد تكون قيمتهم nil أو غير مُعرّفة، مما يسبب خطأً في إنشاء حساب المستخدم، ممكن يُرجع خطأً إلى الـ Provider (في حالتنا Google)، والـ Provider يحاول إعادة إرسال نفس الطلب مرة ثانية لباحث فيحدث نفس الخطأ، وهكذا دواليك في حلقة لا تنتهي، وملايين الأخطاء المتكررة دون توقف 😎

الحل السريع كان وضع قيمة افتراضية لحقول الاسم الأول والاسم الأخير بدلا من استخدام البيانات مباشرة من خلال OmniAuth، وحُلّت المشكلة ولله الحمد.

نظّفت قاعدة البيانات بعد ذلك وعادت إلى حجمها الطبيعي وتعلمت أن لا أفترض أي افتراضات غير مدروسة مرة أخرى...

والسلام عليكم 👋🏻
4
هل أنت بحاجة لاستخدام Managed services من الـ Cloud providers لمشروعك الجانبي أو شركتك الناشئة؟ 🤔

للتوضيح، قصدي بالـ Managed services أشياء مثل Auto-scaling في EC2 أو S3 لحفظ البيانات أو غيرها من الخدمات "السحابية" اللي كل الناس تتجه لها أول ما تحكيلها بدي أعمل مشروع جانبي أو شركة ناشئة بمنتج SaaS بسيط، والسبب من وجهة نظري يعود لعاملين:
- سهولة استخدام هذه الخدمات "في البداية"
- الخوف من المجهول إذا ما استخدمتها

عن نفسي، قبل سنتين إلى 3 سنوات، كانت كل مشاريعي موجودة في مكان واحد وهو Heroku، أيام ما كان يقدم حصة مجانية للمستخدمين، وكانت التجربة سهلة لأبعد الحدود، زي كإنك بتستخدم مستودع Git، مجرد ما تعمل عليه Push بكون موقعك جاهز للاستخدام خلال دقائق، التجربة لا مثيل لها في ذلك الوقت (شايفكم جماعة Vercel و Fly.io والشله 😁)

بعد ما صار Heroku مدفوع، استمريت في استخدامه لأشهر معدودة ثم قررت الانتقال لشيئ خارج Heroku والسبب كان بسيط، انا بدفع 15$ شهريا عشان اخذ 512MB ذاكرة و 512MB مساحة تخزين "للتطبيق فقط مش للملفات" و 2 workers، بأقل من هذا المبلغ ممكن تجيب 8GB ذاكرة و 80GB مساحة تخزين و 4 vCPUs من Hetzner على سبيل المثال.

ولكن واجهتني العوامل اللي ذكرتها في أول المنشور، Heroku كان سهل جدا، أنا مجرد بعمل Push وهو يهتم بباقي الأمور، فما كان عندي الخبرة الكافية للانتقال لشيئ أنا أعمله Manage بإيدي، وكنت خايف ما أعرف أستمر في متابعة المشاريع وتطويرها.

إلى أن لقيت خدمة https://hatchbox.io (وهذا إعلان غير مدفوع، للأسف 😂) وهي عبارة عن خدمة تعطيها مستودع Git الخاص بمشروعك المكتوب بـ Ruby on Rails وتختار الـ Cloud Provider اللي انت بتستخدمه زي Linode أو VULTR وهي تحجز الخادم وتعملك Deployment للمشروع تبعك والخدمات الإضافية اللي انت محتاجها زي قاعدة البيانات مثلا، فيك تعتبرها زي Heroku ولكن على أي خادم وبسعر 10$ بالشهر لكل خادم.

في البداية كان العرض ممتاز، انا بدفع على الخادم 5$ وبدفع 10$ لـ HatchBox وباخذ مواصفات أحسن من Heroku بنفس السعر، ولكن بعد فترة اضطريت أضيف خادمين إضافيين، فصرت أدفع 30$ تكاليف HatchBox، ونفسهم أو أكثر منهم بشوي تكاليف الخوادم، فحسيت اني لازم أتعلم كيف أستخدم هالخوادم مع نفسي وأطلع من HatchBox، خصوصا واني واجهت مشاكل خلال استخدام HatchBox وكنت بحلها واستفدت من التواصل مع الدعم الفني تبعهم.

في نفس هذه الفترة، الناس في 37Signals قررو الخروج من الـ Cloud كله وكتأثير جانبي، طلعولنا المكتبة الرهيبة بطلة هذا المنشور وهي Kamal، واللي ممكن تقرأ عنها وتشوف الـ Demo تبعها من هون:
https://kamal-deploy.org

كمال ببساطة بتحكيلك انت أكتب Dockerfile للمشروع تبعك، وعطيني وصول SSH على الخادم تبعك، وأنا بهتم بالباقي، بداية من بناء الـ Docker image وصولا إلى تشغيل الـ Containers الخاصة بالمشروع والخدمات الجانبية زي قاعدة البيانات وتجهيز الـ Reverse proxy وشهادات الـ SSL وكل هذه الأمور.

وفعلا بدأت الإنتقال من HatchBox إلى كمال، وكان الأمر سلس وسهل "لما فهمت كيف Docker بيشتغل"، والحمدلله نقلت كل مشاريعي على خوادم أنا بديرها وبدير كل خدماتها الجانبية من قواعد بيانات وتخزين ملفات.

قللت التكاليف ومواصفات خوادم أفضل وتعلمت أشياء ما كنت بفكر إني أتعلمها، وكالعادة العصافير تزقزق والسلام عليكم 👋🏻

ملاحظة: المنشور القادم تكملة لهذا المنشور 😎
4👍1
تعقيبًا على منشور البارحة

ماذا استفدت خلال وبعد التحوّل من Heroku (وأشباهه) إلى إدارة الخوادم بشكل يدوي؟

🔸 أولا التكاليف | حاليا منصة باحث (ومشاريع غيرها كثير) موجودة على نفس الخادم بالمواصفات التالية:
- معالجات بعدد 16 (vCPU)
- ذاكرة بحجم 128GB
- مساحة تخزينية بحجم 2TB

هذه المواصفات لو بدك تجيبها من مكان زي Fly.io رح تدفع 1000$ شهري تقريبا، في المقابل انت ممكن تجيبها من Hetzner بحدود 100$ (الحسابات مش دقيقة 100% ولكن تقريبيًّا).

🔸 ثانيا التعلّم | خلال هذه التجربة تعلّمت أمور كثيرة جدا، منها:
- إدارة الخوادم (ولو بشكل بسيط)
- تعلّمت Docker وكيف بيشتغل واستخداماته
- كتابة Scripts بتحكي مع الخادم وبتنقل البيانات عليه
- تجهيز لوحات متابعة لموقعك وإضافاته زي قاعدة البيانات
- فهم أكبر لإدارة موارد الخوادم
- كل ما يتعلق بالـ Domains وشهادات SSL

وغيرها من الأمور اللي انت في البداية مارح تعرف تعملها وتضطر تتعلمها وممكن تعطلك فترة بسيطة، ثم تجد أنها سهلة ورح تضيف لخبرتك الشيء الكثير.

🔸 ثالثا الإبداع (ما عرفت ألاقي تعبير أخف 😂) | وجود مثل هذه المواصفات متاحة لك في أي وقت يسمح لك بإطلاق العنان لخيالك، فانت ممكن تحط بيانات ضخمة على الذاكرة أو تخزن ملفات بالآلاف أو تعمل مشروع سريع وتحطه على الخادم بدون ما تفكر مرتين قبل ما تبدأ تنفذ الفكرة وتخاف من توابعها من ناحية "وين رح أرفعها؟".

🔸 رابعًا الحرية | على الخادم الخاص بك ممكن ترفع أي مشروع بأي لغة وبأي تقنية انت بدك تستخدمها، في المقابل بعض الـ PaaS بتدعم أشياء محدودة وما بتقدر تطلع عنها، وأحيانا تكون محكوم حتى بإصدار اللغة اللي ممكن تستخدمه أو إطار العمل. هذا الأمر أبدا مش موجود لما تكون انت مدير نفسك 😎

طيب هل دائما لازم أروح لإدارة الخوادم بشكل يدوي وما أستخدم PaaS أو خدمات Managed من AWS مثلا أو غيره؟ الجواب لا بكل تأكيد، ولكن هدف منشوري السابق وهذا المنشور توضيح أن الناس أصبح في عقلها الباطن أنك يا مبرمج "لا يجب" عليك أن تلمس الخادم، صندوق أسود ومش من واجبنا نفهم شو اللي صاير فيه.

هذه النظرة هي اللي تغيرت عندي وبحاول أغيرها عند الناس من خلال مشاركة مثل هذه التجربة.

أخيرًا، شو أخبار الـ Performance؟

المثال العملي اللي عندي هو منصة باحث واللي بجيها متوسط 155 طلب في الدقيقة على الصفحة الأهم والأثقل وهي صفحة عرض المواد (الدروس والمحاضرات). بدون حساب باقي الصفحات، الـ P99 لهذه الصفحة هو 200ms، والمتوسط 35ms، مع العلم أن المنصة لا تستخدم أي Caching تقريبًا.

في بعض أوقات الذروة يصل عدد الطلبات إلى 1000 طلب في الدقيقة، وأرقام زمن الاستجابة تقريبا لا ترتفع عن الأرقام المذكورة.

بعرف أن عدد الطلبات قليل مقارنة بمواقع ومنصات ثانية، ولكن الأرقام المذكورة هي الطبيعي لأي مشروع جانبي أو شركة ناشئة، ولا داعي لدفع تكاليف أكثر بكثير فقط لأنه "من الممكن" وصول الطلبات لمئات الآلاف في لحظة من لحظات المستقبل البعيد 😁

والسلام عليكم 👋🏻
4
خان المُبرمجين (علي فاضل)
Photo
حطيت صورة لـ Graph زمن الاستجابة في منشور سابق

وسأل أحد الأصدقاء هل هذه الميزة من Ruby on Rails؟ والجواب نعم ولا 😁

إطار عمل Rails معروف باهتمامه بفكرة الـ Convention over Configuration أو "الاعتماد على الاصطلاحات بدلا من الإعدادات"، وهذا أمرٌ لو تعلمون عظيم.

الصورة من المنشور السابق أو الصوَر في هذا المنشور مصدرها مكتبتين لإطار عمل Rails، الأولى اسمها rails_performance والثانية اسمها ActiveInsights وأمنيتي انهم يصيرو مكتبة واحدة 😂

- المكتبتين إعدادهم سهل جدا، مجرد تثبيت للاعتمادية في ملف Gemfile (شبيه بملف package.json لجماعة JS 😛) كالتالي:

gem 'rails_performance'
gem 'activeinsights'


- تشغيل الـ Generators الخاصة بكل مكتبة كالتالي:

rails generate rails_performance:install
rails active_analytics:install:migrations


- إضافة الـ Routes الخاصة بكل مكتبة في ملف routes.rb كالتالي:

mount RailsPerformance::Engine, at: 'rails/performance'
mount ActiveAnalytics::Engine, at: 'rails/activeinsights'


وهكذا انت عندك لوحات متابعة لموقعك تقدر تشوف منها عدد الطلبات وسرعتها والأخطاء اللي بتصير سواءً كان على مستوى الموقع أو صفحات محددة.

الفرق بين المكتبين:
- الأولى تستخدم Redis لتخزين البيانات، بينما الثانية تستخدم قاعدة بياناتك بغض النظر شو كانت
- الأولى صعب تخزن فيها بيانات أكثر من 4 ساعات لأنها تعرض البيانات دفعة واحدة، الثانية ممكن تخزن فيها بيانات أسابيع وأشهر
- الأولى إذا نزّلت 3 اعتماديات إضافية، ممكن تتحصل على بيانات استهلاك المعالج والذاكرة والمساحة التخزينية على الخادم، الثانية لا

الاعتماديات الإضافية الخاصة بالنقطة الأخيرة للمكتبة الأولى:

gem "sys-filesystem"
gem "sys-cpu"
gem "get_process_mem"


لاحظ أن كل هذا بدون إعدادات كثيرة وكله Self-Hosted بدون ما تدفع تكاليف زيادة، الكثير من مكتبات Rails تتبع نفس النمط، مجرد تثبيت للمكتبة و Generators والباقي مجرد فائدة ومتعة للمُطوّر 😎

والسلام عليكم 👋🏻

ملاحظة: الصور من منصة باحث، ولمن سيسأل عن فرق عدد الطلبات بين المكتبين فالسبب أن المكتبة الثانية بقدر ألغي منها تتبع طلبات معينة زي طلبات الـ Health check، بينما الأولى ما بقدر، للأسف.
3
منشور خفيف لطيف لهذا اليوم المبارك 🕌

دائما كنت أنسى أضيف بعض الملفات لملف gitignore في المشاريع اللي بشتغلها، ومن أشهر هذه الملفات ملف DS_Store على نظام تشغيل Mac، وأحيانا لما تكثر هذه الملفات في مستودع Git الخاص بالمشروع بكون حذفها وتنظيف المستودع منها مرهق (مش مستحيل).

إلى أن وجدت هذا الموقع:
https://www.toptal.com/developers/gitignore

انت بتحكيله شو التقنيات اللي بتستخدمها، مثلا Ruby و Rails على نظام تشغيل Mac، وهو بيعملك ملف gitignore فيه كل ما يتعلق بهذه التقنيات جاهز للاستخدام، بدون ما تنسى شيء.

والسلام عليكم 👋🏻
3
السلام عليكم ورحمة الله وبركاته،

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

- الاستخدام المفرط للهجة العامية في المنشورات مضر غير نافع، لا ضير من استخدام العامية بجانب الفصحى، ولكن خلينا نحاول نرتقي بطريقة كتابتنا.

- الأخطاء الإملائية وعدم تنسيق المنشور شيء سيء مش جيد، حاول تنسق منشورك وتهتم فيه، مثلا ما يكون في مسافات كثيرة متتابعة بدون داعي.

- إذا في مصطلح عربي بديل عن الانجليزي حاول تستخدمه وتتبعه بالمصطلح الانجليزي، بعرف المجال التقني صعب فيه هذا الأمر ولكن حاول.

بحب أقرأ منشوراتكم ولكن داخلي هذا الأمر من فترة وحبيت أحكيه لعلنا نرتقي بالمحتوى أكثر، وما ننسى ان ما نكتب اليوم هو بيانات تدريب النماذج غدا، شئنا أم أبينا 😁

ملاحظة: نماذج مثل ChatGPT و Claude بتساعد كثير في مراجعة المحتوى قبل نشره.
7👍1
هل أنت بحاجة Redis ومثيلاتها لأمور مثل الـ Caching والـ Background Jobs في عصر الـ NVMe؟ 🤔

بدايةً، Redis مقاطعة، ولها بدائل كثيرة مثل valkey وهي متوافقة مع Redis بداية من الإصدار 7.2، ولكن ذكرتها لشهرتها ومعرفت الناس بها.

مع الإصدار السابع والثامن لإطار عمل Ruby on Rails، أعلن DHH عن مجموعة مكتبات تحت مسمى Solid وهي:
- SolidCache
- SolidQueue
- SolidCable

الأولى من اسمها مخصصة للـ Caching وهي بديلة لأشياء مثل Redis و Memcached والثانية مخصصة للـ Background Jobs وهي بديلة لأشياء مثل Sidekiq والثالثة والأخيرة مخصصة للـ WebSockets وهي بديلة لأشياء مثل CableReady.

طيب ما المميز في هذه المجموعة من المكتبات؟ اسمها حلو مثلا؟

حقيقة المميز فيها هو اعتمادها على قاعدة البيانات مثل SQLite أو PostgreSQL بدلا من الذاكرة، على عكس كل المكتبات الثانية، فكل من Redis و Memcached و Sidekiq و CableReady تعمل على ذاكرة الخادم بدلا من المساحة التخزينية اللي تستخدمها قاعدة البيانات بشكل أساسي، وكلهم معتمدين على Redis كمكان لتخزين بياناتهم (تحديدا Sidekiq و CableReady).

فكرة مجموعة مكتبات Solid أصبحت ممكنة في عصر المساحات التخزينية المعتمدة على الـ NVMe. كمثال، شركة 37Signals بدأت في استخدام SolidCache في منتجها Basecamp من سنة ونص تقريبا. المُلاحظ كان أن سرعة القراءة من SolidCache كانت أبطأ من Redis بنسبة 40%، ولكن مساحة الـ Cache أصبحت أكبر بـ 6 مرات (10TB!)، وسعرها أرخص بنسبة 80%.

بالمُحصّلة، زمن الاستجابة في Basecamp نزل من 375ms للـ p95 إلى 225ms.

ممكن تقرأ عن تجربتهم من هنا:
https://dev.37signals.com/solid-cache

مثال آخر هو مكتبة SolidQueue، حاليا 37Signals تستخدمها في منتجهم Hey.com وقادرين على معالجة أكثر من 20 مليون Background Job في اليوم، كله بدون استخدام الذاكرة والاعتماد المباشر على قاعدة البيانات.

طيب ليش بحكيلك هالكلام؟ عشان أبهرك مثلا؟

صراحة نعم حاب أبهرك، مع الإصدار الثامن من Ruby on Rails انت فقط محتاج قاعدة بيانات SQLite موجودة على المساحة التخزينية للخادم لدعم الـ Caching والـ Background Jobs والـ WebSockets، بتكلفة قليلة وبدون أي اعتماديات إضافية مثل Redis.

أكيد أُطر عمل ثانية رح تبدأ تتبع نفس النهج مستقبلا، والجميل أن شركة مثل 37Signals تستخدم هذه المكتبات لدعم منتجات حقيقية لها مئات الآلاف (إن لم يكن ملايين) المستخدمين.

والسلام عليكم 👋🏻
4👍1
#تجارب_فاشلة

لسهولة بدأ مشاريع جديدة وتجربة أفكار مختلفة في Ruby on Rails، وجدت أن عندي مشاريع كثيرة وكل فترة بحتاج أبدأ شيء جديد ولكن يستهلك مني وقت في إعداد المشروع من ناحية تثبيت الاعتماديات المطلوبة وتجهيزها بشكل كامل على المشروع.

فقررت في منتصف الليل اني أعمل مكتبة بمجرد ما أضيفها على مشروع Rails الجديد وأشغّل أمر مثل:
rails g package:install


يكون عندي المشروع جاهز من ناحية الاعتماديات وتجهيزها في المشروع، وحتى تحديث إصدارات الاعتماديات ممكن يتم مرة واحدة داخل المكتبة الجديدة وبشكل مباشر تنتقل هذه التحديثات لمشاريعي كلها، الفكرة من بعيد ممتازة.

فعلا، عملت المكتبة وسميتها permadeps (اخصارًا لـ Permanent Dependencies أو الاعتماديات الدائمة) وهذا مستودعها على GitHub:
https://github.com/AliOsm/permadeps

وكنت مبسوط عليها وبدأت أستخدمها في أكثر من مشروع، ولكن بدأت تظهر المشاكل:

🔸 في Rails (وغيرها) ممكن تحدد هل الاعتمادية هي اعتمادية للتطوير فقط (Development Dependency) أو اعتمادية تحتاجها حتى في الـ Production؟ وهذا الأمر كان غير ممكن في حالة permadeps، فكنت مضطر أستخدم كل الاعتماديات في الـ Production واللي هو أمر مش مؤثر بكثرة، مجرد استهلاك إضافي للذاكرة (بحدود 15MB).

🔸 يوجد مكتبتان أساسيتان لكتابة الاختبارات في Rails وهي مكتبة minitest ومكتبة RSpec. بعض مشاريعي كانت تستخدم الأولى والبعض الآخر يستخدم الثانية. فاضطريت أحط الإثنين كاعتماديات في permadeps واللي هو أمر مش لطيف، ولكن ممكن التغاضي عنه، وله نفس مساوئ النقطة السابقة.

🔸 لما عملت permadeps كنت أستخدم Frontend Stack يعتمد على الاعدادات الإفتراضية من Rails واللي بتستخدم ERb، بعد فترة قررت الانتقال إلى Phlex. مبدئيًّا ممكن تحكي الأمور سهلة بس عدّل الاعتماديات في permadeps ولكن بهذه الطريقة أنا محتاج أعدل كل المشاريع عشان تستخدم Phlex واللي هو أمر مرهق وغير ضروري في حالات كثيرة.

🔸 أخيرا، بعض الاعتماديات مثل PgHero وهي عبارة عن لوحة متابعة لقاعدة بيانات PostgreSQL أستخدمها مع المشاريع اللي بتستخدم قاعدة بيانات PostgreSQL فقط، ولكن حتى في المشاريع اللي بتستخدم SQLite مثلا كنت مضطر أنزلها لأنها من اعتماديات permadeps.

بعد هذه التجربة الفاشلة والمشاكل اللي واجهتها، قررت إيقاف مكتبة permadeps والاعتماد على شيء مختلف وهو Rails Templates.

من خلال Rails Templates بتقدر تعمل Setup للكثير من الاعتماديات وإضافة ملفات للمشروع من بدايته وتجهيزه بالطريقة اللي بدك ياها بمجرد إضافة خيار واحد إلى أمر إنشاء المشروع في Rails، فبدل ما تكتب:
rails new blog


ممكن تكتب:
rails new blog -m ~/template.rb


إذا كان الـ Template موجود على الجهاز، أو:
rails new blog -m URL


إذا كان الـ Template موجود على رابط.

ممكن تقرأ أكثر عن Rails Templates من هنا:
https://guides.rubyonrails.org/rails_application_templates.html

والسلام عليكم 👋🏻
1