Created
April 17, 2019 15:37
-
-
Save kevinkoltz/9d642ddd8a017376bf14b348f814a73c 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 SeleniumServer do | |
@moduledoc """ | |
Runs Selenium Server from a process. | |
Can be supervised from the application, for example: | |
# Define workers and child supervisors to be supervised | |
children = [ | |
...other children | |
# Start selenium server process for Hound | |
supervisor(SeleniumServer, []) | |
] | |
""" | |
use GenServer | |
require Logger | |
@executable "selenium-server" | |
@args "" | |
@impl | |
def init(state \\ %{}) do | |
send(self(), :start) | |
{:ok, state} | |
end | |
def start_link() do | |
GenServer.start_link(__MODULE__, :ok, name: __MODULE__) | |
end | |
@impl true | |
def handle_info(:start, state) do | |
start() | |
{:noreply, state} | |
end | |
defp start do | |
shutdown_existing_selenium_server() | |
path = System.find_executable(@executable) | |
port = | |
Port.open({:spawn_executable, path}, [ | |
:stderr_to_stdout, | |
:binary, | |
:exit_status | |
]) | |
{:os_pid, os_pid} = Port.info(port, :os_pid) | |
System.at_exit(fn _exit_status -> | |
swallow_cmd("kill -9 #{os_pid}") | |
end) | |
stream_output(port) | |
end | |
defp shutdown_existing_selenium_server() do | |
swallow_cmd("kill -9 $(lsof -ti tcp:4444)") | |
end | |
defp stream_output(port) do | |
receive do | |
{^port, {:data, data}} -> | |
log_selenium_output(data) | |
stream_output(port) | |
{^port, {:exit_status, 0}} -> | |
log("Command success") | |
{^port, {:exit_status, status}} -> | |
log("Command error, status #{status}", :error) | |
end | |
end | |
# Sends standard output and standard error to /dev/null, | |
# preventing it from being printed to the screen. | |
defp swallow_cmd(cmd) do | |
"#{cmd} > /dev/null 2>&1" | |
|> to_char_list | |
|> :os.cmd() | |
end | |
defp log_selenium_output(data) do | |
data | |
|> String.split("\n") | |
|> Enum.map(&String.trim/1) | |
|> Enum.reject(&(&1 == "")) | |
|> Enum.map(fn message -> | |
[ | |
~r/^[0-9]{4}-[0-9]{2}-[0-9]{2}\s+/, | |
~r/^[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}\s+/, | |
~r/^INFO\s+/, | |
~r/.*INFO::main:\s+/ | |
] | |
|> Enum.reduce(message, fn regex, acc -> | |
Regex.replace(regex, acc, "") | |
end) | |
end) | |
|> Enum.each(&log/1) | |
end | |
defp log(message, level \\ :info) do | |
Logger.log(level, "[SeleniumServer] " <> String.trim(message)) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment