Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Mishka Installer Event Hook

guidance/event/hook.livemd

Mishka Installer Event Hook

Mix.install([
  {:mishka_installer, github: "mishka-group/mishka_installer", branch: "master"}
])

Solve a possible problem in the execution of sample codes

> Should you come into an error such as “you are on another node,” it is imperative that you terminate the livebook session associated with this repository and then reopen it.

Build purpose

Imagine you are going to make an application that will have many plugins built for it in the future. But the fact that many manipulations will be made on your source code makes it difficult to maintain the application. For example, you present a content management system for your users, and now they need to activate a section for registration and SMS; the system allows you to present your desired input/output absolutely plugin oriented to your users and makes it possible for the developers to write their required applications beyond the core source code.

> NOTICE: Do not use the master branch; this library is under heavy development. Expect version 0.1.0, and for using the new features, please wait until a new release is out.

This library is divided into the following main sections:

Events and Hook

In this section, you can define a series of plugins for each event, for example: after successful registration or unsuccessful purchase from “the store”, and for each event, put a set of callbacks in one module.

After completing this step, when the user wants to create his own plugin, the Macro behaviour and Hook module will call you in its action module.

This helps you have a regular and error-free system, and the library uses an almost integrated structure in all of its events.

> In Mishka Installer Library, a series of action or hook functions are > given to the developer of the main plugin or software, which helps build plugins outside/inside > the system and convert software sections into separate events.

Some of the functions of this module include the following:

  • Retrieves the merged configuration for the hook module.
  • Register a plugin for a specific event.
  • Start a plugin of a specific event.
  • Restart a plugin of a specific event.
  • Stop a plugin of a specific event.
  • Unregister a plugin of a specific event.
  • Retrieves a Plugin GenServer state.
  • Each plugin has A GenServer to do some auto jobs.

> For more information please see the MishkaInstaller.Event.Hook module.

At the outset, it is necessary for you to establish the project route and project Evn, from which you can select one of the following modes of operation. It must to be done in Main project not inside plugins.

System.get_env("MIX_ENV") OR Application.get_env(:mishka_installer, :project_env)
System.get_env("PROJECT_PATH") OR Application.get_env(:mishka_installer, :project_path)

Should you choose to leave this area unchecked, it is possible that it will evaluate a set of default data for you. While this will not be a problem in the developer environment, it is highly likely that you will see an error when you release the code.

Step 1: Create main functions

Consider the following scenario:

we have a user management system, and after registering and logging into the system, we are going to carry out a number of actions. On the other hand, we do not intend to alter the primary functions contained within the source code except for the initial instance, and we will add our preferred plugins outside of the source code.

defmodule UserManagement do
  alias MishkaInstaller.Event.Hook

  def register(params) do
    Hook.call!("after_register", params)
  end

  def login(params) do
    Hook.call!("after_login", params)
  end
end

You can see that we make use of the call! function by looking at the code that is located above. When we are absolutely certain that the state module exists for the event that we want, we should use this function. If we are not certain, we should use the call method instead.

> For more information please read the document. click.

Step 2: Create a custom plugin

> It’s important to note that the manner in which the plugins are called is prioritized, and each plugin has the ability to either display the output at the same time or transmit its processed information to another plugin that has a higher priority. Other plugins do not take into consideration this possibility.

For more information and options please read the document. click.

By default, all plugins are considered as 100 if they are not prioritized. The smaller this number is, the more plugins will be prioritized in that particular event

Due to the fact that there is a complete document for these parts in the system (Hook document), we did not make the examples completely in order to make it easier to understand.

> As a result of this, this area has a good number of additional options that give you the ability to personalize each plugin. I ask that you read the document.

Plugin 1 with priority: 20 (In the same event)

In this example, it is very simple to act in such a way that if there is a certain number in the system, the OTP code will be sent and other plugins will not be executed in this special event, i.e. after_register.

defmodule UserManagement.Plugins.SendOTPPlugin do
  use MishkaInstaller.Event.Hook,
    event: "after_register",
    queue: false,
    initial: %{priority: 20}

  def call(entries) do
    if is_map(entries) and Map.get(entries, :mobile) == "123456789" do
      {:reply, :halt, {:ok, "Message is sent!"}}
    else
      {:reply, {:ok, entries}}
    end
  end
end

Plugin 2 with priority: 100 (In the same event)

defmodule UserManagement.Plugins.SendEmailPlugin do
  use MishkaInstaller.Event.Hook, event: "after_register", queue: false

  def call(entries) do
    {:reply, {:ok, entries}}
  end
end

Plugin 3 with priority: 100 (In another event)

defmodule UserManagement.Plugins.SendSmsPlugin do
  use MishkaInstaller.Event.Hook, event: "after_login", queue: false

  def call(entries) do
    {:reply, {:error, entries}}
  end
end

Step 2: Manual start or activation in the Application module of your project

Note: If you want your plugin to execute automatically, all you need to do is send the name of the module in which you utilized the MishkaInstaller.Event.Hook to the Application module.

children = [
  ...
  UserManagement.Plugins.SendSmsPlugin,
  UserManagement.Plugins.SendEmailPlugin,
  UserManagement.Plugins.SendOTPPlugin
]

...
opts = [strategy: :one_for_one, name: SomeModule.Supervisor]
Supervisor.start_link(children, opts)

Since we did not add the Application module in LiveBook, we have to start it manually, but the above method is recommended for the actual project.

UserManagement.Plugins.SendSmsPlugin.start_link()
UserManagement.Plugins.SendEmailPlugin.start_link()
UserManagement.Plugins.SendOTPPlugin.start_link()

The remaining elements that you require will be automatically fixed by the system, and once the system is restarted, if these plugins are running automatically, they will be automatically accessible again.

Step 3: Using parent functions

You are no longer required to interact with the parent methods in order to add a plugin. In addition, you can even install a plugin in mix.exs within a library. Furthermore, if the library itself has a Application module and you call the plugin in itself, you do not even require it in the parent project. Also, make adjustments.

UserManagement.register(%{mobile: "123456789"})
# {:ok, "Message is sent!"}
UserManagement.register(%{mobile: "00000000"})
# {:ok, {:ok, %{mobile: "00000000"}}}