Files
n8n-openai-adapter/lib/elixir/lib/task/supervised.ex
T
eksperimental ed5671b4f8 Standardize use of backticks and quotes; including Error messages and Title Case commands
This is a large commit that does the following:
* Removes backticks from messages and comments.
  All references to backticks have been replaced with double quotes everywhere the
  code is not interpreted as Markdown, (ie. anywhere outside documentation and
  markdown files, such as in code comments, or error messages).

* Variables in Exception messages are printed using `inspect`
  The way no-matching error message are printed, have changed because now we use inspect for printing
  variables. The following file and their respective test have been changed:
  - lib/elixir/lib/exception.ex
  - lib/elixir/lib/inspect/algebra.ex
  - lib/elixir/test/elixir/inspect_test.exs
  - lib/ex_unit/test/ex_unit/formatter_test.exs
  - lib/elixir/test/elixir/exception_test.exs

* Properly use Title Case for Mix, Git, Dializer

* Use backticks when citing a command

****************************************************
CONVENTION FOR RENAMING USING BACKTICKS AND QUOTES

https://github.com/elixir-lang/elixir/pull/3697#issuecomment-138811747

1. Backticks should never be printed in error messages, neither be included anywhere where Markdown code is not interpreted as such.

2. Do not use single quotes anywhere. We should favor double quotes everywhere, to avoid confusion

3. If you want to format something in error messages, use inspect. For example, if you want to show the dependency name and that is an atom, instead of the dependency "foo", let's show the dependency :foo. Less noise and may click better

4. Similarly, if you want to show something with double quotes, call inspect, as it handles escaping as well as the quotes

5. Things like "--all" just add verbosity, we can definitely read --all without ambiguity.

6. When using switches with a single hyphen (such as "-o"), we can make it explicit in the text: e.g. "... give the switch -o when choosing ..."

****************************************************
SHELL COMMANDS TO DETECT CODE BREAKING THE RULES

* Detect values surrounded by single-quotes where we want double-quotes.

    # regular variables
    ag "'#{"
    # constants or ENV variables
    ag "'[A-Z][A-Z0-9_-]+"
    # switches
    ag -i "(?<!(\[))'--?[a-z0-9][a-z0-9_-]+'"
    # atoms
    ag -i "(?<!(\[))':[a-z0-9][a-z0-9_-]+'"

    # DETECT BACKTICKS OUTSIDE DOCS
    ag "^\s+(?<!(#))#[^#\r\n]*\`" --ignore "*.md"
    ag '^\s+["%].*`' --ignore "*.md"
    ag -s '(raise|Error)\b(?!(`|/)).*\`'

* Spot mentions to running a command that is not using backticks:

    commands="elixir|elixirc|mix|iex|ex_doc|git|make|rebar|dialyzer|erl|rm|cd|mkdir|rmdir|ln|ls|pwd"
    actions="runs?|running|executes?|executing|types?|typing|enters?|entering|calls?|calling"
    ag '(?i)('${actions}')(?-i)\b[^`\r\n/]+[\ \t]+(?!(`))('${commands}')'
    ag '(?-i)\b(?!(`))('${commands}')[\ \t]+[^`\r\n/]+(?i)(commands?)'

* Spot where a command is mentioned:

    #commands="erlang|elixir|eex|iex|ex_unit|ex_doc|logger|elixirc|git|make|rebar|dialyzer|erl|rm|cd|mkdir|rmdir|ln|ls|pwd"
    commands="mix|elixirc|git|make|rebar|dialyzer|erl|rm|cd|mkdir|rmdir|ln|ls|pwd"
    ag -s '(?<!(\`))(?<!(\.))(?<!(/))(?<!(:))(?<!(_))\b('${commands}')\b(?!(:))(?!(\?))(?!(_))(?!(-))(?!(\.))(?!(\`))(?!(/))(?!(>))' \
    --ignore "*.erl" --ignore "*.yrl" --ignore "*.src"
2015-09-11 18:49:51 +07:00

132 lines
4.0 KiB
Elixir

defmodule Task.Supervised do
@moduledoc false
def start(info, fun) do
{:ok, :proc_lib.spawn(__MODULE__, :noreply, [info, fun])}
end
def start_link(info, fun) do
{:ok, :proc_lib.spawn_link(__MODULE__, :noreply, [info, fun])}
end
def start_link(caller, info, fun) do
:proc_lib.start_link(__MODULE__, :reply, [caller, info, fun])
end
def async(caller, info, mfa) do
initial_call(mfa)
ref = receive do: ({^caller, ref} -> ref)
send caller, {ref, do_apply(info, mfa)}
end
def reply(caller, info, mfa) do
initial_call(mfa)
:erlang.link(caller)
:proc_lib.init_ack({:ok, self()})
ref =
# There is a race condition on this operation when working across
# node that manifests if a "Task.Supervisor.async/1" call is made
# while the supervisor is busy spawning previous tasks.
#
# Imagine the following workflow:
#
# 1. The nodes disconnect
# 2. The async call fails and is caught, the calling process does not exit
# 3. The task is spawned and links to the calling process, causing the nodes to reconnect
# 4. The calling process has not exited and so does not send its monitor reference
# 5. The spawned task waits forever for the monitor reference so it can begin
#
# We have solved this by specifying a timeout of 5000 seconds.
# Given no work is done in the client between the task start and
# sending the reference, 5000 should be enough to not raise false
# negatives unless the nodes are indeed not available.
receive do
{^caller, ref} -> ref
after
5000 -> exit(:timeout)
end
send caller, {ref, do_apply(info, mfa)}
end
def noreply(info, mfa) do
initial_call(mfa)
do_apply(info, mfa)
end
defp initial_call(mfa) do
Process.put(:"$initial_call", get_initial_call(mfa))
end
defp get_initial_call({:erlang, :apply, [fun, []]}) when is_function(fun, 0) do
{:module, module} = :erlang.fun_info(fun, :module)
{:name, name} = :erlang.fun_info(fun, :name)
{module, name, 0}
end
defp get_initial_call({mod, fun, args}) do
{mod, fun, length(args)}
end
defp do_apply(info, {module, fun, args} = mfa) do
try do
apply(module, fun, args)
catch
:error, value ->
reason = {value, System.stacktrace()}
exit(info, mfa, reason, reason)
:throw, value ->
reason = {{:nocatch, value}, System.stacktrace()}
exit(info, mfa, reason, reason)
:exit, value ->
exit(info, mfa, {value, System.stacktrace()}, value)
end
end
defp exit(_info, _mfa, _log_reason, reason)
when reason == :normal
when reason == :shutdown
when tuple_size(reason) == 2 and elem(reason, 0) == :shutdown do
exit(reason)
end
defp exit(info, mfa, log_reason, reason) do
{fun, args} = get_running(mfa)
:error_logger.format(
'** Task ~p terminating~n' ++
'** Started from ~p~n' ++
'** When function == ~p~n' ++
'** arguments == ~p~n' ++
'** Reason for termination == ~n' ++
'** ~p~n', [self, get_from(info), fun, args, get_reason(log_reason)])
exit(reason)
end
defp get_from({node, pid_or_name}) when node == node(), do: pid_or_name
defp get_from(other), do: other
defp get_running({:erlang, :apply, [fun, []]}) when is_function(fun, 0), do: {fun, []}
defp get_running({mod, fun, args}), do: {:erlang.make_fun(mod, fun, length(args)), args}
defp get_reason({:undef, [{mod, fun, args, _info} | _] = stacktrace} = reason)
when is_atom(mod) and is_atom(fun) do
cond do
:code.is_loaded(mod) === false ->
{:"module could not be loaded", stacktrace}
is_list(args) and not function_exported?(mod, fun, length(args)) ->
{:"function not exported", stacktrace}
is_integer(args) and not function_exported?(mod, fun, args) ->
{:"function not exported", stacktrace}
true ->
reason
end
end
defp get_reason(reason) do
reason
end
end