زمان shutdown در GenServer به چه دلیل می باشد؟

درود خدمت شما دوستان عزیز:

در آموزش های مربوط به otp در قسمت Genserver یک پارامتری هست به نام :shutdown‍ که من نتونستم درکش کنم خوب!! یعنی بعد از اون تایمش این genserver ریست یا خاموش می شه و پاک می شه اطلاعات داخلش؟

مثلا:

use GenServer, restart: :transient, shutdown: 10_000

با تشکر

https://hexdocs.pm/elixir/GenServer.html

روی terminate یه پارامتر shutdown داری که وقتی براش زمان تعیین میکنی پروسه های مربوط به جای اینکه فورا خاموش بشن بعد از زمانی که دادی از بین میرن، اما در نظر داشته باش که زمان دادن gracefulness رو تضمین نمیکنه و برای تضمینش راه بهتری وجود داره.

Supervisor => terminated
Child => terminate at ^ + time

کلا این موضوع مربوط به سوپروایز کردن هست, در نظر داشته باش که در مورد termination حرف میزنیم نه hibernation پس GC هیپشو آزاد میکنه.

1 Like

توماج جان من فکر کنم هنوز متوجه نشدم!!!

منظور شما اینکه هر پروسزی که درست می کنیم بعد از انجام کارش بالاخره از بین می ره تا فرمان جدید و پروسز جدید!! درسته ؟

:permanent - the child process is always restarted.

:temporary - the child process is never restarted, regardless of the supervision strategy: any termination (even abnormal) is considered successful.

:transient - the child process is restarted only if it terminates abnormally, i.e., with an exit reason other than :normal, :shutdown, or {:shutdown, term}.

مثلا من یک توکن داخل جن سرورم نگه می دارم. بعد هر سری می یایم آبدیت می کنم یا می خونمش !! تا زمانی که براش مشکلی پیش نیاد ریست نمی شه ولی بعد از این تایم shutdown کلا این توکنم می پره از state جن سرورم ؟

مشکلمو با یک مثال توضیح دادم که بفهمم منظور این گزینه shutdown اینه یا خیر؟


یک سوال اضافه

به این کد توجه فرمایید من اومدم مثلا توکن های کاربران رو اینجوری هر سری ذخیره کردم

def handle_cast({:new_user, user}, state) do
    new_state = %{ state | user: size}
    {:noreply, new_state}
  end

همیشه توکن جدید یا اربر جدید رو با کاربر قدیمی می یام بر اساس هر درخواست جدید ذخیره می کنم تا درخواست بعدی که بازم همین وضعیت هست مثلا بعد از ۴ درخواست token جدید یا ذخیره کاربر جدید

مثلا می شه این داده ها

%{
   "user_id1" => "1",
   "user_id2" => "2",
   "user_id3" => "3",
   "user_id4" => "4",
}

منظور اینکه بعد از تایم shutdown کل موارد بالا می پره یعنی کل توکن هام یا اینکه فقط آخرین فرمان مثلا "user_id4" => "4", می پره ؟

بله بهتره هر کاربر اکتور خودشو داشته باشه که این اتفاق نیوفته

اگه transient باشه بله
اگر نه همیشه باقی میمونه مگر یک خطا به وجود بیاد

1 Like

در ارلنگ هدف اینکه که سیستم و اکتور ها هرکدام به صورت مستقل و جدا باشند و درصورت خطا کمترین تاثیر روی سیستم داشته باشند
اگر یک کاربر مشکلی برخورد کنه فقط اکتور او ریستارت بشه

چقدر بد آموزشی که دیدم اصلا در مورد اینکه هر کاربر رو در یک جن سرور یا کلمه ای که شما می فرمایید یعنی اکتور جدید ذخیره کنه صحبتی نکرد.

آخه کل GenServers موقع شروع یک اسم می گیره

 def start_link(_arg) do
    GenServer.start_link(__MODULE__, %State{}, name: @name)
 end

یعنی کل پروسز ها داخل یک name در جنسرور هستند!! پس یعنی راهی اون آموزش رفته ایزوله نیست و کل state هارو تو یک جا ذخیره کرده و حالا باید بفهمم چیجوری هر کدوم رو جدا کنم :scream:

اینو ببین

1 Like

خود داکیومنت الیکسیر هم اومده

  def handle_cast({:push, element}, state) do
    {:noreply, [element | state]}
  end

همینجوری جلو رفته و نیومده جدا کنه اینم پس کلش بعد از یک زمانی همه ی satet هاش می پرند جز اینکه در دیتابیس واسطی ذخیره بشه

این نمیپره مگه اینکه خطا به وجود بیاد restart بشه

1 Like

البته اگر مورد زیر نباشه

مثلا ۲ گیگ رم داریم و ۲ هزار نفر کاربر کل ۲ هزار نفر اگر در یک زمان درخواست بزنند ۲ گیگ رم پر می شه

حالا فکر کنیم ۱۹۹۹ نفر درخواست زدند و ۱۹۹۹ مگ رم مصرف شد و سیستم داره کار می کنه با نفر آخری که درخواست زده می شه رم پر می شه و ارور نمایان می شه و سپوروایزر تلاش می کنه ریست کنه. ۲ هزار تا توکن مثلا می پره !!!

الان پیشنهاد چی هست ؟ چطور جلویگیری کنیم از دست رفتن داده هامون

ممنون گزاشتم دانلود بشه ببنیمش امروز بارون باریده اینترنت سرعتش اومده پایین :joy: نمی شه آنلاین دید

1 Like

هر اکتور memory خودشو داره و اگه برای هر کاربر پروسس جدا درست کنی اگه رم پر باشه ارلنگ اصلا نمیگذاره نفر ۲۰۰۰۰ پروسس ساخته بشه چون رم نداره
از state در اکتور وقتی استفاده کن که از دست رفتن اون داده برات خیلی مهم نیست
مثل cache

1 Like

سام عزیز اگر فقط برای این مورد مثالی کد الیکسیری چیزی داشته باشی من دیگه کاملا متوجه می شم داستان از چه قراره.

من می تونم هر درخواست یعنی

def save_user(user) do
   GenServer.cast @name, {:new_user, user}
end

اینجوری بفرستمش و از طرف سرور بگیرمش

def handle_cast({:new_user, user}, state) do
   new_state = %{ state | user: size}
   {:noreply, new_state}
end

حالا نمی دونم این کار من یعنی در سری درخواست می دم در یک پروسز جدید هست ؟ یا باید وقتی تابع save_user رو می خونم باید در یک تسک یا spawn جدید ارسال کنمش ؟

parent = self()

spawn(fn -> send(parent, {self(), :new_user, save_user(data)}) end)

کتاب elixir in action فصل ۷ مثال با توضیح داره
برای هر کاربر یک لیست جدا درست میکنه با genserver

1 Like

اگر این فصل می فرمایید که به بحث ما مرتبط هست
“Chapter 7. Building a concurrent system”

سام عزیز این کتاب اتفاقا امروز داشتم می خوندم این اومده بود برای هر داده ای یک بار genserver رو استارت می کرد. من گفتم اگر این استارت بکنه این همه جن سرور بشه مشکلی پیش نمی یاد مصرف زیاد نمی شه !! البته با تایم خاموشی خودکار و تغییر به موردی که بالا صحبت کردیم بعد از مدتی حذف می شه و کاملا مجزاست.
فکر نکنم مشکلی پیش بیاد. پست اولی هم لینک دادید هم طرف همینجوری نوشته بود

1 Like