Node Master – Telegram
Node Master
1.03K subscribers
24 photos
2 files
156 links
Group Chat: @nodemastergp
Admin: @napoleon_n1
Download Telegram
یکی از بچه های فعال تو گروه خودمون داخل شرکتشون دنبال یک همکار جدید میگردن.

دوست داشتین رزومه خودتون بفرستین.

https://jobinja.ir/companies/concept-x/jobs/AT2K?_gl=1*z5obhf*_ga*MTU2MzU0NzAzOC4xNzEzMDkxOTU2*_ga_T8HC2S1534*MTczNDQ2MDE1MC41LjEuMTczNDQ2MTMyNS4yNS4wLjA.

#Work
درود دوستان امیدوارم حالتون خوب باشه.
حدود یک ماهی هست هیچ مطلبی رو باهم برسی نکردیم.
خواستم بهتون خبر بدم مدتی هست من با استرس شدیدی درگیر شدم و کلا توانایی تولید محتوا مثل قبل رو ندارم.
از این بابت من از شما معذرت میخوام. و یه صورت موقت مدتی داخل چنل نمی نویسم ولی گروه فعال هستم

جدا از این مسائل ولی هروقت اگر حس کردید من میتونم بهتون کمک کنم pv به من پیام بدین قطعا جواب میدم.

امیدوارم موفق باشین❤️
👍42
Node Master
دلیل این که این کد جذابه این موضوع هست که بعضی قسمت های #NodeJS دسترسی هایی خیلی نزدیک به زبانی مثل C بهت میده. و اون Api نزدیک به Api های low level داخل C هست. نمونه دیگ از این موضوع میتونه وقتی باشه که یک فایل یا سوکت به صورت خام باز میکنید و یکدونه file…
syscall-nodemaster.png
36.2 KB
قبلا در این مثال اشاره کوچکی به File Denoscriptor ها باهم کردیم. امروز با هم یکم عمیق تر میشیم. قبل از هرچیزی بهتر است این موضوع را درک کنیم که وقتی از "File" در اینجا صحبت میکنیم منظور از فایل های ویدیویی و موسیقی و عکس و باینری به تنهایی نیست. در اینجا باید از زاویه دید سیستم عامل به کلمه "File" و معنی اون نگاه کنیم تا بتونیم درک مناسبی داشته باشیم. از زاویه دید OS هر File میتونه یک Directory یا نمونه های بالا که گفتم یا حتی انواع IO Device های مختلف مثل Mouse و Keyboard و البته socket رو نباید فراموش کرد.
شاید گیج شده باشید یا براتون سوال پیش اومده باشه که چرا باید یک File از زاویه دید OS معادل همچین چیز هایی باشه؟ جواب خیلی ساده هست داشتن یک Abstraction خوب با یک Interface یکسان برای کار کردن با انواع مختلف IO Device ها قدرت خیلی زیادی میده و البته توسعه رو خیلی آسون تر میکنه. البته ما به عنوان Backend developer مستقیما با این sys call ها کار نمیکنیم و زبان های برنامه نویسی سطح بلاتر این موضوع رو هنوز Abstract تر کردن و یک Interface ساده تری به ما دادن. درواقع این موضوع کار توسعه دهنده زبان های برنامه نویسی دیگ رو راحت تر کرده تا برای ما بتونن راحت تر یک Interface تمیز و خوب توسعه بدن.

حالا میرسیم به این که FD چیست؟
- یک عدد postive int کوچک میباشد که برای هر Process این عدد ها Unique هستن و Process ما با استفاده از این آیدی هایی که از Kernal اومده میتونه با IO Device های مختلف صحبت کنه. به عنوان مثال FD 123 در یک Process با یک سوکت اشاره داره و در یک Process دیگ به یک text file.

- به صورت کلی File Denoscriptor ها بخشی از POSIX Api هستن و سیستم عامل های UNIX-like دارن.
- روی ویندوز داستان ظاهرا متفاوت هست و یک مفهومی به اسم Handle دارن که جزیاتش رو زیاد نمیدونم و در آینده باهم یادمیگیرم.

اگر هنوز یکم درک موضوع Abstraction که بالاتر اشاره کردم براتون سخته. مثال جذاب زیر براتون روشن میکنه داستان رو.
package main

import (
"fmt"
"net"
"os"
)

const MY_TXT = "NodeMaster Is Alive!"
const WRITE_NET = "WRITE TO TCP SOCKET"
const WRITE_FILE = "WRITE TO FILE"

func main() {
fd, _ := os.OpenFile("myTest.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
nt, _ := net.Dial("tcp", "localhost:3000")
fmt.Println(WRITE_NET)
nt.Write([]byte(MY_TXT))
fmt.Println(WRITE_FILE)
fd.Write([]byte(MY_TXT))
fmt.Println(nt)
fmt.Println(fd)
}

اینجا یک برنامه #Golang خیلی ساده داریم که یک فایل معمولی باز میکنیم و یک tcp socket و MY_TXT رو داخل هردو این ها Write میکنیم و چندتا لاگ ساده داریم که کارمون راحت تر باشه برای پیدا کردن syscall ها برنامه رو build بگیرید و با command زیر برنامه رو اجرا کنید.
در حقیقت وقتی سوکت و یک فایل متنی روی دیسک باز میکنیم اون پشت syscall مربوطه به ما یک File Denoscriptor میده که میتونیم با اون کار هامون رو انجام بدیم.
strace ./main

این strace به ما کمک میکنه که syscall هایی که برنامه ما انجام میده رو trace کنیم. در عکس بالا ما چندین write syscall رو میبینیم که به عنوان arg اول یک File Denoscriptor میگیره و به عنوان arg دوم یک بافر دیتایی که ما میخوایم داخلش بنویسیم.
در شماره یک که ما عدد 6 رو میبینیم این 6 در حقیقت به یک tcp socket اشاره داره و در شماره دو داخل عکس عدد 3 به File denoscriptor مربوط به text file ما روی دیسک اشاره داره. همینطور که میبینید حتی داخل عکس هم بدون دونستن این موضوع اگر نگاه فقط به singture فاکنکشن write کنید از روی file denoscriptor ها به هیچ عنوان متوجه نمیشید که مقصدی که داخلش write میکنیم آیا یک socket هست یا یک فایل روی دیسک یا هر IO Device دیگه ای و دقیقا همین موضوع اون چیزی هست که ما میخوایم و میشه همون Abstraction که بالاتر درموردش صحبت کردیم.

یک نکته این که درسته در #Golang و #Java ما Writer و Reader اینترفیس داریم و حتی اگر سیستم عامل همچین قابلیتی به ما نمیداد دوباره همچین interface هایی وجود داشت ولی کار توسعه دهنده های این زبان ها بسیار سخت تر بود برای ایجاد این interface ها.
حالا دوتا نکته که دوست دارم داخل گروه نظرتون رو بگید و درموردشون صحبت کنیم.
1. داخل عکس بالا چندتا write دیگ هم داریم که عدد 1 رو به عنوان File denoscriptor استفاده کردن. حالا این عدد 1 چی هست؟ داخل گروه خوشحال میشم درموردش صحبت کنیم.
2. چرا از #Golang استفاده کردیم برای مثال؟

بعد از مدت ها این اولین پست من هست امیدوارم براتون مفید باشه و خیلی خیلی ممنونم که همیشه همراه من بودید و امیدوارم همگی موفق باشید رفقا.
👍14
Iman Hosseini Pour
syscall-nodemaster.png
یه فکت درمورد لینوکس هست که میگه:
"همه چیز در لینوکس File هست"
همین یک جمله کافی هست که متوجه بشیم تقریبا وقتی میخوایم با هرچیزی کار کنیم به نوعی با File Denoscriptor ها سرکار داریم. داخل پست قبل داخل عکس بالا یک نکته ای اشاره کرده بودم که File Denoscriptor عدد 1 چی هست؟ باهم جوابش رو اینجا برسی میکنیم.
وقتی یک Process جدید در سیستم عامل ساخته میشه File Denoscriptor های 1,2,3 به صورت رزرو شده هستن و به به Process اختصاص داده میشوند.

0 = stdin
1 = stdout
2 = stderr
داخل عکس پست قبل هرجا از
fmt.Println()

استفاده کرده بودیم در حقیقت داشتیم روی FD 1 مینوشتیم. به صورت خلاصه هروقت console.log میزنیم داریم روی FD 1 مینویسیم. یعنی کنسول هم یک فایل هست. این موضوع منطقی هم هست چون وقتی یک ترمینال باز میکنید اگر
tty

بزنید بهتون آدرس terminal باز شده رو بهتون میده که وقتی Process روش باز میکنید از طریق FD 1 و 2 شما به برنامتون input و output میفرستید و میبینید.
با این تفاسیر وقتی Terminal ما یک file هست پس میتونیم با node:fs داخلش بنویسیم.
import fs from "node:fs";
fs.writeSync(1, Buffer.from("Hello NodeMaster\n"));
👍14
Iman Hosseini Pour
یه فکت درمورد لینوکس هست که میگه: "همه چیز در لینوکس File هست" همین یک جمله کافی هست که متوجه بشیم تقریبا وقتی میخوایم با هرچیزی کار کنیم به نوعی با File Denoscriptor ها سرکار داریم. داخل پست قبل داخل عکس بالا یک نکته ای اشاره کرده بودم که File Denoscriptor عدد…
داشتم داکیومنت مربوط به #Docker میخوندم یک چیزی نظرم رو خیلی جلب کرد و توضیح مربوط به "-i" بود.
https://docs.docker.com/reference/compose-file/services/#stdin_open
من همیشه فکر میکردم برای این که دوتا Process بتونن باهم از طریق چنل های stdin و stdout ارتباط بگیرن نیاز دارن که رابطه Parrent and Child باهم داشته باشند که خب اشتباه میکردم. اشتباه به این بزرگی که اصلا دقت نمیکردم که pipe ها در #Linux اصلا ارتباط Parrent و Child ندارند ولی روی stdin و stdout دارن با هم ارتباط میگیرن.

بزارید این موضوع رو با مثال ببینیم یک کنجکاوی جدید هم برای آینده ایجاد کنیم.
یک ترمینال باز کنید و "ps" رو بزنید که PID مربوط بهش رو دریافت کنید. همونطور که میدونید هر Process هم 3 تا FD به صورت استاندارد برای stdout, stdin, stderr داره. حالا اگر ما یطوری PID مربوط به terminal رو داشته باشیم باید بتونیم روی چنل stdin اون Process دیتا ارسال کنیم و روی ترمینال ببینیمش.
اینجا هست که در لینوکس "/proc" میاد وسط
در این دایرکتوری میتونیم اطلاعات زیادی درمورد وضعیت کرنل بگیریم و یکی از کاراش این هست که میتونیم اطلاعات درمورد Process ها درموردش ببینیم با استفاده از فرمت زیر.
/proc/PID


قبل تر باهم PID مربوط به ترمینالی که باز داریم رو گرفتیم حالا اگر بخوایم میتونیم از اینجا به stdin اون Process دسترسی داشته باشیم باتوجه به این که fd استاندارد stdin برای تمام proccess ها 0 هست.
/proc/4561/fd/0"

خب حالا به عنوان مثال اگر برنامه زیر رو اجرا کنید میبینید که داخل stdin ترمینال شما بدون ارتباط Child and parrent از طریق stdin channel تونستید دیتا ارسال کنید.
import fs from "node:fs";

const stdinFd = fs.openSync("/proc/4561/fd/0", fs.constants.O_WRONLY);

fs.writeSync(stdinFd, Buffer.from("echo Write To stdin - NodeMaster"));

fs.closeSync(stdinFd);

نکته این هست که Sky is the limit. به عنوان مثال میتونید کار سم کنید که http request از طریق stdin بفرستید و response رو از stdout بخونید.
البته رابطه child and parrent همونطوری که تقریبا داخل docker هم میبینیم میتونه بهمون دسترسی بده که این چنل ها رو در دسترس بزاریم یا نه همونطوری که اگر "-i" استفاده نکنیم این چنل در دسترس نیست از طریق داکر. یک طوری مثل عوارضی بزرگ راه در نظر بگیرد.

این کار همینطور که میدونید به نوعی IPC هست اما اینجا یک سوال پیش میاد.
- وقتی نیاز نیست که دوتا Process رابطه Child and parrent داشته باشند تا روی stdin و stdout باهم ارتباط بگیرن. پس کجا محدودیت ایجاد میشه که این دوتا Process نتونن با هم روی این چنل ها ارتباط برقرار کنند؟
اینجا هست که یک ویژگی در کرنل لینوکس به اسم Namespace به ما کمک میکنه که مجموعه های مختلف از Process های ایزوله داشته باشیم و Process که در یک Namespace وجود دارند، نمیتواند با یک Process دیگر که در Namespace دیگر وجود دارد ارتباط روی stdout , stdin چنل بگیرد ( مگر socket )
منطقی هم هست چون namespace رو میشه دوتا machine مختلف در نظر گرفت تقریبا.( این موضوع درست مطلق نیست و بیشتر برای تصویر سازی هست )

حالا میخوام برگردم به مثال بالا اگر دقت کنید من مثل یک فایل رفتار کردم با fd/0. حالا با وجود این فکت که تمام IO device ها به نوعی فایل هستن میتونیم "lsusb" بزنیم فایل مربوط به کیبورد خودمون رو پیدا کنیم و براش درایور بنویسیم. که یک Process دیتا رو از روی کیبورد وقتی تایپ میکنیم بگیره و از طریق stdin مربوط به ترمینال تایپ کردن ما رو بفرسته برای TTY. این یکی رو واقعا دقیق نمیدونم چطور کار میکنه. حتی شاید این جمله یکم اشتباهات هم داشته باشه. ولی در کلیات حس میکنم اون پشت همچین اتفاقی داره میافته. که قطعا یک روز باهم دقیق برسیش میکنیم.
👍20
درود به همگی دوستان.
براتون سال خوش و پر از موفقیتی رو آرزو میکنم.
امیدوارم موفق باشید.🔥
👍30
یک مفهمومی در یادگیری مفاهیم عمیق وجود داره به اسم First principles thinking. خیلی خالصه میشه شکستن یک مسئله پیچیده به مسائل کوچک تر و برسی اون ها از طریق مفاهیم Fundamental. روز به روز که جلوتر میریم این موضوع کم رنگ تر و کم رنگ تر شده تا الان که باتوجه به پیشرفت LLM ها خیلی ها دیگه علاقه ای به داشتن کسب دانش عمیق درمورد یک موضوعی ندارند.
جدا از این موضوع خیلی ها از قدرتی که دانش Fundamental در هر موردی بهشون میده ( در اینجا برنامه نویسی ) خبر ندارن یا علاقه ای بهش ندارن و همین باعث میشه گاهی اوقات در یک Loop ناقص از LLM های مختلف درخواست فیکس کردن باگشون رو کنن یا در فورم های مختلف به دنبال چرایی مشکلشون بگردن و هیچ وقت ممکنه به این موضوع دقت نکنن که چقدر Fundamental میتونه راه گشا باشه براشون و اگر در این مورد خوب بودن خیلی موفق تر بودن.
به عنوان مثال در این سال ها کلی دوره آموزشی، مقاله، بلاگ پست، ویدیو یوتیوب، درمورد Event loop تهیه شده و همه دیدم ولی هیچکس نیومد تو این ویدیو ها به ما بگه که کل Event loop رو به صورت خیلی ساده میتونیم در همین چند خط کد #Clang ببینیم.
حجم چیز هایی که میشه از این man page و این تکه کد یاد گرفت درمورد مفاهیم AsyncIO و کلا IO واقعا مثال زدنی نیست و البته همین موضوع میتونه اهمیت یادگیری مفاهیم سیستم عامل رو دوباره به ما نشون بده.

گاهی اوقات بهتره وقتی یک مسئله ای داریم یک قدم عقب تر بریم و از یک زاویه دیگه بهش نگاه کنیم.

حالا سوال پیش میاد خب ایمان من میخوام Fundamental قوی بشم از کجا شروع کنم؟
فرقی نداره که Frontend dev هستین یا Backend.

سیستم عامل، شبکه، الگوریتم و البته برای FrontDev ها Web Api هم میشه در نظر گرفت.
https://man7.org/linux/man-pages/man7/epoll.7.html
👍20👎1
درود و وقت بخیر دوستان. امیدوارم حالتون خوب باشه.
اخیر یک ویدیو دیدم درمورد این که چطور در Netflix از #Java استفاده میکنن. سوال پیش میاد چرا این ویدیو باید برای ما جالب باشه و اهمیت بدیم؟
باتوجه به این که این روزا به شدت تکنولوژی در حال پیشرفت هست و هر روز ابزارها و فریمورک های جدید رو شاهد هستیم. این حس رو به ما القا میکنه که باید سریع باشیم و این تکنولوژی های جدید رو یاد بگیریم و اگر یاد نگیریم عقب میافتیم و در بازار کار جایی نخواهیم داشت!

منطقی هست باتوجه به این سرعت پیشرفت و AI این حس FOMO خیلی بیشتر شده به خصوص برای دوستانی که تازه کارتر هستن و هنوز وارد بازار کار نشدند. این دسته افراد خیلی بیشتر آسیب میبینن چون تا حالا حقیقت ماجرا که اکثر شرکت ها به شدت نسبت به تغییر این دسته از تکنولوژی ها گارد دارن رو لمس نکردن و همین موضوع باعث ناراحتی و ترس خیلی زیادی میشه.

نکته جالبی که در این ویدیو میبینیم جدا از زاویه دید فنی. زاویه دید بیزینسی هم رو میبینیم که چطور تیم فنی #Netflix رو تحت تاثیر خودش گذاشته که به عنوان مثال درمورد مهاجرت کدبیس ها از #Java 8 به #Java 17 صحبت میکنه که در چندسال پیش انجام شده و این رو به عنوان یک نکته مهم بیان میکنه و درموردش و تاثیراتش صحبت میکنه. دوباره با این حال بعد از این همه تلاشی که کردن روی ورژن های مثل 21 یا 24 که جدیدتر هستن نیومدن و قطعا تا سال چند سال آینده روی همین java 17 خواهند موند.

نکته بعدی خود #Java هست؟ چرا باوجود چیزایی مثل #Golang #Rust از زبانی که برای boomer ها بوده استفاده میکنن؟
خب جواب این هست چرا اصلا استفاده نکنن؟ اکوسیستم خوبی داره سرعت بالایی داره و از همه مهم تر خیلی خیلی Stable هست و از نظر هزینه براشون به صرفه نیست که مهاجرت کنن روی تکنولوژی های دیگه.

این صحبت ها به این معنی نیست که #Java خوب هست یا #Golang یا بقیه زبان ها بد یا خوب هستند. هدف صحبت امروز بیشتر این هست که لزوما برای موفق بودن همیشه نیازی نیست آخرین فریمورک آخرین تکنولوژی Backend خفن رو بلد باشیم. هنوز هم کدبیس های #COBOL هست و #CLang و #C++ به این زودی ها جایی نمیرن و البته چقدر شرکت هایی وجود داره که روی Java 8 و .NET 3.5 هستن و البته #PHP هم هنوز نمرده و نشانه هایی از مردن هم نداره جز در ویدیو های Tech influencer ها.

https://www.youtube.com/watch?v=XpunFFS-n8I
👍18
یکی از ابزار هایی که وقتی با #Postgres کار میکنید و کمتر استفاده میشه ولی خیلی کاربردی هست Window function ها هستن.
به صورت کلی Window function ها این قابلیت رو میدن که دسترسی داشته باشین به مجموعه row های قبل یا بعد از record که در حال حاظر در حال برسی هست.

به عنوان مثال سناریویی رو در نظر بگیرد که نیاز دارید یک سطر X رو با سطر های X+N یا X-N برسی کنید ( row های قبل یا بعد ). یکی از کاربرد هایی که ممکنه براتون داشته باشه داخل کار کردن سناریو هایی است که با Timeseries دیتا ها سرکار دارید.

سینتکس مربوط به استفاده از window function ها به صورت کلی به این صورت هستن.

window_function(arg1, arg2,..) OVER (
[PARTITION BY partition_expression]
[ORDER BY sort_expression [ASC | DESC] [NULLS {FIRST | LAST }])


- منظور از window_function در اینجا اون فانکشنی هست که میخوایم استفاده کنیم به عنوان مثال LAG function
- قسمت PARTITION BY به صورت کلی شباهت هایی به Group by دارد ولی در حال حاظر کاری بهشون نداریم.
- قسمت Order by هم ترتیب مقایسه Row ها رو با سطر بعد یا قبلش مشخص میکنه. دقیقا مثل Order by در حالت معمولی کار میکنه.

به صورت کلی window function های مختلفی داریم ولی برای درک بهتر و این که یک مثال ساده داشته باشیم LAG function هم کاربردی هست هم ساده.
فرض کنید یک table دارید که تعداد فروش محصولات رو برای هر سال دارد.
"year","sales_amount"
"2018","100"
"2019","120"
"2020","150"
"2021","180"

حالا سناریویی رو تصور کنید که میخواید در هر سطر برسی کنید که نسبت به سال قبل چقدر محصول بیشتر فروش داشتین؟ اینجا LAG function به داد شما میرسه
SELECT 
year,
sales_amount,
sales_amount - LAG(sales_amount , 1) OVER (ORDER BY year) AS sales_diff
FROM
sales;

در اینجا ما نیاز داریم که مقدار sales_amount سطر جاری رو از sales_amount سطر قبل که مربوط به سال قبل هست کم کنیم که تفاوت این دو رو بتونیم به دست بیاریم.
حالا Lag 3 تا arg میگیره که به این ترتیب هستن
- نام فیلدی که دیتا مربوط به سطر قبل یا بعدش رو لازم داریم.
- مقدار offset که میتوان عدد منفی به عنوان مثل -1 هم داشت. به صورت پیش فرض عدد 1 هست
- مقدار سوم که در اینجا نداریم default value هست که به صورت پیش فرض Null هست وقتی معمولا پیش میاد که در سطر اول یا اخر در هرکدوم از این سناریو ها ممکنه سطر بعدی یا قبلی وجود نداشته باشه پس در نتیجه یک مقداری باید قرار بگیره که پیش فرض Null هست

حالا وقتی Query رو اجرا کنید همچین نتیجه ای میبینید.
year,sales_amount,sales_diff
2018,100,
2019,120,20
2020,150,30
2021,180,30

جمع بندی:
کلا Window function ها ابزار های قدرتمندی هستن که بهمون خیلی کمک میکنن Query های پیچیده ای بزنیم که ممکنه در بیزینس لاجیک های خاص مخصوصا وقتی با timeseries دیتا کار داریم انجام بدیم.
موضوع بعدی این که ترکیبشون با Subquery یک ترکیب قدرتمند هست که رسما میشه Query هایی رو نوشت که در حالت عادی باتوجه به Data model که داریم ممکنه بدست آوردن اون دیتا غیرممکن باشه و قبل از هرچیزی برای رسیدن به نتیجه وقتی نیاز داریم که دیتا رو یک تغییرات بدیم و بعد از روی اون به اطلاعات برسیم; سناریو خوبی هست برای استفاده از این دو مفهوم.
👍19
Node Master
قرار بر این بود که درمورد تمام موضوعات BackEnd صحبت کنیم. ولی خب تا به امروز فقط درمورد Runtime های مربوط به js بیشتر NodeJS صحبت کردیم. امروز نگاهی به یکی از ویژگی های بسیار خوب #postgres اشاره میکنیم. شما میتونید یک فیلد با تایپ JSON تعریف کنید و دیتا رو…
قبلا در مورد استفاده از jsonb در #postgres صحبت کردیم و به صورت خلاصه اشاره کردیم چرا میتونه خوب باشه. امروز دوباره قراره یک نکته دیگ که خیلی خیلی میتونه مفید باشه یاد بگیرم. این که چطور اطلاعات یک جدول رو تبدیل کنیم به json ؟
حالا سوالی که برامون پیش میاد اصلا چرا باید همچین کاری کنیم؟ به صورت کلی گاهی اوقات نیاز دارید در هنگام Query زدن اطلاعات مربوط به polymorphic table ها رو همه و همه با جزیات در یک Query ببینید. در #MySQL ظاهرا راه حل های Native برای این گونه مسائل وجود داره که در آینده باهم یاد خواهیم گرفت ولی در Postgres با کمک Json ها که آزادی عمل زیادی بهتون میده میتونید هر کاری کنید از جمله حل کردن این گونه مسائل.

فرض کنید یک users table داریم با column های id, name , email. حالا میخواهیم تمام اطلاعات مربوط به هر row رو داخل یک column به اسم user_data داشته باشیم
SELECT to_json(users) AS user_data FROM users;

خب در اینجا ما از فانکشن کمکی to_json کمک گرفتیم که هر row در جدول users رو به json تبدیل کنیم که سطون های جدول users به عنوان key و مقادیر هر row به عنوان value در نظر گرفته میشود. این فانکشن کمکی به صورت کلی یکم محدود هست به این که کل سطون ها رو تبدیل به json میکنه. حالا اگر بخوایم قبل از json شدن روی دیتا مربوط به اون column های خاص یک کاری انجام بدیم مثلا type cast انجام بدیم چکار باید کنیم؟
اینجا json_build_object به نجات ما میاد.
SELECT
json_build_object(
'id',
u.id :: TEXT,
'base_mail_name',
split_part(u.email, '@', 1),
'fqdn',
split_part(u.email, '@', 2)
) AS users_data
FROM
users AS u;

اینجا رسما دیتا مربوط هر row رو میگیرم و دستی به شکلی که میخوایم در Result set نهایی داشته باشیم شکل میدیم. فانکشن json_build_object تعداد زوج از param ها رو میگیره که param های فرد به عنوان Key و param های زوج به عنوان Value نهایی ما در json هستن. فانکشن split_part هم مثل اینجا صرفا برای split کردن یک string هست مثل متد split در #JavaScript عمل میکنه.

به صورت کلی فانکشن های کمکی خیلی زیادی برای کار کردن با json ها در #Postgres هستن ولی این دوتا بین اون ها خیلی کاربردی تر هستن. بقیه خیلی خیلی خاص تر هستن. کلا استفاده از همین ها هم خیلی نمیبینیم چون به صورت روزمره کاربردی نیستن ولی داخل سناریو های خاصی که بالا به یکیش اشاره کردم این ها کمک خیلی بزرگی میکنند. یا حتی در استفاده از Union برای ایجاد یک interface یکسان برای Table های مربوط در Query.

نکته بعدی این که هردو فانکشن بالا ورژن jsonb هم دارند.
to_jsonb
jsonb_build_object

درمورد Performance اطلاعات دقیق ندارم و بیشتر نظر شخصی خودم هست.
- قطعا تاثیر منفی در Performance دارن ولی اونقدر کمک بزرگی میکنند که به هیچ عنوان این تاثیر منفی به چشم نمیاد برای مشکلاتی که از این روش ها استفاده میکنید.
- معمولا مشکلاتی که بالا اشاره کردم شخصا در کدبیس ها دیدم که به هردلیلی سناریو های مختلف که از این طریق میشه رفت جلو رو، در سطح application هندل کردن که خب اونجا قطعا هم دردسر خیلی بیشتری داره برای توسعه هم نگهداری و هم البته وب سرور رو درگیر کاری میکنه که لزوما براش ساخته و بهینه نشده. در نتیجه اینجا اگر تمام این موضوعات در نظر بگیری فدا کردن یک کوچولو Performance دیتابیس خیلی منطقی به نظر میاد.
👍10👎2
درود و وقت همگی بخیر امیدوارم حالتون خوب باشه.
بچه هایی که تازه کار هستن و #Backend رو مدت کمی هست کار میکنن ممکنه یکم براشون سوال باشه که به صورت کلی یک سیستم چه چیزهایی رو دارد و چطور این ها باهم کار میکنند. به جواب رسیدن برای هرکدوم از این سوال ها زمان زیادی ممکنه از ادم بگیره اگر راهنما خوبی هم وجود نداشته باشه.
پیشنهاد میکنم این دوره رو حتما ببینید.
https://downloadly.ir/elearning/video-tutorials/system-design-for-beginners/
بهتون دید خیلی خوبی میده که چه چیزایی رو حداقل باید بدونید و میتونه به عنوان یک Roadmap هم بهش نگاه کنید که در آینده در هرکدوم از بخش های مختلف این آموزش عمیق تر بشید.

اگر باتجربه تر هم هستید و سیستم دیزاین نیاز به refresher دارید یا کلا تا حالا کار نکردین شروع خوبی میتونه باشه.
👍22
درود و خسته نباشید دوستان امیدوارم حالتون خوب باشه.
اگر با lib هایی مثل #jest و #vitest برای پروژه هاتون تست نوشته باشید و البته بعد تلاش کرده باشین که سوییچ کنید روی std test runner خود #NodeJS که خیلی هم از Stable شدنش نمیگذره.
یکی از بزرگترین مشکلاتی که این Test runner داشت و تست نوشتن رو در یک سناریو واقعا آزار دهنده میکرد در آپدیت 22.17 LTS فیکس شده.
assert.partialDeepStrictEqual()

گاهی اوقات پیش میاد که میخواید یک subset از یک object رو assert کنید و نمیخواید کل اون attr های اون object رو assert کنید. تا قبل از این آپدیت این سناریو در STD test runner غیرممکن بود. شخصا واقعا خوشحالم که این رو خیلی سریع متوجه شدن و اضاف کردن چون همه چیزش خیلی خوب شده و فقط همین یدونه کم بود.
👍11
امیدوارم حالتون خوب باشه دوستان.
داخل آپدیت ES2025 یک static method جدید برای به اسم Promise.try اضافه شده و در این پست باهم برسیش میکنیم.
https://telegra.ph/%D9%85%D8%AA%D8%AF-%D8%AC%D8%AF%DB%8C%D8%AF-Promisetry-%D8%AF%D8%B1-ES2025-07-21

البته به صورت تستی با استفاده از telegra.ph شاید بهتر باشه
👍13
درود دوستان.
قبلا که #python کد میزدم یک پکیج داشت به اسم isort که import ها رو خیلی تر تمیز sort میکرد. همیشه دنبال یک پکیج خوب بودم برای #typenoscript که همچین کاری رو انجام بده تا بلاخره دیروز یک پکیح خوب پیدا کردم که میتونید به عنوان config prettier استفاده کنید.
البته package های دیگ هم هستن ولی این خیلی برای من راحت تر بود. فکر کنم eslint هم همچین چیزی داشته باشه ولی فرصت نشده تست کنم.
https://www.npmjs.com/package/prettier-plugin-organize-imports
👍7
Forwarded from amir jahan
Node.js Backend Developer

📍 مکان: تهران – با امکان دورکاری کامل یا هیبریدی
👨‍💻 نوع همکاری: تمام‌وقت یا پاره‌وقت (ساعت کاری منعطف، مبتنی بر خروجی)

درباره ما

ما یک تیم تحقیق و توسعه‌ی پویا هستیم که روی ساخت محصولات دیجیتال نوآورانه با محوریت هوش مصنوعی، داده‌کاوی و سرویس‌های کاربردی وب کار می‌کنیم. تمرکز ما روی طراحی و پیاده‌سازی معماری‌های تمیز، مقیاس‌پذیر و انعطاف‌پذیر برای پروژه‌هایی‌ست که کاربران واقعی و چالش‌های فنی جدی دارند.
در حال حاضر به دنبال یک توسعه‌دهنده‌ی بک‌اند با Node.js هستیم که عاشق حل مسئله و طراحی سیستم‌های پایدار باشه و بتونه در ساخت سرویس‌های مقیاس‌پذیر و حرفه‌ای نقش کلیدی ایفا کنه.

مسئولیت‌ها

طراحی و توسعه‌ی سرویس‌های بک‌اند با استفاده از Node.js (ترجیحاً با Nest.js یا Express.js)

طراحی و پیاده‌سازی APIها (RESTful / GraphQL) با رعایت اصول امنیتی و بهینه‌سازی

اتصال به دیتابیس‌های MongoDB و PostgreSQL و طراحی مدل داده‌ی کارآمد

پیاده‌سازی صف‌های پردازش با Kafka یا RabbitMQ

استفاده از Redis برای کشینگ و بهبود عملکرد سیستم

مشارکت در طراحی معماری سیستم‌ها بر اساس Clean Architecture و Design Patterns

همکاری در Code Review و بهبود کیفیت کد تیم

مستندسازی مؤثر برای ماژول‌ها و سرویس‌ها

مهارت‌ها و تجربه‌ها

تسلط بالا به Node.js و یکی از فریم‌ورک‌های محبوب (Nest.js یا Express.js)

تجربه کار عملی با MongoDB و PostgreSQL

آشنایی با ابزارهای Messaging Queue مثل Kafka یا RabbitMQ

تجربه‌ی استفاده از Redis برای کش و مدیریت Session

آشنایی با مفاهیم Microservices و معماری‌های رویدادمحور (Event-driven)

تسلط به Git و آشنایی با ابزارهای مدیریت پروژه (Jira یا مشابه)

توانایی تست‌نویسی (Unit/Integration)

درک مفاهیم امنیتی وب و استانداردهای OWASP

آشنایی با CI/CD و مفاهیم DevOps امتیاز محسوب می‌شود

چرا اینجا جذابه؟

تیم حرفه‌ای ولی صمیمی داریم

محیط کاری آزمایشی + تحقیقاتی، مناسب عاشقان یادگیری

امکان دورکاری کامل یا حضور در دفتر (اگر تهران باشی)

ساعت کاری شناور؛ تمرکز ما روی نتیجه‌ست، نه زمان

درگیر پروژه‌ای می‌شی که کاربر واقعی، مقیاس‌پذیری و چالش‌های معماری جدی داره

اگر این موقعیت برات جالبه، لطفاً برامون بفرست:

رزومه (حتی اگر خیلی رسمی نیست)

لینک گیت‌هاب یا چندتا از پروژه‌های قبلیت

حقوق پیشنهادی (اختیاری)

مدت زمانی که می‌تونی در هفته همکاری داشته باشی

@amirjaha_n
y2311769@gmail.com
سلام و درود دوستان امیدوارم حالتون خوب باشه.
یک نکته ای که همیشه در پروژه ها میبینم چه در پروژه های Front و چه در پروژه های Backend وقتی با یک HTTP Request کار میکنیم اکثرا URL ها رو به صورت Hardcode میبینیم و اگر پارامتری هم نیاز داشته باشه در نهایت با استفاده از #JavaScript Template Literal کارمون رو پیش میبریم.
به صورت کلی استفاده کردن از Template Literal هیچ مشکلی نداره و کارمون راه میندازه ولی گاهی اوقات ممکنه کمی برامون دردسر ایجاد کنه. برای درک این موضوع به مثال زیر توجه کنید.
import process from "node:process";
const BASE_URL = process.env.BASE_URL;
const url = `${BASE_URL}/posts/1`;
fetch(url);


در اینجا همه چی اوکی کار میکنه مشکلی نیست ولی یک نکته که باید توجه کنیم این هست که حتما BASE_URL ما "/" اضافه نداشته باشد.
https://jsonplaceholder.typicode.com/ 
https://jsonplaceholder.typicode.com


به صورت کلی مسئله خیلی بزرگی نیست ولی همین نکته کوچیک داخل code base که بهش آشنایی ندارید ممکنه ساعت ها ازتون زمان بگیره تا پیداش کنیم. خب حالا سوال پیش میاد که راه حل برای این موضوع چی هست؟

برای حل این موضوع میتونید از URL Web API استفاده کنید. به عنوان مثال اگر کد بالا را بخواهیم Refactor کنیم به این صورت خیلی کارمون تمیز تر و راحت تر میشه و دیگه همچین چیزی رو نمیبینیم.
import process from "node:process";
import { URL } from "node:url";

const url = new URL(process.env.BASE_URL);

const path = "/posts/1";
url.pathname = path;

fetch(url.href);


باتوجه به این که داریم از Web API استفاده میکنیم داخل تمامی Runtime ها به راحتی میتونیم از این API استفاده کنیم و همشون هم به همین شکل کار میکنن.

حالا گاهی اوقات میخوایم querystring مثل زیر داشته باشیم
/post?userId=1&tag=nodejs


دوباره استفاده از Template literal هیچ ایرادی نداره کارمون راه میندازه ولی اگر بخواهیم این رو هم تمیز تر کنیم که در آینده کارمون راحت تر باشه و کد تمیز تری داشته باشیم چطور؟
برای این کار هم میتونیم از سه روش کارمون رو پیش ببریم
1. استفاده از node:querystring که این module فقط استاندارد #NodeJS هست.
2. استفاده از URLSearchParams Web API که باتوجه به این که Web API هست قطعا همه جا پشتیبانی میشه.
3. استفاده از راه حل دوم به صورت غیر مستقیم با استفاده از searchParams property مربوط به URL.

حالا اگر بخواهیم مثال بالا رو Refactor کنیم و همچین چیزی رو اضاف کنیم به این صورت عمل میکنیم.

import process from "node:process";
import { URL } from "node:url";
import querystring from "node:querystring";

const url = new URL(process.env.BASE_URL);
const query = { userId: 1, tag: "NodeMaster" };

// #1 Using querystring module from NodeJS
const path = "/posts";
url.pathname = path;
url.search = querystring.stringify(query);

// #2 Using URLSearchParams
url.pathname = "/posts";
url.search = new URLSearchParams(query).toString();

// #3 Using searchParams property of URL instance
url.pathname = "/posts";
url.searchParams.append("userId", "1");
url.searchParams.append("tag", "NodeMaster");
//
fetch(url.href);

در نگاه اول ممکنه خیلی نکته بزرگی به نظر نیاد ولی داخل code base های بزرگ که با کلی API 3rd party کار میکنید میتونه فرشته نجات باشه.
👍17
درود دوستان امیدوارم حالتون خوب باشه. یک ویژگی خیلی کوچیک #Python داشت که من همیشه دلم میخواد داخل #NodeJS ببینم. این ویژگی خیلی وقته روی #Deno هست ( فکر کنم #BunJS هم داره ). واقعا جای خالیش رو من حس میکردم. و بلاخره این ویژگی رو به صورت Experimental در آپدیت 22.18 دیدیم که اضافه شد. برا این که وارد بحث بشیم دوست دارم با این کد پایتون شروع کنم.
def main():
print("Hello From Main Function")
if __name__ == "__main__":
main()

توضیح کد خیلی ساده هست که با استفاده از این پترن میشه تشخیص داد آیا این بخش از code که داره اجرا میشه آیا import شده توسط یک ماژول دیگه یا ماژول اصلی هست که باهاش برنامه رو اجرا کردن؟ اگر ماژول اصلی باشه که برنامه رو run کردن فانکشن main رو اجرا میکنه برنامه وارد main routine خودش میشه. شاید فکر کنید داخل زبانی مثل #Python و #JavaScript اینکار احمقانه باشه باتوجه به این که هر expressionـی رو میتونیم داخل top level خودمون اجرا کنیم. پس مزیت این کار چیه؟ جواب این هست که باتوجه به این که ما برنامه رو مینویسیم خب ما میدونیم کجا main routine رو اجرا کنیم ولی تصور کنید روی یک code base بزرگ رفتین و دنبال entrypoint میگردید. در این سناریو میتونه به عنوان داکیومنتیشن مناسب باشه. یا زمانی بخواید کدی رو اجرا کنید که فقط و فقط اگر کسی اون ماژول رو import کرده باشه و ... . همین الان هم وقتی پروژه #NestJS دارید bootstrap function دقیقا داره نقش main routine رو بازی میکنه و شما حتما باید اون رو اجرا کنید که برنامتون اجرا بشه. معمولا داخل #NestJS همچین چیزی میبینیم
function bootstrap() {
// init app
}

bootstrap();


سناریویی رو در نظر بگیرد به هر دلیلی میخواید از این main.js یک چیزی رو import کنید( هرچند اگر همچین چیزی نیاز داشتید بهتره سعی کنید راه دیگه ای پیدا کنید ) و اگر شما این فایل رو import کنید داخل یک ماژول دیگه خب bootstrap اجرا میشه و ما این رو نمیخوایم. پس چیکار میتونیم کنیم؟
function bootstrap() {
console.log("hello");
}

if (import.meta.main) {
bootstrap();
} else {
console.log("imported");
}

اینجا هست import.meta.main به کمک ما میاد حالا اگر شما مستقیما node main.js بزنید فانکشن bootstrap اجرا میشه ولی اگر از یک فایل دیگ مثل server.js داشته باشید و این فایل رو import کنید بخش else اجرا میشه و bootstrap هیچ وقت call نمیشه.
👍14
همیشه ما همه تلاش داریم کد با Performance خوب توسعه بدیم بدون این که این موضوع رو تصور کنیم که داخل کدبیس های #JavaScript معمولا Performance شوخیه.
ولی امروز قراره درمورد یک ویژگی جدید که در آپدیت ES2025 به #JavaScript اضافه شده صحبت کنیم که بهمون کمک میکنه که Performance بهتری داشته باشیم. سمت #NodeJS در بیزینس لاجیک های پیچیده میتونه معجزه کنه. برای #FrontEnd هم کاربردی هست ولی باتوجه به این که مرورگر های قدیمی ساپورت نمیکنن خب قطعا به این زودی استفاده ازش رو نمیبینیم.
ویژگی جدید ما اضاف شدن یک static method جدید به Iterator هست.
Iterator.from()

حالا سوال پیش میاد که چطور این به ما کمک میکنه. فرض کنید یک array بزرگ دارید و میخواید data رو map کنید به یک شکل دیگه و برای این کار یک pipeline از map ها رو ایجاد کردید:
const data = [1, 2, 3, 4, 5];

const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);

در نگاه اول مشکلی نداره ولی اگر با عینک Performance ببینیم دوتا مشکل میبینیم.
1. برای هر map مجبوریم یکبار کامل loop بزنیم خب 3 بار loop میزنیم پس داریم O(3n)
2. هربار که یک loop کامل میزنیم هربار داریم یک Array جدید بعد از map ایجاد میکنیم. به صورت خلاصه هر .map برابر هست با یک Array allocation جدید. خب اینجا یک array اورجینال داریم و 3 تا map پس 4 تا array allocation داریم.
ممکنه برای تازه کارترها سوال های زیر پیش بیاد:
1. خب چرا اصلا این استایل کد میزنیم؟
2. چرا همه رو داخل یک map انجام نمیدیم؟

پاسخ سوال اول:
- میتونیم با for ... of کار رو بهتر با یک loop در بیاریم ولی مسئله این هست که معمولا برنامه نویس های #JavaScript در اینجور مواقع حتی بدون این که خودشون بدونن دیدگاه Functional Programming دارن و خب از اونجایی که به صورت فلسفی FP ذات Declarative داره و به صورت فلسفی کار کردن با API ها Declarative خیلی راحت تر و لذت بخش تر از Imperative هست همچین چیزی رو میبینیم.
- اگر هم خیلی کنجکاوید بیشتر بدونید وقتش هست نگاهی به #Elixir #Scala یا حتی Lambda ها در #Java اونجا قشنگ متوجه میشید. یا اصلا مسیر رو برعکس برید و نگاهی به رویکرد #Golang کنید و فرق زمین تا آسمونی رو ببینید.
پاسخ سوال دوم:
- در بزینس لاجیک های پیچیده برای خوانایی کد داشتن map های بیشتر خیلی بهتر از این هست که یک map بزرگ داشته باشیم. منطقی هم هست چون خیلی بهمون God Object ها رو یادآوری میکنه.

خب حالا سوال پیش میاد چیکار کنیم؟ خیلی ساده هست کافیه فقط خط اول رو به این شکل عوض کنیم و array رو تبدیل کنیم به Iterator.
const data = [1, 2, 3, 4, 5, 6]; 
const data = Iterator.from([1, 2, 3, 4, 5, 6]);

خب دوباره الان سوال پیش میاد که WTF الان چی شد؟ سادس.
ما دیتا رو تبدیل کردیم به یک Iterator که ذات Iterator ها به صورت Lazy هست یعنی تا وقتی که نیاز به consume شدن data نباشه هیچ پردازشی انجام نمیشه و اگر هم نیاز به map کردن باشه دقیقا در runtime به صورت on-demand برای هر index تبدیل انجام میشه و ما نیازی به alloc کردن حافظه اضافه برای Array نداریم و هیچ loop اضافه ای هم درکار نیست.

حالا به این نکات توجه کنید:
- هر iterator رو فقط یکبار میشه consume کرد و اگر نیاز باشه باید دوباره ازش بسازی. در حقیقت با .toArray داریم consume کردن رو شبیه سازی میکنیم و دومی مقدار خالی به ما میده به خاطر iterator بودن.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);

data.toArray()
data.toArray()

- در این قسمت به map ها باید توجه کرد که با هر بار call شدن یک Array جدید نمیسازن بلکه یک Iterator جدید که روی Iterator قبلی سوار هست رو به ما میده! پس در نتیجه با توجه به تعریف Iterator که بالاتر گفتم نه loop اضافه ای داریم و نه alloc اضافه.
const data = Iterator.from([1, 2, 3, 4, 5, 6]);

const final = data
.map((item) => item.toString())
.map((item) => `- ${item} -`)
.map((item) => `${item} ${new Date()}`);

حالا اگر یکم بیشتر دقت کنی میبینیم خیلی شبیه به stream ها هست. اصلا این دوتا api به شدت باهم سازگار هستن. در این حد که استریم ها رو میشه تبدیل کرد به iterator و برعکس. بقیه کد هم دقیقا به صورت مشابهه کار میکنه.
import { Readable } from "node:stream";
const data = Iterator.from([1, 2, 3, 4, 5, 6]);
const streamData = Readable.from(data);

دل نوشته:
حقیقتا دیگ نمیشه تفاوت بین stream, iterator, generator, rxjs, web stream, رو تشخیص داد😂. همشون رو میتونی جایگزین هم استفاده کنی. ( دلایل مختلفی برای وجود این همه api برای یک کار هست )
👍16
درود رفقا امیدوارم حالتون خوب باشه.
بلاخره تلسم رو شکوندم بعد از چند ماه این ویدیو رو گرفتم.
در این ویدیو باهم یاد میگیرم که چطور از AsyncLocalStorage استفاده کنیم در #NodeJS البته قبل از هرچیزی میریم نگاهی به react context در #React میکنیم که از بچه های #FrontEnd یاد بگیرم چطور همچین مسائلی رو که AsyncLocalStorage به ما کمک میکنه حل کنیم رو با react context حل میکنن.

https://youtu.be/B_s401HuZAU
👍18