Created
February 7, 2019 14:33
-
-
Save ccapndave/059ea5d3683901f4e0d9cd7464d2af5c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule AlchemyWeb.LicenseChecker do | |
@moduledoc """ | |
At a constant interval, confirm that all connected users have a license. If not then | |
send a message to their channel telling the client to kick them out. | |
""" | |
use GenServer | |
alias Alchemy.Licensing | |
# The interval between checks | |
@interval 1000 | |
def start_link(opts) do | |
GenServer.start_link(__MODULE__, opts) | |
end | |
def init(_args) do | |
schedule_check_licenses() | |
{:ok, %{}} | |
end | |
defp schedule_check_licenses() do | |
self() |> Process.send_after(:check_licenses, @interval) | |
end | |
@doc """ | |
Check the licenses for all connected users. If any users don't have a license slot, send a message to their channel | |
to tell them so. | |
""" | |
defp check_licenses() do | |
# Get all connected user channels | |
channel_pids_and_tokens = Registry.lookup(Registry.UserChannels, "users") | |
# Get the pids of all channels that no longer have a license | |
expired_channel_pids = | |
Enum.zip( | |
# PIDs | |
channel_pids_and_tokens |> Enum.map(&elem(&1, 0)), | |
# License details | |
channel_pids_and_tokens | |
|> Enum.map(&elem(&1, 1)) | |
|> Licensing.acquire_license_slots() | |
) | |
|> Enum.filter(fn {_, %Licensing.LicenseDetails{has_license_slot: has_license_slot}} -> | |
has_license_slot === false | |
end) | |
|> Enum.map(&elem(&1, 0)) | |
# Send a message to each expired channel so they can disconnect their clients | |
expired_channel_pids | |
|> Enum.each(&send(&1, :license_expired)) | |
end | |
def handle_info(:check_licenses, state) do | |
check_licenses() | |
schedule_check_licenses() | |
{:noreply, state} | |
end | |
end |
defmodule AlchemyWeb.LicenseChecker do
@moduledoc """
At a constant interval, confirm that all connected users have a license. If not then
send a message to their channel telling the client to kick them out.
"""
use GenServer
alias Alchemy.Licensing
# The interval between checks
@interval 1000
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def init(_args) do
schedule_check_licenses()
{:ok, %{}}
end
defp schedule_check_licenses() do
self() |> Process.send_after(:check_licenses, @interval)
end
@doc """
Check the licenses for all connected users. If any users don't have a license slot, send a message to their channel
to tell them so.
"""
defp check_licenses() do
Registry.UserChannels
|> Registry.dispatch("users", fn channel_pids_and_tokens ->
# Get the pids of all channels that no longer have a license
expired_channel_pids =
Enum.zip(
# PIDs
channel_pids_and_tokens |> Enum.map(&elem(&1, 0)),
# License details
channel_pids_and_tokens
|> Enum.map(&elem(&1, 1))
|> Licensing.acquire_license_slots()
)
|> Enum.filter(fn {_, %Licensing.LicenseDetails{has_license_slot: has_license_slot}} ->
has_license_slot === false
end)
|> Enum.map(&elem(&1, 0))
# Send a message to each expired channel so they can disconnect their clients
expired_channel_pids
|> Enum.each(&send(&1, :license_expired))
end)
end
def handle_info(:check_licenses, state) do
check_licenses()
schedule_check_licenses()
{:noreply, state}
end
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
DISREGARD THIS. IT IS INCORRECT
There is a lot of unnecessary iteration here.
The logic can be summarized as: