[{"content":"در ۲۱ اکتبر ۲۰۲۶ GitLab یک patch release بحرانی منتشر کرد که یکی از موارد آن CVE-2026-110264 است، با امتیاز CVSS 10.0 که بالاترین مقدار ممکن است. این ضعف در GitLab CE و EE وجود دارد و در شرایطی خاص به یک کاربر بدون احراز هویت اجازه می‌دهد روی سرور GitLab کد دلخواه اجرا کند. گزارش The Hacker News هم همین را پوشش داده است.\nاگر GitLab را خودتان نصب و نگهداری می‌کنید (self-managed)، اول آپدیت کنید و بعد این مقاله را بخوانید.\nخلاصه شناسه CVE-2026-110264 امتیاز ۱۰٫۰ (Critical) بردار CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H نوع ضعف Integer Overflow در کامپایلر عبارت منظم (regex) گزارش‌دهنده joaxcar، از طریق برنامه‌ی باگ‌بانتی GitLab در HackerOne بردار یعنی: از راه شبکه، با پیچیدگی کم، بدون لاگین و بدون تعامل کاربر قابل بهره‌برداری است و روی محرمانگی، یکپارچگی و در دسترس بودن اثر کامل دارد.\nماجرا چیست؟ طبق توضیح GitLab، ضعف از یک integer overflow هنگام کامپایل یک regex دست‌ساز می‌آید. بر اساس گزارش The Hacker News، این در موتور Onigmo اتفاق می‌افتد که موتور regex داخلی Ruby است و GitLab آن را همراه خودش ارائه و patch می‌کند.\nنکته‌ی نگران‌کننده این است که GitLab شرایط دقیق بهره‌برداری را اعلام نکرده. یعنی فعلاً نمی‌شود با یک تنظیم مشخص مطمئن شد که سرور شما در امان است. طبق گزارش، فعلاً نشانه‌ای از بهره‌برداری فعال نیست و تا ۲۲ اکتبر در فهرست KEV سازمان CISA هم نیامده، ولی این وضعیت می‌تواند سریع عوض شود.\nچه چیزهایی تحت تأثیرند؟ نسخه‌های آسیب‌پذیر، همه‌ی نسخه‌ها از ۷٫۰ تا پیش از این‌ها:\nشاخه آسیب‌پذیر پیش از نسخه‌ی رفع‌شده 19.5 19.5.1 19.5.1 19.4 19.4.3 19.4.3 19.3 19.3.6 19.3.6 19.2 19.2.9 19.2.9 19.1 19.1.9 19.1.9 19.0 19.0.10 19.0.10 7.0 تا 18.11 18.11.13 18.11.13 GitLab.com از قبل patch شده و تنها نصب‌های self-managed باید اقدام کنند. tenantهای GitLab Dedicated با نسخه‌ی 19.3.5-internal0 و 19.4.2-internal0 یا جدیدتر هم رفع‌شده‌اند.\nاگر بعد از ۱۲ اکتبر برای وصله‌ی CVE-2026-97229 (آن هم CVSS 10) آپدیت کرده‌اید، طبق گزارش The Hacker News آن نسخه‌ها (19.2.8، 19.3.5 و 19.4.2) این مورد جدید را ندارند و باید یک بار دیگر آپدیت کنید.\nچه کار کنیم؟ ۱. آپدیت. به نسخه‌ی رفع‌شده‌ی شاخه‌ی خودتان بروید. GitLab هیچ workaround موقتی معرفی نکرده و آپدیت تنها راه مطمئن است.\n۲. به migrationها توجه کنید. نسخه‌های 19.4.3 و 19.3.6 شامل migration دیتابیس‌اند. روی سرور تک‌نود، آپدیت downtime دارد چون migration باید قبل از بالا آمدن GitLab تمام شود. روی نصب چندنودی می‌توانید از روش zero-downtime استفاده کنید.\n۳. تا زمان آپدیت، دسترسی را محدود کنید. اگر نمونه‌ی GitLab شما از اینترنت در دسترس است و فوراً نمی‌توانید آپدیت کنید، دسترسی را موقتاً با فایروال، VPN یا allowlist بسته نگه دارید. این توصیه‌ی رسمی GitLab نیست و فقط یک اقدام احتیاطی عمومی است.\n۴. شناسایی نفوذ. GitLab دو قاعده‌ی تشخیص برای نمونه‌های self-managed منتشر کرده: «Onigmo native worker crash» و «Org mode render error burst». این‌ها را روی لاگ‌های برنامه اجرا کنید (راهنما: Detecting security incidents). اگر نمونه‌تان تا الان از اینترنت قابل دسترس بوده، فایل‌ها، توکن‌ها و runnerهای ناشناس را هم بررسی کنید.\n۵. توکن‌ها و runnerها. چون GitLab معمولاً به کد، secretها و CI دسترسی دارد، در صورت شک به نفوذ، توکن‌ها، متغیرهای CI و کلیدهای deploy را rotate کنید.\nمنابع GitLab Critical Patch Release: 19.5.1 و دیگر نسخه‌ها گزارش The Hacker News Detecting security incidents در GitLab ","permalink":"https://hosseinagharezaei.ir/fa/posts/gitlab-critical-rce-cve-2026-110264/","summary":"\u003cp\u003eدر ۲۱ اکتبر ۲۰۲۶ GitLab یک patch release بحرانی منتشر کرد که یکی از موارد آن \u003ca href=\"https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-5-1-released/\"\u003eCVE-2026-110264\u003c/a\u003e است، با امتیاز \u003cstrong\u003eCVSS 10.0\u003c/strong\u003e که بالاترین مقدار ممکن است. این ضعف در GitLab CE و EE وجود دارد و در شرایطی خاص به یک کاربر \u003cstrong\u003eبدون احراز هویت\u003c/strong\u003e اجازه می‌دهد روی سرور GitLab کد دلخواه اجرا کند. \u003ca href=\"https://thehackernews.com/2026/10/critical-gitlab-flaw-cvss-100-could.html\"\u003eگزارش The Hacker News\u003c/a\u003e هم همین را پوشش داده است.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eاگر GitLab را خودتان نصب و نگهداری می‌کنید (self-managed)، اول آپدیت کنید و بعد این مقاله را بخوانید.\u003c/p\u003e","title":"آسیب‌پذیری بحرانی GitLab با CVSS 10: اجرای کد از راه دور (CVE-2026-110264)"},{"content":"در ۲۱ اکتبر ۲۰۲۶ مرکز ملی امنیت سایبری بریتانیا (NCSC) هشداری با عنوان «Critical security issue affecting PHP» منتشر کرد. دو آسیب‌پذیری در خودِ PHP می‌تواند به مهاجم بدون احراز هویت اجازه‌ی اجرای کد از راه دور (RCE) روی وب‌سروری بدهد که PHP اجرا می‌کند. هر دو مورد در نسخه‌های جدید رفع شده‌اند.\nاگر روی سرورهایتان PHP دارید، اول نسخه را آپدیت کنید و بعد این مقاله را بخوانید.\nخلاصه CVE-2026-109618 CVE-2026-109619 عنوان RCE via OOM corruption RCE via stale global state امتیاز CVSS v4.0 ۹٫۲ (Critical) ۹٫۲ (Critical) بردار AV:N/AC:H/AT:P/PR:N/UI:N AV:N/AC:H/AT:P/PR:N/UI:N نوع ضعف use-after-free، مدیریت نادرست خطا use-after-free، وضعیت global باقی‌مانده هر دو آسیب‌پذیری از راه شبکه، بدون نیاز به لاگین و بدون تعامل کاربر قابل بهره‌برداری‌اند.\nماجرا چیست؟ CVE-2026-109618: PHP برای خطای کمبود حافظه (OOM) از longjmp() استفاده می‌کند. اگر تخصیص حافظه وسط مقداردهی اولیه‌ی داده‌های درخواست شکست بخورد، مرحله‌ی پاک‌سازی درخواست ممکن است داده‌ی نیمه‌ساخته را معتبر فرض کند. نتیجه خرابی حافظه است و در شرایطی RCE. محرک‌ها بیشتر به پردازش درخواست‌های multipart مربوط‌اند: درخواست بدون طول مشخص، تعداد نامحدود هدر در هر بخش، فیلدهای فایل خالی که در max_file_uploads حساب نمی‌شوند و نام فیلدهای تودرتو.\nCVE-2026-109619: در Workerهایی که بین درخواست‌ها زنده می‌مانند، بخشی از وضعیت global (خطا، session، آبجکت و extension) می‌تواند بعد از آزاد شدن حافظه‌ی درخواست هنوز به آن اشاره کند. درخواست بعدیِ همان Worker ممکن است قبل از مقداردهی اولیه‌ی عادی از این وضعیت کهنه استفاده کند و به use-after-free برسد. نمونه‌ی تأییدشده‌ی بهره‌برداری، PHP 8.5 با fatal_error_backtraces فعال و همچنین چرخه‌ی session upload progress است.\nچه چیزهایی تحت تأثیرند؟ نسخه‌های آسیب‌پذیر:\nPHP ۸٫۲ پایین‌تر از 8.2.35 PHP ۸٫۳ پایین‌تر از 8.3.36 PHP ۸٫۴ پایین‌تر از 8.4.27 PHP ۸٫۵ پایین‌تر از 8.5.12 نسخه‌های رفع‌شده: 8.2.35، 8.3.36، 8.4.27 و 8.5.12.\nNCSC تأکید می‌کند هر سازمانی که از PHP استفاده می‌کند در معرض خطر است، از جمله محصولات و appliance‌هایی که PHP را داخل خود دارند. نسخه‌های قدیمی‌تر از ۸٫۲ که پشتیبانی نمی‌شوند هم باید به نسخه‌ی پشتیبانی‌شده ارتقا پیدا کنند.\nاز نظر نحوه‌ی اجرا (طبق advisory رسمی PHP):\nApache mod_php: بهره‌برداری با تنظیمات پیش‌فرض و prefork معمولی روی HTTP تأیید شده است. PHP-FPM: بر اساس تحلیل سورس آسیب‌پذیر است، هرچند exploit کامل نمایش داده نشده. FrankenPHP و LSAPI: احتمالاً آسیب‌پذیرند ولی هنوز تأیید نشده. چه کار کنیم؟ ۱. آپدیت. تنها راه‌حل کامل، ارتقا به یکی از نسخه‌های رفع‌شده است.\n۲. همه‌ی نصب‌های PHP را پیدا کنید. اول سیستم‌های در دسترس از اینترنت، و فقط به نسخه‌های قدیمی بسنده نکنید. کانتینرها، imageهای Docker و محصولات بسته‌بندی‌شده (پنل‌ها، CMSها، appliance‌ها) را هم چک کنید. NCSC هلند فهرستی از نرم‌افزارهای وابسته به PHP منتشر کرده: NCSC-NL/php2shell.\n۳. اگر فوراً نمی‌توانید آپدیت کنید، این کاهش‌دهنده‌ها را اعمال کنید (کامل نیستند):\nmemory_limit=-1 را در سطح سرور تنظیم و همه‌ی Workerها را ری‌استارت کنید. از RLIMIT_AS و RLIMIT_DATA استفاده نکنید چون mmap() را شکست می‌دهند و مسیر آسیب‌پذیر را فعال می‌کنند. post_max_size را محافظه‌کارانه نگه دارید و اندازه‌ی بدنه‌ی درخواست را در فرانت‌اند (Nginx/لودبالانسر) محدود کنید. max_input_nesting_level را کم کنید و تعداد متغیرهای ورودی، بخش‌های multipart، هدرها و آپلودها را محدود کنید. اگر اپلیکیشن از multipart/form-data استفاده نمی‌کند، این درخواست‌ها را در فرانت‌اند ببندید. session.upload_progress.enabled=0 را تنظیم کنید و برای PHP 8.5 مقدار fatal_error_backtraces=0 بگذارید. سپس Workerها را ری‌استارت کنید. اگر عملکرد مهم نیست، pm.max_requests=1 در PHP-FPM وضعیت باقی‌مانده بین درخواست‌ها را از بین می‌برد. ۴. اگر نه آپدیت ممکن است و نه کاهش‌دهنده‌ها، NCSC پیشنهاد می‌کند سیستم را موقتاً آفلاین کنید.\n۵. نشانه‌های نفوذ را بررسی کنید. اگر سیستم تا الان در معرض اینترنت بوده، دنبال backdoor و فایل‌ها یا پردازش‌های ناشناس بگردید.\nمنابع هشدار NCSC GHSA-w8hw-w9fx-j79w (CVE-2026-109618) GHSA-6wmf-4rv5-p3rp (CVE-2026-109619) NCSC-NL/php2shell ","permalink":"https://hosseinagharezaei.ir/fa/posts/php-critical-rce-cve-2026-109618/","summary":"\u003cp\u003eدر ۲۱ اکتبر ۲۰۲۶ مرکز ملی امنیت سایبری بریتانیا (NCSC) هشداری با عنوان \u003ca href=\"https://www.ncsc.gov.uk/news/critical-security-issue-affecting-php\"\u003e«Critical security issue affecting PHP»\u003c/a\u003e منتشر کرد. دو آسیب‌پذیری در خودِ PHP می‌تواند به مهاجم \u003cstrong\u003eبدون احراز هویت\u003c/strong\u003e اجازه‌ی \u003cstrong\u003eاجرای کد از راه دور (RCE)\u003c/strong\u003e روی وب‌سروری بدهد که PHP اجرا می‌کند. هر دو مورد در نسخه‌های جدید رفع شده‌اند.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eاگر روی سرورهایتان PHP دارید، اول نسخه را آپدیت کنید و بعد این مقاله را بخوانید.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"خلاصه\"\u003eخلاصه\u003c/h2\u003e\n\u003ctable\u003e\n  \u003cthead\u003e\n      \u003ctr\u003e\n          \u003cth\u003e\u003c/th\u003e\n          \u003cth\u003eCVE-2026-109618\u003c/th\u003e\n          \u003cth\u003eCVE-2026-109619\u003c/th\u003e\n      \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eعنوان\u003c/td\u003e\n          \u003ctd\u003eRCE via OOM corruption\u003c/td\u003e\n          \u003ctd\u003eRCE via stale global state\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eامتیاز CVSS v4.0\u003c/td\u003e\n          \u003ctd\u003e۹٫۲ (Critical)\u003c/td\u003e\n          \u003ctd\u003e۹٫۲ (Critical)\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eبردار\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003eAV:N/AC:H/AT:P/PR:N/UI:N\u003c/code\u003e\u003c/td\u003e\n          \u003ctd\u003e\u003ccode\u003eAV:N/AC:H/AT:P/PR:N/UI:N\u003c/code\u003e\u003c/td\u003e\n      \u003c/tr\u003e\n      \u003ctr\u003e\n          \u003ctd\u003eنوع ضعف\u003c/td\u003e\n          \u003ctd\u003euse-after-free، مدیریت نادرست خطا\u003c/td\u003e\n          \u003ctd\u003euse-after-free، وضعیت global باقی‌مانده\u003c/td\u003e\n      \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003eهر دو آسیب‌پذیری از راه شبکه، بدون نیاز به لاگین و بدون تعامل کاربر قابل بهره‌برداری‌اند.\u003c/p\u003e","title":"آسیب‌پذیری بحرانی PHP: اجرای کد از راه دور (CVE-2026-109618)"},{"content":"در مقاله‌ی قبل یک Publisher و Worker ساده روی JetStream ساختیم. اما Workerِ آن مقاله فرض می‌کرد پردازش همیشه موفق است. در عمل پیام‌هایی هستند که هر بار fail می‌شوند. اگر کاری نکنیم، یا بی‌نهایت تکرار می‌شوند یا گم می‌شوند.\nدر این مقاله سه چیز را اضافه می‌کنیم:\nمحدود کردن تعداد تلاش‌ها با MaxDeliver فاصله‌ی بین تلاش‌ها با BackOff و NakWithDelay فرستادن پیام «سوخته» به یک صف dead-letter همه‌ی رفتارهای زیر را با یک سرور NATS تعبیه‌شده در Go (با JetStream) و کتابخانه‌ی nats.go آزمایش کرده‌ام و خروجی‌ها از همان آزمایش‌اند.\nساخت Consumer با تنظیمات صریح به‌جای اینکه PullSubscribe یک Consumer پیش‌فرض بسازد، خودمان آن را با تنظیمات دلخواه می‌سازیم:\n_, err = js.AddConsumer(\u0026#34;EVENTS\u0026#34;, \u0026amp;nats.ConsumerConfig{ Durable: \u0026#34;worker-consumer\u0026#34;, AckPolicy: nats.AckExplicitPolicy, AckWait: 30 * time.Second, MaxDeliver: 3, BackOff: []time.Duration{500 * time.Millisecond, time.Second}, FilterSubject: \u0026#34;events.created\u0026#34;, }) MaxDeliver: 3 یعنی هر پیام حداکثر ۳ بار تحویل داده می‌شود. AckWait مدت انتظار برای ack است. اگر Worker در این مدت ack نزند، پیام دوباره تحویل داده می‌شود. BackOff فاصله‌ی تحویل‌های مجدد را مشخص می‌کند. بعد Worker مثل قبل به همین Consumer وصل می‌شود:\nsub, _ := js.PullSubscribe(\u0026#34;events.created\u0026#34;, \u0026#34;worker-consumer\u0026#34;) Nak یعنی چه؟ وقتی پردازش fail شد، دو راه داریم: ack نزنیم و منتظر AckWait بمانیم، یا صریح بگوییم «این پیام را دوباره بده» با Nak. من هر دو را با یک پیام «poison» که همیشه fail می‌شود امتحان کردم:\nروش رفتار مشاهده‌شده m.Nak() بلافاصله دوباره تحویل می‌شود. BackOff اثری ندارد. هر ۳ تلاش در همان ثانیه‌ی صفر انجام شد. m.NakWithDelay(1 * time.Second) بعد از تأخیر داده‌شده دوباره می‌آید (تلاش‌های ۲ و ۳ حدود ثانیه‌ی ۱ و ۲٫۵). ack نزدن طبق BackOff دوباره تحویل می‌شود (در آزمایش من تلاش‌های ۲ و ۳ در ثانیه‌ی ۰٫۵ و ۱٫۵؛ AckWait را برای آزمایش ۲ ثانیه گذاشته بودم). نتیجه‌ی عملی: Nak() ساده برای خطای موقتی خطرناک است، چون یک Worker را در حلقه‌ی تلاش سریع گیر می‌اندازد. برای خطاهایی که احتمالاً با کمی صبر درست می‌شوند (مثلاً دیتابیس لحظه‌ای در دسترس نیست) از NakWithDelay استفاده کن.\nیک Worker کامل‌تر:\nfor _, m := range msgs { if err := process(m.Data); err != nil { log.Println(\u0026#34;process failed:\u0026#34;, err) m.NakWithDelay(time.Second) continue } m.Ack() } وقتی تلاش‌ها تمام شد: Advisory بعد از رسیدن به MaxDeliver، JetStream دیگر پیام را به این Consumer نمی‌دهد. پیام داخل Stream می‌ماند، ولی JetStream یک advisory روی این subject منتشر می‌کند:\n$JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES.\u0026lt;stream\u0026gt;.\u0026lt;consumer\u0026gt; داخل advisory (JSON) شماره‌ی پیام در Stream (stream_seq) و تعداد تحویل‌ها (deliveries) هست. با همین شماره می‌توانیم پیام اصلی را برداریم.\nساخت صف dead-letter یک Stream جدا برای پیام‌های ناموفق می‌سازیم و یک سرویس کوچک به advisory گوش می‌دهد:\njs.AddStream(\u0026amp;nats.StreamConfig{ Name: \u0026#34;DLQ\u0026#34;, Subjects: []string{\u0026#34;dlq.events\u0026#34;}, }) nc.Subscribe(\u0026#34;$JS.EVENT.ADVISORY.CONSUMER.MAX_DELIVERIES.EVENTS.worker-consumer\u0026#34;, func(m *nats.Msg) { var adv struct { Stream string `json:\u0026#34;stream\u0026#34;` StreamSeq uint64 `json:\u0026#34;stream_seq\u0026#34;` Deliveries int `json:\u0026#34;deliveries\u0026#34;` } json.Unmarshal(m.Data, \u0026amp;adv) raw, err := js.GetMsg(adv.Stream, adv.StreamSeq) if err != nil { log.Println(\u0026#34;getmsg:\u0026#34;, err) return } // MsgId جلوی ذخیره‌ی تکراری را می‌گیرد js.Publish(\u0026#34;dlq.events\u0026#34;, raw.Data, nats.MsgId(fmt.Sprintf(\u0026#34;dlq-%d\u0026#34;, adv.StreamSeq))) }) در آزمایش من، سه پیام فرستادم: good-1، poison و good-2. دو پیام سالم یک‌بار تحویل و ack شدند، پیام poison سه بار تحویل شد و بعد در Stream به نام DLQ دقیقاً یک پیام ثبت شد. Consumer هم در پایان هیچ پیام pending یا ack-pending نداشت.\nچند نکته‌ی مهم Advisoryها پیام‌های core NATS هستند، نه JetStream. اگر سرویس DLQ در لحظه‌ی انتشار advisory پایین باشد، آن را از دست می‌دهد. برای سیستم‌های حساس باید راه جبرانی داشته باشی، مثلاً بازبینی دوره‌ای Consumer با ConsumerInfo یا ذخیره‌ی advisoryها در یک Stream. پیام اصلی بعد از رسیدن به MaxDeliver از Stream حذف نمی‌شود. مدت نگهداری‌اش به سیاست retention همان Stream بستگی دارد. خطاهای دائمی (مثلاً payload خراب) فایده‌ای ندارد چند بار retry شوند. اگر خطا را تشخیص می‌دهی، همان لحظه می‌توانی m.Term() بزنی تا JetStream دیگر آن را تحویل ندهد. MsgId در مثال بالا از ذخیره‌ی تکراری در DLQ جلوگیری می‌کند، به شرطی که Stream در پنجره‌ی duplicate-detection خودش باشد. قدم بعدی دو موضوع می‌ماند که می‌خواهم در مقاله‌ی بعد بنویسم: اجرای چند Worker روی یک Consumer، و مانیتورینگ تأخیر پردازش. کد کامل نمونه‌ی پایه در go-nats-demo است.\n","permalink":"https://hosseinagharezaei.ir/fa/posts/nats-jetstream-retry-dlq/","summary":"\u003cp\u003eدر \u003ca href=\"/fa/posts/nats-jetstream-go/\"\u003eمقاله‌ی قبل\u003c/a\u003e یک Publisher و Worker ساده روی JetStream ساختیم. اما Workerِ آن مقاله فرض می‌کرد پردازش همیشه موفق است. در عمل پیام‌هایی هستند که هر بار fail می‌شوند. اگر کاری نکنیم، یا بی‌نهایت تکرار می‌شوند یا گم می‌شوند.\u003c/p\u003e\n\u003cp\u003eدر این مقاله سه چیز را اضافه می‌کنیم:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eمحدود کردن تعداد تلاش‌ها با \u003ccode\u003eMaxDeliver\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eفاصله‌ی بین تلاش‌ها با \u003ccode\u003eBackOff\u003c/code\u003e و \u003ccode\u003eNakWithDelay\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eفرستادن پیام «سوخته» به یک صف \u003cstrong\u003edead-letter\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cblockquote\u003e\n\u003cp\u003eهمه‌ی رفتارهای زیر را با یک سرور NATS تعبیه‌شده در Go (با JetStream) و کتابخانه‌ی \u003ccode\u003enats.go\u003c/code\u003e آزمایش کرده‌ام و خروجی‌ها از همان آزمایش‌اند.\u003c/p\u003e","title":"Retry و Dead-Letter Queue در NATS JetStream با Go"},{"content":"وقتی می‌خواهم یک مفهوم را واقعاً بفهمم، کوچک‌ترین نمونه‌ی قابل‌اجرا از آن را می‌سازم. این‌بار نوبت NATS JetStream بود. نتیجه، پروژه‌ی go-nats-demo است: یک Publisher، یک Worker و خود NATS، همه با Docker Compose.\nچرا JetStream؟ NATS معمولی پیام‌ها را فقط به مشترک‌هایی می‌رساند که همان لحظه متصل‌اند. اگر Worker پایین باشد، پیام از دست می‌رود. JetStream لایه‌ی پایداری روی NATS است: پیام‌ها در یک Stream ذخیره می‌شوند و Consumerها می‌توانند بعداً و با ack دریافتشان کنند.\nساختار go-nats-demo/ ├── docker-compose.yml ├── publisher/ (Dockerfile + main.go) └── worker/ (Dockerfile + main.go) NATS با JetStream و داشبورد مدیریتی روی پورت 8222 Publisher هر ۲ ثانیه یک پیام روی events.created منتشر می‌کند Worker پیام‌ها را می‌خواند، لاگ می‌گیرد و ack می‌زند اتصال با retry در Docker Compose هیچ تضمینی نیست که NATS قبل از سرویس‌های ما بالا بیاید. پس هر دو سرویس تا ۱۰ بار، با فاصله‌ی ۲ ثانیه، اتصال را امتحان می‌کنند:\nfunc connectNATS(url string) *nats.Conn { for i := 0; i \u0026lt; 10; i++ { nc, err := nats.Connect(url) if err == nil { return nc } log.Println(\u0026#34;Waiting for NATS to be ready...\u0026#34;, err) time.Sleep(2 * time.Second) } log.Fatal(\u0026#34;Failed to connect to NATS after 10 attempts\u0026#34;) return nil } Publisher: ساخت Stream و انتشار پیام Publisher اگر Stream وجود نداشته باشد آن را می‌سازد و بعد در یک حلقه پیام منتشر می‌کند:\njs, _ := nc.JetStream() _, err := js.AddStream(\u0026amp;nats.StreamConfig{ Name: \u0026#34;EVENTS\u0026#34;, Subjects: []string{\u0026#34;events.created\u0026#34;}, }) if err != nil \u0026amp;\u0026amp; err != nats.ErrStreamNameAlreadyInUse { log.Fatal(err) } for { msg := []byte(time.Now().Format(time.RFC3339)) if _, err := js.Publish(\u0026#34;events.created\u0026#34;, msg); err != nil { log.Println(\u0026#34;publish error:\u0026#34;, err) } time.Sleep(2 * time.Second) } Worker: Pull Consumer با نام durable نکته‌ی اصلی این است که Worker یک نام durable (worker-consumer) دارد. یعنی JetStream وضعیت خواندن این Consumer را نگه می‌دارد. اگر Worker ری‌استارت شود، از همان‌جا که مانده ادامه می‌دهد و پیام‌های ازدست‌رفته را دریافت می‌کند:\nsub, err := js.PullSubscribe(\u0026#34;events.created\u0026#34;, \u0026#34;worker-consumer\u0026#34;) if err != nil { log.Fatal(err) } for { msgs, err := sub.Fetch(10, nats.MaxWait(5*time.Second)) if err != nil \u0026amp;\u0026amp; err != nats.ErrTimeout { log.Println(\u0026#34;fetch error:\u0026#34;, err) continue } for _, m := range msgs { log.Println(\u0026#34;Received:\u0026#34;, string(m.Data)) m.Ack() } } Fetch(10, ...) تا ۱۰ پیام را یک‌جا می‌گیرد و Ack() به JetStream می‌گوید پردازش تمام شد. پیامی که ack نشود، دوباره تحویل داده می‌شود.\nاجرا git clone git@github.com:h-agharezaei/go-nats-demo.git cd go-nats-demo docker compose up --build بعد داشبورد NATS را روی http://localhost:8222/ ببین. برای آزمایش durable بودن، فقط سرویس worker را متوقف و دوباره بالا بیاور و لاگ‌ها را نگاه کن.\nقدم بعدی این نمونه عمداً ساده است. چیزهایی که برای کار واقعی لازم می‌شوند و می‌خواهم سراغشان بروم: سیاست retry و MaxDeliver، dead-letter، چند Worker روی یک Consumer، و مانیتورینگ تأخیر پردازش.\n","permalink":"https://hosseinagharezaei.ir/fa/posts/nats-jetstream-go/","summary":"\u003cp\u003eوقتی می‌خواهم یک مفهوم را واقعاً بفهمم، کوچک‌ترین نمونه‌ی قابل‌اجرا از آن را می‌سازم. این‌بار نوبت \u003cstrong\u003eNATS JetStream\u003c/strong\u003e بود. نتیجه، پروژه‌ی \u003ca href=\"https://github.com/h-agharezaei/go-nats-demo\"\u003ego-nats-demo\u003c/a\u003e است: یک Publisher، یک Worker و خود NATS، همه با Docker Compose.\u003c/p\u003e\n\u003ch2 id=\"چرا-jetstream\"\u003eچرا JetStream؟\u003c/h2\u003e\n\u003cp\u003eNATS معمولی پیام‌ها را فقط به مشترک‌هایی می‌رساند که همان لحظه متصل‌اند. اگر Worker پایین باشد، پیام از دست می‌رود. \u003cstrong\u003eJetStream\u003c/strong\u003e لایه‌ی پایداری روی NATS است: پیام‌ها در یک Stream ذخیره می‌شوند و Consumerها می‌توانند بعداً و با ack دریافتشان کنند.\u003c/p\u003e","title":"یک Publisher و Worker ساده با NATS JetStream در Go"},{"content":"سلام! من روهام هستم، مهندس نرم‌افزار ارشد در تهران.\nبیشتر با Go و Node.js کار می‌کنم و به معماری تمیز، APIهای کارآمد و جزئیاتی که سیستم‌های بک‌اند را قابل‌اعتماد می‌کنند اهمیت می‌دهم.\nروی چه کارهایی کار می‌کنم طراحی و ساخت سرویس‌ها و APIهای بک‌اند سیستم‌های رویدادمحور با Kafka و NATS JetStream همروندی در Go: گوروتین‌ها، context، اتصال‌پذیری و تاب‌آوری ابزارهای داده‌ی بازار و تحلیل تکنیکال (کندل، اندیکاتور، سیگنال) در حال یادگیری Rust، از طریق یک موتور تحلیل بازار (quant-core) تحلیل کمی و ساختار بازار در چند تایم‌فریم مهارت‌ها زبان‌ها: Go، TypeScript / Node.js (NestJS)، Rust، Python پیام‌رسانی: Apache Kafka، NATS JetStream ابزارها: Docker، Docker Compose، Hugo، GitHub Actions تماس با من GitHub LinkedIn ","permalink":"https://hosseinagharezaei.ir/fa/about/","summary":"\u003cp\u003eسلام! من \u003cstrong\u003eروهام\u003c/strong\u003e هستم، مهندس نرم‌افزار ارشد در تهران.\u003c/p\u003e\n\u003cp\u003eبیشتر با \u003cstrong\u003eGo\u003c/strong\u003e و \u003cstrong\u003eNode.js\u003c/strong\u003e کار می‌کنم و به معماری تمیز، APIهای کارآمد و جزئیاتی که سیستم‌های بک‌اند را قابل‌اعتماد می‌کنند اهمیت می‌دهم.\u003c/p\u003e\n\u003ch2 id=\"روی-چه-کارهایی-کار-میکنم\"\u003eروی چه کارهایی کار می‌کنم\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eطراحی و ساخت سرویس‌ها و APIهای بک‌اند\u003c/li\u003e\n\u003cli\u003eسیستم‌های رویدادمحور با Kafka و NATS JetStream\u003c/li\u003e\n\u003cli\u003eهمروندی در Go: گوروتین‌ها، context، اتصال‌پذیری و تاب‌آوری\u003c/li\u003e\n\u003cli\u003eابزارهای داده‌ی بازار و تحلیل تکنیکال (کندل، اندیکاتور، سیگنال)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"در-حال-یادگیری\"\u003eدر حال یادگیری\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRust\u003c/strong\u003e، از طریق یک موتور تحلیل بازار (\u003ca href=\"https://github.com/h-agharezaei/quant-core\"\u003equant-core\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eتحلیل کمی و ساختار بازار در چند تایم‌فریم\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"مهارتها\"\u003eمهارت‌ها\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eزبان‌ها:\u003c/strong\u003e Go، TypeScript / Node.js (NestJS)، Rust، Python\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eپیام‌رسانی:\u003c/strong\u003e Apache Kafka، NATS JetStream\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eابزارها:\u003c/strong\u003e Docker، Docker Compose، Hugo، GitHub Actions\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"تماس-با-من\"\u003eتماس با من\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/h-agharezaei\"\u003eGitHub\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.linkedin.com/in/hossein-agharezaei/\"\u003eLinkedIn\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"درباره من"},{"content":"خوش آمدید به وبلاگ من! این اولین مقاله‌ای است که در وبسایت شخصی خودم منتشر می‌کنم.\nچرا این سایت را ساختم؟ برای به اشتراک گذاشتن تجربیات و دانش خودم برای یادگیری بیشتر برای ارتباط با افراد علاقه‌مند به موضوعات مشابه ادامه دارد\u0026hellip; به زودی مقالات بیشتری منتشر خواهم کرد. منتظر باشید!\n","permalink":"https://hosseinagharezaei.ir/fa/posts/first-post/","summary":"\u003ch2 id=\"خوش-آمدید-به-وبلاگ-من\"\u003eخوش آمدید به وبلاگ من!\u003c/h2\u003e\n\u003cp\u003eاین اولین مقاله‌ای است که در وبسایت شخصی خودم منتشر می‌کنم.\u003c/p\u003e\n\u003ch2 id=\"چرا-این-سایت-را-ساختم\"\u003eچرا این سایت را ساختم؟\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eبرای به اشتراک گذاشتن تجربیات و دانش خودم\u003c/li\u003e\n\u003cli\u003eبرای یادگیری بیشتر\u003c/li\u003e\n\u003cli\u003eبرای ارتباط با افراد علاقه‌مند به موضوعات مشابه\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ادامه-دارد\"\u003eادامه دارد\u0026hellip;\u003c/h2\u003e\n\u003cp\u003eبه زودی مقالات بیشتری منتشر خواهم کرد. منتظر باشید!\u003c/p\u003e","title":"اولین مقاله من"},{"content":"منتخبی از پروژه‌های عمومی من. بسیاری از آن‌ها تمرین عملی مفاهیمی هستند که می‌خواستم عمیق بفهمم.\nquant-core Rust — موتور تحلیل بازار با کارایی بالا برای تشخیص پرایس‌اکشن، الگوهای فرکتال و ساختار بازار در چند تایم‌فریم. فعلاً روی XAUUSD و EURUSD متمرکز است و برای هر ابزار مالی قابل گسترش است.\ngo-gold-analyzer Go — تحلیل تکنیکال خودکار برای طلا. هر دقیقه داده‌ی Yahoo Finance را می‌گیرد، RSI و MACD و ATR را حساب می‌کند و سیگنال BUY / SELL / HOLD همراه با لاگ تولید می‌کند.\ngo-nats-demo Go — سرویس‌های Publisher و Worker روی NATS JetStream با durable subscription، retry اتصال و داشبورد مدیریتی، همه با Docker.\ngo-kafka-first Go — تمرین عملی Kafka: topic، partition، offset و consumer group، با KRaft و Kafka UI از طریق Docker Compose.\nnestjs-structure TypeScript — ساختار پروژه‌ی NestJS با تنظیمات بر اساس محیط (default، development، production، test).\nیادداشت‌های همروندی در Go آزمایش‌های کوچک روی گوروتین و context: go-goroutine-01، go-context-01، go-connectivity-test.\n","permalink":"https://hosseinagharezaei.ir/fa/projects/","summary":"\u003cp\u003eمنتخبی از پروژه‌های عمومی من. بسیاری از آن‌ها تمرین عملی مفاهیمی هستند که می‌خواستم عمیق بفهمم.\u003c/p\u003e\n\u003ch2 id=\"quant-core\"\u003e\u003ca href=\"https://github.com/h-agharezaei/quant-core\"\u003equant-core\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eRust\u003c/strong\u003e — موتور تحلیل بازار با کارایی بالا برای تشخیص پرایس‌اکشن، الگوهای فرکتال و ساختار بازار در چند تایم‌فریم. فعلاً روی XAUUSD و EURUSD متمرکز است و برای هر ابزار مالی قابل گسترش است.\u003c/p\u003e\n\u003ch2 id=\"go-gold-analyzer\"\u003e\u003ca href=\"https://github.com/h-agharezaei/go-gold-analyzer\"\u003ego-gold-analyzer\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eGo\u003c/strong\u003e — تحلیل تکنیکال خودکار برای طلا. هر دقیقه داده‌ی Yahoo Finance را می‌گیرد، RSI و MACD و ATR را حساب می‌کند و سیگنال BUY / SELL / HOLD همراه با لاگ تولید می‌کند.\u003c/p\u003e","title":"پروژه‌ها"}]