<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های بهنام محمدی</title><link>https://virgool.ir/feed/@behnamm92</link><description>مهندس نرم افزار</description><language>fa</language><pubDate>2026-11-10 22:12:15</pubDate><image><url>https://files.virgool.ir/upload/users/3456/avatar/ga7nTl.jpg</url><title>بهنام محمدی</title><link>https://virgool.ir/@behnamm92</link></image><item><title>Economics of AI Engineering</title><link>https://virgool.ir/@behnamm92/economics-of-ai-engineering-nbawggf9rx40</link><description>شاید برای عقب‌نماندن از هوش‌مصنوعی، باید کمتر پیچیده‌اش کنیم.اگر برای عقب‌نماندن از هوش‌مصنوعی (LLM) هر روز یک Skill جدید نصب می‌کنید، شاید دقیقا دارید عقب می‌مانید.این روزها خیلی از برنامه‌نویس‌ها یک ترس مشترک دارند: نکند ابزار مهمی را نشناسم؟ نکند پرامپت‌هایم حرفه‌ای نباشد؟ نکند بقیه با ده‌ها Agent و Skill چند برابر سریع‌تر از من کار کنند؟و بازار هم دقیقا از همین ترس تغذیه می‌کند.هر روز یک پکیج‌فروش جدید می‌بینیم که توضیح می‌دهد چه فایل‌هایی بسازیم، چطور با هوش‌مصنوعی حرف بزنیم، چه Skillهایی نصب کنیم، چند Agent و Subagent داشته باشیم و چطور چند مدل ضعیف و قوی را به هم متصل کنیم.انگار برای استفاده از مدلی که قرار است زبان طبیعی ما را بفهمد، باید یک زبان و معماری جدید یاد بگیریم.درحالی‌که جهت حرکت خود هوش‌مصنوعی دقیقا برعکس این است.مدل بعدی قرار است برای فهمیدن حرف ما به دستورالعمل کمتری نیاز داشته باشد، نه بیشتر.مدل‌ها هر نسل در فهم منظور کاربر، مدیریت Context، استدلال و استفاده از ابزارها بهتر می‌شوند. بنابراین اگر امروز برای کارکردن با هوش‌مصنوعی مجبوریم یک پرامپت هزارخطی، ده Skill، چند فایل دستورالعمل و پنج Agent دور مدل بسازیم، نباید فورا نتیجه بگیریم که این «معماری آینده» است.ممکن است فقط داریم محدودیت مدل امروز را با پیچیدگی جبران می‌کنیم؛ محدودیتی که چند نسخه بعد خود مدل حلش کند.حتی پیچیدگی بیش از حد می‌تواند علیه خود هوش‌مصنوعی کار کند. وقتی Context را با صدها قانون عمومی، دستورالعمل تکراری، Agentهای متعدد و لایه‌های واسط پر می‌کنیم، مسئله اصلی میان انبوهی از اطلاعات کم‌اهمیت گم می‌شود.مدلی را که برای فهم زبان طبیعی بهینه شده، مجبور می‌کنیم اول معماری‌ای را که دورش ساخته‌ایم بفهمد و بعد تازه برود سراغ مسئله واقعی.این به معنی بد بودن Skill، Agent یا Model Routing نیست. همه این‌ها در جای درست می‌توانند بسیار مفید باشند.مشکل از جایی شروع می‌شود که پیچیدگی به‌عنوان تخصص فروخته می‌شود.وقتی پیچیدگی تبدیل به محصول می‌شوداز نظر اقتصادی هم همیشه ارزان‌ترین مدل، اقتصادی‌ترین انتخاب نیست.گاهی یک مدل ارزان مسئله را خلاصه می‌کند، مدل دوم برنامه می‌نویسد، مدل سوم کد تولید می‌کند و مدل چهارم خروجی بقیه را بررسی می‌کند؛ درحالی‌که ممکن است یک مدل قوی‌تر همان مسئله را با رفت‌وبرگشت کمتر، از دست رفتن Context کمتر و خطای کمتر حل کند.برای یک مقایسه ساده، در زمان نگارش این متن، Opus 5 در API به‌ازای هر یک میلیون توکن ورودی ۵ دلار و خروجی ۲۵ دلار هزینه دارد. یعنی اگر استفاده روزمره و نسبتا سنگین Claude Code را مستقیماً با API انجام دهید، هزینه می‌تواند خیلی سریع به چند صد دلار در ماه برسد.در مقابل، Claude Code همین مدل را داخل اشتراک ماهانه ۲۰ دلاری Pro ارائه می‌کند و پلن Max 5x هم با ۱۰۰ دلار ظرفیت پنج برابر بیشتر می‌دهد.البته Subscription نامحدود نیست و Anthropic هم تعداد ثابت Token یا Session تضمین نمی‌کند؛ اما اصل مقایسه خیلی ساده است:برای یک برنامه‌نویس که روزانه با Claude Code کار می‌کند، انجام همان حجم کار از طریق Subscription می‌تواند چندده برابر ارزان‌تر از مصرف مستقیم API تمام شود.یعنی قبل از اینکه برای کاهش هزینه سراغ چند مدل ارزان‌تر، Router، Agent و معماری پیچیده برویم، شاید ساده‌ترین بهینه‌سازی این باشد که اصلا API را برای کاری که Subscription بسیار ارزان‌تر پوشش می‌دهد، استفاده نکنیم.خیلی وقت‌ها به‌جای اینکه مستقیم یک مدل قوی را برداریم و مسئله‌مان را حل کنیم، وارد دنیایی از API، چند مدل مختلف، Router، Wrapper، Agent، Skill و Integration می‌شویم؛ نه لزوماً چون نتیجه بهتر یا ارزان‌تری می‌دهد، بلکه چون پیچیدگی ناخودآگاه به ما حس «حرفه‌ای‌تر بودن» و کنترل بیشتر می‌دهد.و دقیقا همین‌جا یک بازار آموزشی هم شکل گرفته که استفاده از هوش‌مصنوعی را شبیه یک تخصص بسیار پیچیده نمایش می‌دهد: این فایل را بساز، آن Skill را نصب کن، این مدل را برای Planning بگذار، آن یکی را برای Coding، یک Agent برای Review و یکی دیگر برای هماهنگ‌کردن بقیه.من مخالف Agent، Skill یا Model Routing نیستم؛ وقتی واقعا مسئله‌ای را حل می‌کنند، اتفاقا بسیار ارزشمندند.نقدم به جایی است که پیچیدگی خودش تبدیل به محصول می‌شود.به‌نظرم معیار مهم‌تر از قیمت هر Cost per Successful Outcome توکن است؛ یعنی هزینه‌ای که واقعا برای رسیدن به یک نتیجه درست می‌پردازیم.اگر یک مدل قوی مسئله را در یک رفت‌وبرگشت درست بفهمد ولی سه مدل ارزان‌تر به چند مرحله برنامه‌ریزی، انتقال Context، Retry و Review نیاز داشته باشند، دیگر صرفا مقایسه قیمت توکن تصویر درستی به ما نمی‌دهد.ارزان‌ترین مدل لزوما ارزان‌ترین راه‌حل مسئله نیست.گاهی برای ارزان‌تر کردن Token، کل سیستم را گران‌تر می‌کنیم؛ و گاهی برای حرفه‌ای‌تر به‌نظر رسیدن، چیزی را پیچیده می‌کنیم که مزیت اصلی هوش‌مصنوعی دقیقاً ساده‌کردن آن بوده است.این اشتباه را قبلا هم کرده‌ایماین اولین بار نیست که در صنعت نرم‌افزار یک ابزار یا پترن مفید را به یک قانون عمومی تبدیل می‌کنیم.یک دوره آن‌قدر درگیر معماری‌های عجیب‌وغریب شدیم که برای یک CRUD ساده، حجم زیادی کد، Abstraction و لایه مختلف تولید می‌کردیم. برای اضافه‌کردن یک فیلد ساده گاهی باید DTO، Command، Handler، Mapper، Repository، Interface و چند تست را تغییر می‌دادیم.قبل از عصر LLMها، هزینه این تصمیم‌ها را بیشتر در Developer Experience می‌دیدیم: Learning Curve بالاتر، آنبردینگ سخت‌تر، اشکال‌زدایی کندتر و زمان بیشتری که یک برنامه نویس باید صرف فهمیدن مسیر اجرای یک درخواست می‌کرد.اما حالا همان پیچیدگی یک هزینه جدید هم دارد:هوش‌مصنوعی هم باید تمام این معماری را بفهمد.هرچه یک تغییر ساده میان فایل‌ها، Abstractionها و لایه‌های بیشتری پخش شده باشد، مدل برای انجام همان تغییر به Context بیشتری نیاز دارد. Context بیشتر یعنی فایل‌های بیشتری باید خوانده شوند، توکن بیشتری مصرف می‌شود، احتمال گم‌شدن مسئله اصلی میان اطلاعات فرعی بیشتر می‌شود و در نهایت هزینه و زمان انجام تغییر با AI هم افزایش پیدا می‌کند.یعنی بعضی تصمیم‌های معماری که سال‌ها پیش بیشتر DX را خراب می‌کردند، امروز مستقیما روی هزینه استفاده از هوش‌مصنوعی هم اثر می‌گذارند.اگر برای اضافه‌کردن یک فیلد، هوش‌مصنوعی مجبور باشد ده فایل را بخواند، طبیعتا تغییر آن گران‌تر از سیستمی است که همان رفتار را با فهمیدن دو یا سه فایل بتواند تغییر دهد. (حتی احتمال دوباره کاری به دلیل نفهمیدن Context را هم افزایش می‌دهد)این به معنی «کد کمتر همیشه بهتر است» یا «همه Abstractionها را حذف کنیم» نیست. مسئله، نسبت پیچیدگی به ارزشی است که ایجاد می‌کند.MediatR ابزار خوبی بود؛ تا وقتی که برای یک عملیات ساده مجبور شدیم بین Command، Handler، Behavior و چند فایل حرکت کنیم. میکروسرویس هم راه‌حل قدرتمندی بود؛ تا وقتی که قبل از داشتن مسئله واقعی مقیاس‌پذیری، تمام هزینه‌های یک سیستم توزیع‌شده را وارد پروژه کردیم.مشکل MediatR یا میکروسرویس نبود.مشکل از جایی شروع شد که پترن‌ها جای تفکر را گرفت.و حالا هزینه Over-engineering فقط زمان برنامه‌نویس نیست.هر خط و لایه اضافی که برای فهم یک تغییر لازم است، بخشی از Context Budget هوش‌مصنوعی هم هست.فکر می‌کنم در AI Coding هم در خطر تکرار همین اتفاق هستیم؛ با این تفاوت که این بار زمین بازی بسیار سریع‌تر تغییر می‌کند.ساده بسازیم، چون آینده را نمی‌دانیمما سال‌ها نرم‌افزار را با ذهنیتی عمدتا Deterministic طراحی کرده‌ایم: ورودی مشخص، قانون مشخص و خروجی قابل‌پیش‌بینی.حالا داریم این سیستم‌ها را با لایه‌هایی ترکیب می‌کنیم که Non-deterministic هستند و با سرعت عجیبی هم تکامل پیدا میکنند.مدل بعدی ممکن است دستورالعمل‌ها را بسیار بهتر بفهمد، استفاده از ابزارها بهتر شود، Context بسیار بزرگ‌تر شود یا چیزی که امروز برایش پنج Agent و یک جریان پیچیده ساخته‌ایم، چند ماه دیگر تبدیل به قابلیت عادی خود مدل شود.از آن طرف، کاملا ممکن است مدل‌های آینده آن‌قدر قوی شوند که همین پیچیدگی و بدهی فنی را هم خودشان تشخیص دهند و اصلاح کنند.واقعیت این است که نمی‌دانیم.و دقیقا همین «نمی‌دانیم» برای من مهم است.استدلال من این نیست که ساده بسازیم چون می‌دانیم آینده چگونه خواهد بود. دقیقا برعکس:ساده بسازیم چون نمی‌دانیم آینده چگونه خواهد بود.ممکن است پیچیدگی امروز فردا لازم باشد، ممکن است خود هوش‌مصنوعی آن را حذف کند و ممکن است کاملا بی‌استفاده شود. اما چیزی که امروز می‌دانیم این است که پیچیدگی هزینه دارد، سرعت تغییر را کم می‌کند، نگهداری می‌خواهد و می‌تواند Time-to-Market ما را افزایش دهد.پس چرا امروز برای آینده‌ای که هنوز نمی‌شناسیم، هزینه قطعی پرداخت کنیم؟در چنین محیطی Optionality خودش یک مزیت معماری است. مدل باید قابل تعویض باشد، پرامپت بتواند کوچک‌تر یا حتی حذف شود، Agent بدون جراحی کل سیستم کنار گذاشته شود و قابلیت نسل بعدی مدل نیازمند بازنویسی نصف اکوسیستم ما نباشد.شاید به‌جای تلاش برای ساختن «معماری نهایی AI»، بهتر باشد حداقل معماری لازم برای حل مسئله امروز را بسازیم و فضای کافی برای تکامل پیدا کردن فردا باقی بگذاریم.هدف کسب‌وکار ما نمایش پیچیدگی معماری نیست.هدف این است که امروز با هزینه کمتر یاد بگیریم، سریع‌تر وارد بازار شویم و فردا حق انتخاب بیشتری داشته باشیم.آینده فقط درباره سریع‌تر کدزدن نیستبه‌نظرم تحول بزرگ‌تر هوش‌مصنوعی اصلا سریع‌تر کدزدن نیست.هوش‌مصنوعی دارد مرز میان Business، Product، Design، Engineering، Research و حتی جامعه‌شناسی و روان‌شناسی مشتری را کمرنگ می‌کند. نه به این معنی که این تخصص‌ها حذف می‌شوند، بلکه فاصله و تحویل کار میان آن‌ها کمتر می‌شود.برنامه‌نویس آینده دیگر نمی‌تواند بگوید: «پروداکت‌منیجر تسک را نوشته بود و من هم همان را پیاده کردم.»او باید بفهمد این قابلیت چه مسئله‌ای از مشتری را حل می‌کند، چرا این راه‌حل انتخاب شده، رقبا چطور مسئله را حل کرده‌اند، آیا اصلا لازم است چیزی ساخته شود، چطور می‌توان فرضیه را قبل از توسعه کامل آزمایش کرد و بعد از انتشار قرار است چه چیزی از بازار یاد بگیریم و اصلا چطور مسئله را به هوش‌مصنوعی بفهمانیم.همه برنامه‌نویس‌ها قرار نیست پروداکت‌منیجرشوند؛ اما مهندسی که محصول را نفهمد، به‌تدریج تبدیل به مجری تسک‌هایی می‌شود که هوش‌مصنوعی بهتر و ارزان‌تر از او اجرا می‌کند.به‌نظرم آینده متعلق به Product Engineerهاست؛ افرادی که مسئولیتشان با Merge شدن Pull Request تمام نمی‌شود و از شناخت مسئله و بازار تا طراحی راه‌حل، معماری، پیاده‌سازی، انتشار و سنجش نتیجه را می‌فهمند.برای همین استفاده از مدل‌های قوی هم فقط برای تولید کد مهم نیست. هوش‌مصنوعی باید در تحقیقات بازار، تحلیل رقبا، شناخت رفتار مشتری، به چالش کشیدن فرضیات، تصمیم‌گیری و حتی پیدا کردن چیزی که نباید بسازیم به ما کمک کند.اگر تمام استراتژی هوش‌مصنوعی یک شرکت این باشد که «چطور با ارزان‌ترین مدل Feature بیشتری تولید کنیم؟»، احتمالاً فقط Feature Factory فعلی را سریع‌تر کرده‌ایم.یک Feature Factory مجهز به هوش‌مصنوعی همچنان Feature Factory است؛ فقط با سرعت بیشتری محصول اشتباه می‌سازد. هوش‌مصنوعی نباید فقط فاصله Requirement تا Code را کوتاه کند. باید فاصله مسئله تا یادگیری معتبر از بازار را کوتاه کند.شرکت‌ها به AI Operating Model نیاز دارند، نه فقط ابزار بیشتربه همین دلیل فکر می‌کنم مسئله واقعی شرکت‌ها دیگر فقط خرید یک Coding Assistant، آموزش پرامپت یا نصب چند Agent نیست.شرکت‌ها به یک AI Operating Model نیاز دارند: بدانند کدام مسئله را به کدام مدل بدهند، کجا استفاده از مدل قوی‌تر اقتصادی‌تر است، کجا واقعا Agent لازم دارند و کجا فقط پیچیدگی اضافه می‌کنند.باید بدانند چه قسمت‌هایی از سیستم باید کاملا Deterministic باقی بماند و Non-determinism را کجا و چگونه مدیریت کنند. باید برای Context، Evaluation، Security و Human Review تصمیم آگاهانه داشته باشند و مهم‌تر از همه، هوش‌مصنوعی را وارد Product Discovery کنند، نه اینکه کاربرد آن را به Code Generation محدود کنند. و باید اکوسیستمی بسازند که بتواند همراه مدل‌ها تکامل پیدا کند.فکر نمی‌کنم تفاوت واقعی شرکت‌ها در چند سال آینده در تعداد Agentهایی باشد که نصب کرده‌اند.تفاوت در این خواهد بود که چه کسی می‌تواند هوش‌مصنوعی را از یک ابزار تولید کد، به یک سیستم ساخت و یادگیری محصول تبدیل کند.پس شاید برای عقب‌نماندن از هوش‌مصنوعی لازم نباشد هر روز ابزار جدیدی نصب کنیم.شاید یکی از مهم‌ترین نشانه‌های بلوغ در AI Engineering این باشد که بدانیم چه چیزهایی را نباید اضافه کنیم.در نهایت سؤال مهم این نیست که چند Agent داریم، چند Skill نصب کرده‌ایم یا Prompt ما چند خط است.سؤال این است: آیا با هوش‌مصنوعی فقط سریع‌تر کد تولید می‌کنیم، یا سریع‌تر محصول درست را پیدا می‌کنیم و می‌سازیم؟نوشته شده توسط بهنام محمدی</description><category>بهنام محمدی</category><author>بهنام محمدی</author><pubDate>Wed, 05 Aug 2026 14:35:19 +0330</pubDate></item><item><title>Developer Experience معیاری که نادیده گرفته شد</title><link>https://virgool.ir/codenevis/developer-experience-معیاری-که-نادیده-گرفته-شد-m6x0qqc3wgix</link><description>قابل استفاده بودن و موفق شدن یک نرم افزار به عوامل متعددی بستگی دارد. اما یکی از مهم ترین این عوامل، تجربه کاربری (UX) و در یک نمای کلی تر، تجربه مشتری (CX) است. در واقع، تجربه ای که ما برای کاربر می سازیم کلید موفقیت نرم افزار است.سوالی که در اینجا مطرح می شود این است که چگونه می توانیم تجربه کاربری خوبی را برای کاربران خود رقم بزنیم؟مهم ترین عنصر در اینجا، بهبود دوره ای نرم افزار با استفاده از بازخورد کاربران است. ما باید نرم افزار را به گونه ای تغییر دهیم که نیازهای کاربران را به طور کامل برآورده کند. این امر مستلزم ایجاد تغییرات مداوم در نرم افزار است.مشکلات ناشی از تغییرات مداومبرای مثال، اگر نرم افزار را با استفاده از یک زبان برنامه نویسی سطح بالا مانند جاوا یا سی شارپ نوشته باشیم، اعمال تغییرات به معنای تغییر کلاس ها، توابع، ساختار فایل ها و ... خواهد بود. این تغییرات مداوم و همچنین کدهای نوشته شده توسط افراد مختلف با سبک ها  و دست خط های  متفاوت، پس از مدتی code-base را به وضعیتی غیرقابل توسعه تبدیل می کند.در این وضعیت، درک ساختار کد برای برنامه نویسان دشوار شده و آنها از تغییر کد موجود اجتناب می کنند. در عوض، آنها ترجیح می دهند توابع را به جای استفاده reuse یا extend، از نو بازنویسی (rewrite) کنند. زیرا بازنویسی معمولاً ساده تر از درک کد موجود و تغییر آن است.با گذشت زمان و افزایش عمر نرم افزار، تعداد این توابع موازی با سبک های مختلف کد نویسی افزایش می یابد. در اینجاست که به دلیل دشوار بودن درک و نگهداری کد، مفهوم &#34;Legacy Code&#34; متولد می شود.در واقع، Legacy Code کدی نیست که عملکرد درستی نداشته باشد، بلکه کدی است که هزینه اعمال تغییرات در آن بالا است. این هزینه بالا به طور مستقیم با میزان درک کد توسط توسعه دهندگان رابطه دارد.رابطه بین Developer Experience و Customer Experienceمتأسفانه، این رابطه اغلب نادیده گرفته می شود. به ندرت می بینیم که در انتخاب تکنولوژی ها و معماری ها، به داشتن یک IDE خوب و Learning Curve کوتاه توجهی شود. در عوض، تمرکز همیشه بر روی رفتن به سمت لبه تکنولوژی و دنبال کردن ترندها است. غافل از اینکه تجربه توسعه دهنده (DX) به طور مستقیم تجربه مشتری (CX) را تحت تاثیر قرار می دهد. و در فضای دیگر حتی تعادل بین کار و زندگی برنامه نویسان را به هم میزند زیرا با یک موجود پیچیده به نام Legacy Code طرف هستیم که رفتار آن برای ما قابل پیش بینی نیست و تخمین ها غلط از آب در می آیند.حال این سوال پیش می آید که چگونه می توانیم DX را بهبود ببخشیم؟پاسخ در یک کلمه خلاصه می شود: سادگیسادگی در همه سطوح، از کوچکترین ماژول ها تا معماری کلی نرم افزار برای Integrate کردن این ماژول ها.سادگی کد را قابل فهم تر، قابل نگهداری تر و قابل توسعه تر می کند. همچنین، سادگی باعث می شود که توسعه دهندگان به جای بازنویسی کد، از آن مجددا استفاده کنند یا آن را گسترش دهند چون کد ساده، به سادگی هم درک می شود. در نهایت، سادگی منجر به کاهش هزینه های توسعه، افزایش سرعت توسعه نرم افزار و ماندگاری code-base می شود.</description><category>بهنام محمدی</category><author>بهنام محمدی</author><pubDate>Wed, 06 Mar 2024 02:29:21 +0330</pubDate></item><item><title>نوشتن یک watchdog ساده</title><link>https://virgool.ir/@behnamm92/implement-simple-watchdog-software-mipgbxg82vbt</link><description>اول از همه در مورد مفهوم watchdog صحبت کنیم که اصلا چی هست؟این مفهوم که بیشتر در سخت افزار و برنامه های کامپیوتری mission critical استفاده میشه، کارش اینه که مدام وضعیت healthy یک موجودیت دیگه رو بررسی کنه، و به محض تشخیص معیوب بودن اون سخت افزار یا نرم افزار، مجموعه فرمان های recovery یا alert رو اجرا کنه.رایج ترین نوع recovery الگوریتم ostrich هست که همونطور از نامش پیداست مثل شترمرغ از روی مسئله پیش آمده میپره و بیخیال مشکل میشه و سیستم هدف رو restart میکنه :)برگردیم به مسئله خودمون و پیاده سازی این مفهومصورت مسئلهمی خواهیم یک برنامه single instance داشته باشیم که با selenium یک دستور رو برای crawl کردن تو یک سایتی اجرا کنه، و نکته ای که هست به دلیل وجود rate limit و bot detector توی اون وب سایت باید همه درخواست ها queue بشن و در هر لحظه فقط یک درخواست اجرا بشه و نکته دوم اینه که این سیستم روی ویندوز باید هاست بشه.بدیهیه که با ویندوزی شدن ماجرا کلی از ابزارهای اماده این کار رو از دست میدیم و البته که همیشه هم عجله داریم و باید در کمترین زمان ممکن این کار انجام بشه.الان با چالش های مختلفی رو به رو میشیم که باید همه اونها رو با کمترین ریسورس، که اینجا زمانه حل کنیم.اولین چالش معماری سیستم هست، که crawler و watchdog هر کدوم کجای سیستم باید قرار بگیرن و اصلا health monitoring به چه صورتی انجام بشه؟رایج ترین نوع health check (از این به بعد hc میگیم) به این صورته که یک port مجزا روی برنامه ای که قراره مانیتورینگ روش انجام بشه به بیرون expose میشه و برنامه monitoring که کاملا مستقل اجرا شده این port رو با روش pulling بررسی میکنه و اگر جوابی که انتظار داره رو نگیره (خود برنامه بگه وضعیت خوب نیست یا هیچ جوابی در مدت زمان مشخص نده) وضعیت DOWN به alert manager  اعلام میکنه (مرسومه که در زبان hc وضعیت رو به صورت UP و DOWN اعلام میکنن)خب این روش یه مشکل داره و اون اینه که باید در برنامه crawler کد hc  نوشته بشه و crawler باید بتونه تو این مورد ما، وضعیت سلامت خودشو نگه داره، حالا چون ممکنه برنامه restart هم بشه پس باید اون رو جایی persist کنه.خب تا همینجا کافیه که تشخیص بدیم این روش کلی پیچیدگی داره و کد زیادی باید براش بنویسیم.از اون طرف ما از third party مثل selenium استفاده کردیم که خودش وابسته به browser و فایل اجرایی selenium هست و عملا به دلایل مختلفی هر بخش اون ممکنه crash کنه، ولی watchdog یک برنامه بسیار سبکه که تقریبا مطمئنیم که up-time بالایی داره. بنابراین تصمیم بر این شد خود watchdog مسئول تشخیص سلامت crawler بشه بدون اینکه که crawler اصلا خبر دار بشه که watch dogِی وجود داره.برای این کار ما اومدیم watchdog رو تبدیل به یک reverse proxy کردیم و با عبور دادن همه درخواست ها از اون،  هم تمامی response time نگهداری کردیم و هم تمام منطق hc رو توی اون پیاده سازی کردیم و اجازه دادیم crawler فقط روی منطق خودش تمرکز کنه. https://gist.github.com/behnammohammadi/cbb7cf9a22f93afa12f70c4fd7e4ddde کدی که نوشتیم این منطق رو پیاده میکنه که اگر در 5 دقیقه گذشته تعداد درخواست هایی که به خطا یا timeout خورده بیشتر از درخواست های موفقیت آمیز بشه به شرطی که از اخرین restart کردن سیستم بیشتر از 5 دقیقه گذشته باشد. فرمان restart را به crawler ارسال کنه.نکته مهمی که اینجا وجود داره استفاده از Content.CopyToAsync هست که باعث میشه بدون materialize کردن جواب صرفا stream خونده شده مستقیم به خروجی فرستاده بشه و روی سرعت تاثیر چشم گیری داره.و در اینجا اجرای فرمان restart رو به خود سیستم عامل واگذار کردیم که از طریق دستورات CLI اون رو اجرا میکنه و ما کافیه فقط اون فایل .cmd رو که ساختیم توسط watchdog اجرا کنیم (تابع Restart). https://gist.github.com/behnammohammadi/f155a34b18ab4bb364aab87200cd2e44 حالا برای اینکه خود watchdog رو مطمئن بشیم همیشه در حال اجراست میتونیم استراتژی های مختلفی داشته باشیم ولی در اینجا چون با هر رکوست کلاینت، trigger میشه و اگر خطایی هم رخ بده فقط همون رکوست رو تحت تاثیر قرار میده بنابراین میتونیم این بخش رو بیخیال بشیم و تمرکز رو بذاریم روی up بودن خود اپلیکیشن watchdog.برای این منظور میتونیم برنامه رو به صورت windows service در ویندوز نصب کنیم و recovery mode برای اون مشخص کنیم که در صورت crash کردن برنامه رو restart کنه  یا اون رو در IIS هاست کنیم، ولی خب با این روش ما output console رو از دست میدیم و باید لاگ ها رو جایی persist کنیم تا بتونیم بعدا بخونیم.تو این مورد این خیلی مناسب کیس ما نیست پس تصمیم گرفتیم که هم output console رو داشته باشیم که بتونیم در لحظه عمل debug رو انجام بدیم و هم مکانیزم بازیابی خودکار در صورتی که crash کنه رو داشته باشیم. که البته این روش مشکلاتی رو هم داره مانند اینکه که حتما باید کاربر لاگین شده داشته باشیم و اون session براش باز بمونه ولی تو این کیس ما، این حالت مناسب بود.پس یک فایل اسکریپت ویندوز ساختیم با محتویات زیر که در صورتی که برنامه watchdog کرش کنه و خارج بشه چون توی یک loop هست دوباره به صورت خودکار اجرا میشه https://gist.github.com/behnammohammadi/203867deeac105021fac3b8a7ebe6149 چالش بعدی که داشتیم این بود که درخواست ها همزمان اجرا نشن و سریالی این اتفاق بیفته خب برای این کار هم روش های خیلی زیادی داشتیم که هزینه بر بود به همین منظور خیلی ساده اومدیم از ویژگی lock در برنامه crawler استفاده کردیم و اون بخشی که قراره درخواست رو در وب سایت اجرا کنه رو به صورت critical section نوشتیم و با این روش صف رو پیاده سازی کردیم. https://gist.github.com/behnammohammadi/7b99a63cadc9511c58721b0cb77475e8 همچنین برای پیاده سازی صف زماندار اومدیم از cancellation token استفاده کردیم که داخل critical section وضعیت منقضی شدنش چک میشه که در صورتی که منقضی شده باشه ادامه درخواست پردازش نمیشه.اینجا دیگه کار watchdog ما تموم شد و میتونیم اجراش کنیم و مطمئن باشیم که حواسش به همه چی هست :)</description><category>بهنام محمدی</category><author>بهنام محمدی</author><pubDate>Tue, 02 May 2023 11:55:32 +0330</pubDate></item></channel></rss>