Packages
Mishka Installer is a system plugin manager and run time installer for elixir.
Current section
Files
Jump to
Current section
Files
mishka_installer
README_FA.md
README_FA.md
# سیستم مدیریت پلاگین زبان برنامه نویسی الیکسیر
### هدف ساخت
فرض کنید شما قرار است یک نرم افزاری را ارائه کنید که برای آن افزونه های زیادی تولید خواهد شد ولی اینکه در کد اصلی شما هر بار دستبرده شود باعث تداخل و همینطور نگهداری سخت این نرمافزار می شود. به صورت مثال شما یک سیستم مدیریت محتوایی را برای کاربران خود منتشر می کنید حال آن ها به این نیاز دارند تا برای بخش ثبت نام ارسال پیامک را فعال کنند؛ این سیستم به شما اجازه می دهد به صورت کاملا پلاگین محور خروجی و ورودی مورد انتظار خود را به کاربر داده و این امکان را ایجاد کنید که بیرون از هسته توسعه دهندگان بتوانند افزونه های مورد نیاز خود را برای نرمافزار شما بنویسند.
> ما از این کتابخانه در [**سیستم مدیریت محتوای میشکا**](https://github.com/mishka-group/mishka-cms) استفاده کرده ایم.
---
### تئوری پیادهسازی سیستم مدیریت پلاگین ها
این کتابخانه کل ساختار طرحی نرمافزار شما را به چندین بخش تقسیم بندی می کند و همینطور وابستگی مناسبی که به صورت اختیاری است با `Genserver` دارد و برای هر پلاگین شما شاخه نظارتی در نظر می گیرد که خود باعث کم شدن خطا و همینطور `Down time` کمتر می شود. بخش در نظر گرفته شده:
1. رفتار ها و رویداد ها
2. فراخوانی یا `Hook` با اولویت بندی
3. مدیریت `State` و ارتباط با بانک اطلاعاتی (پشتیبانی از `PostgreSQL`)
> بجز گزینه اول که می تواند بر اساس نیاز توسعه دهنده در سیستم های شخصی خودش بازتعریف مجدد شود باقی موارد تقریبا ثابت می باشند و توابع زیادی برای مدیریت کردن هر پلاگین به توسعه دهنده داده خواهد شود.
---
#### رفتار ها و رویداد ها
در این بخش شما برای هر رویداد که می تواند به صورت مثال: بعد از `ثبت نام موفقیت آمیز` یا `خرید ناموفق از فروشگاه` یک سری `event` تعریف کنید و برای این هر رویداد نیز مجموعه ای از `callback` ها را در یک ماژول قرار بدهید. بعد از انجام این مرحله در زمانی که کاربر پلاگین خودش را می خواهد بسازد ماژول `@behaviour` شما را در ماژول اکشن خود فراخوانی می کند.
> این کار به شما کمک می کند تا یک سیستم منظم و کم خطایی داشته باشید و همینطور این کتابخانه از ساختاری تقریبا یکپارچه در تمام رویداد های خودش استفاده می کند.
---
#### فراخوانی یا Hook با اولویت بندی
در کتابخانه مدیریت پلاگین الیکسیر میشکا یک سری توابع اکشن یا `Hook` به توسعه دهنده افزونه یا نرمافزار اصلی داده می شود که کمک می کند هم در ساخت پلاگین های خارج سیستم و هم در تبدیل بخش های نرمافزار به `event` های مجزا. برخی از توابع این ماژول شامل موارد زیر می شود.
1. ثبت یک افزونه یا پلاگین بیرون از سیستم در بانک اطلاعاتی و `state` رم
2. حذف پلاگین از بانک اطلاعاتی و `state`
3. راهاندازی مجدد پلاگین
4. متوقف کردن موفقت پلاگین
5. فراخوانی پلاگین
6. جستجو در بین `event` ها
و دیگر توابعی که کمک می کند هم نرمافزار مادر تبدیل به یک سیستم رویداد محور شود و هم توسعه دهنده بتواند پلاگین یا افزونه مورد نظر خود را برای بخش های مختلف نرمافزار بسازد و به عنوان یک پکیج جدا نصب روی سیستم کند. این پکیج می تواند در `hex` نیز منتشر گردد.
---
#### مدیریت State و ارتباط با بانک اطلاعاتی پشتیبانی از `PostgreSQL`
بخش بزرگی از این قسمت به وسیله ماژول `Hook` مدیریت می شود و توسعه دهنده افزونه خارجی معمولا زیاد به آن نیاز نخواهد داشت ولی این بخش برای هر پلاگینی که در یک رویداد خاص فعال می شود یک `state` روی رم می سازد و همینطور برای ان یک سوپروایزر داینامیک نیز مشخص می کند. این کار این امکان را می دهد در صورت خطا در هر پلاگین دیگر پلاگین ها در رویداد های مختلف دچار مشکل نشوند و سیستم بتواند با استراتژی های مختلف تلاش به راهاندازی مجدد کند.
> لازم به ذکر است برای ثبات بیشتر و همینطور ذخیره سازی اطلاعات بعد از ثبت یک پلاگین در سیستم؛ این بخش نسخه ای را در بانک اطلاعاتی نیز به صورت بکاپ نگهداری می کند و همینطور استراتژی های برای فراخوانی مجدد در صورت بروز خطا دارا می باشد. ولی برای بالا بردن سرعت فراخوانی هر پلاگین همیشه وب سایت از `state` استفاده می کند.
---
---
### نصب کتابخانه:
لازم به ذکر است این کتابخانه در دو بخش افزونه و همینطور نرم افزاری که می خواهد افزونه هارا نمایش بدهد باید نصب شود و بخاطر وابستگی های کمی که دارد مشکلی ایجاد نمی کند. برای نصب فقط کافی می باشد در `mix.exs` خود در تابع `deps` به صورت زیر این کتابخانه را اضافه کنید.
```elixir
def deps do
[
{:mishka_installer, "~> 0.0.3"}
]
end
```
### استفاده از کتابخانه:
بعد از نصب کردن این کتابخانه شما باید در مرحله اول بانک اطلاعاتی مورد نیاز این پکیج را در وب سایت خود تعبیه کنید، که برای این بخش نیز یک `mix task` درست شده است که کافی است قبل از شروع نرمافزار آن را یک باردر ترمینال خود در مسیر پروژه اجرا کنید.
```elixir
mix mishka_installer.db.gen.migration
```
بعد از پیادهسازی بخش های بالا حال شما به این نیاز دارید که اول در نرمافزار اصلی خود رویداد هایی را پیادهسازی کنید و تابع `call` از ماژول `Hook` را آنجا قرار بدهید تا تمامی پلاگین های فعال شده در `event` مورد نظر شما را بر اساس اولویت فراخوانی کند و `state` مورد نظر شما را به ترتیب به این پلاگین ها بدهد و خروجی مورد انتظار شما در نهایت تولید شود.
به صورت مثال شما می توانید توضیحات بالا را در یک فانکشن کنترلر در فونیکس بعد از ثبت نام موفقیت آمیز ببنید.
```elixir
def login(conn, %{"user" => %{"email" => email, "password" => password}} = _params) do
# If your conditions are passed we call an event and pass it a struct of entries
# which our developers need to create plugin with this information
state = %MishkaInstaller.Reference.OnUserAfterLogin{
conn: conn,
endpoint: :html,
ip: user_ip, type: :email,
user_info: user_info
}
hook = MishkaInstaller.Hook.call(event: "on_user_after_login", state: state)
hook.conn
|> renew_session()
|> put_session(:user_id, user_info.id)
|> put_flash(:info, "You entered to our world, well played.")
|> redirect(to: "/home")
end
```
حال رویداد مورد نظر در بخشی که شما نیاز دارید تا این امکان را به توسعه دهنده بدهید تا پلاگین های خودش را برای آن درست کند آماده می باشد. و وقت آن هست یک پلاگین برای این بخش بنویسیم. این کار بسیار ساده می باشد. به مثال زیر توجه کنید:
```elixir
defmodule MishkaUser.SuccessLogin do
alias MishkaInstaller.Reference.OnUserAfterLogin
use MishkaInstaller.Hook,
module: __MODULE__,
behaviour: OnUserAfterLogin,
event: :on_user_after_login,
initial: []
@spec initial(list()) :: {:ok, OnUserAfterLogin.ref(), list()}
def initial(args) do
event = %PluginState{name: "MishkaUser.SuccessLogin", event: Atom.to_string(@ref), priority: 1}
Hook.register(event: event)
{:ok, @ref, args}
end
@spec call(OnUserAfterLogin.t()) :: {:reply, OnUserAfterLogin.t()}
def call(%OnUserAfterLogin{} = state) do
new_state = Your_Code_Or_Function
{:reply, new_state}
end
end
```
همانطور که در بالا می بینید ما برای فعال کردن `behaviour` از ماژول `MishkaInstaller.Reference.OnUserAfterLogin` استفاده کردیم که چند `callback` در آن وجود دارد می توانید در [اینجا](https://github.com/mishka-group/mishka_installer/blob/master/lib/plugin_manager/event/reference/on_user_after_login.ex) ببنید.
> در هر پلاگین باید دو فانکش اصلی یعنی `initial` و همینطور `call` وجود داشته باشد در اولین تابع ما پلاگین خود را معرفی می کنیم و در دومین تابع هر وقت فانکشن اکشن که این رویداد خاصی که پلاگین برای آن نوشته شده است را صدا بزند بر اساس اولویت این پلاگین نیز فراخوانی می شود. ولی چیزی که مهم می باشد خروجی آخر فانکشن `call` است. این خروجی ممکن است ورودی پلاگین های دیگر با اولویت های بالاتر باشد. ترتیب پلاگین ها از کوچک به بزرگ می باشد و اگر برای یک عدد چندین پلاگین ثبت شده باشد بر اساس اسم در دومین پارامتر مرتب می کند. و لازم به ذکر است به هر صورت اگر نخواستید این `state` به دیگر پلاگین ها برود و در همین پلاگین خروجی آخر بر گردد می توانید `{:reply, :halt, new_state}` را بهجای `{:reply, new_state}` قرار بدهید با این کار دیگر پلاگین های بعدی با اولویت های بالاتر مورد محاسبه قرار نمی گیرد و حلقه در همینجا به تمام می رسد.
---
> توجعه داشته باشید به اسم هر پلاگین یک `Genserver` بدون سوپروایزر نیز درست می گردد که می تواند برای حافظه موقت نیز استفاده گردد که وقتی از تابع `__using__` در بالا استفاده کردید این امکان فراهم می شود.
```elixir
use MishkaInstaller.Hook,
module: __MODULE__,
behaviour: OnUserAfterLogin,
event: :on_user_after_login,
initial: []
```
آخرین مرحله برای استفاده از پلاگین، شما باید آن را در ماژول `Application` خود قرار بدهید که هر وقت سرور خاموش و روشن شد دوباره پلاگین اجرا شود و در صورتی که ثبت نشده است یک بار نیز در بانک اطلاعاتی نسخه ای پشتیبانی از آن تهیه گردد
```elixir
children = [
%{id: YOUR_PLUGIN_MODULE, start: {YOUR_PLUGIN_MODULE, :start_link, [[]]}}
]
```
در موقع استفاده می توانید خطوط زیر را در فایل کانفیگ خود قرار بدهید.
```elixir
config :mishka_installer, :basic,
repo: YOUR_Repo,
pubsub: YOUR_PUBSUB or nil,
html_router: YOUR_WEBSITE_ROUTER_MODULE
``
شما می توانید پیشنهاد های ما و دیگر همکاران را در ریپازیتوری [Proposals](https://github.com/mishka-group/Proposals) ببنید و اگر خودتان درخواستی یا ایده ای دارید در آن جا با توضیحات کامل برای ما ارسال کنید. **لطفا با همکاری در ارائه پیشنهادها و بررسی پروژه کمک کنید تا گروه [میشکا](https://github.com/mishka-group) بتواند محصولات بیشتری را تولید و در اختیار برنامه نویسان و مدیران سایت ها و نرمافزار های آنلاین قرار بدهد**.