'Bad Connection Handle' in aerospike ejabberd integration - erlang

tried to integrate the Aerospike with Ejabberd, and after little bit of struggle and I had hit another issue which says
" DEBUG:[util_extract_common_lead_parms()]:Connection Handle is bad C(0) DEBUG:[util_extract_common_lead_parms()]:Connection Handle is bad C(32680) " I made the connection the following way,
-behaviour(gen_mod).
-define(CONN_NAME, 'ejabberd_aerospike_client').
init()->
Host = "127.0.0.1",
Port = 3000,
case aerospike:connect( Host, Port ) of
{ok, C } ->
register(?CONN_NAME,C),
ok;
{error, _} = Err ->
?ERROR_MSG("failed to start aerospike client: ~p", [Err]),
Err
end.

Related

Erlang: starting gen_server on another node fails after init

I am stuck in a bit of a fix trying to run gen_server on another node. So I have a common gen_server class which looks like this
start(FileName) ->
start_link(node(), FileName).
start_link(ThisNode, FileName) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [ThisNode, FileName], []).
init([ThisNode, FileName]) ->
process_flag(trap_exit, true),
{ok, Terms} = file:consult(FileName),
{A1, B1, C1} = lists:nth(1,Terms),
place_objects(A1, B1, C1).
Now I want to start multiple nodes that will run the same gen_server and somehow communicate with each other, and use a another node to orchestrate that. (All these nodes are started on my local terminal).
So I start a new node in one terminal using erl -sname bar where I intend to run the gen_server, and compile the gen_server module on this node. Then I start another node called 'sup' which I intend to use as a coordinator for all the other nodes. If I run the command my_gen_server:start("config_bar.txt"). on bar, it successfully returns but when I run the command rpc:call('bar#My-MacBook-Pro', my_gen_server, start, ["config_bar.txt"]). on sup, it successfully returns from the init method (I checked this by putting in the logs) but immediately after that, I get this error:
{ok,<9098.166.0>}
(sup#My-MacBook-Pro)2> =ERROR REPORT==== 21-Feb-2022::11:12:30.443051 ===
** Generic server my_gen_server terminating
** Last message in was {'EXIT',<9098.165.0>,
{#Ref<0.3564861827.2990800899.137513>,return,
{ok,<9098.166.0>}}}
** When Server state == {10,10,#Ref<9098.1313723616.3973185546.82660>,
'bar#My-MacBook-Pro'}
** Reason for termination ==
** {#Ref<0.3564861827.2990800899.137513>,return,{ok,<9098.166.0>}}
=CRASH REPORT==== 21-Feb-2022::11:12:30.443074 ===
crasher:
initial call: my_gen_server:init/1
pid: <9098.166.0>
registered_name: my_gen_server
exception exit: {#Ref<0.3564861827.2990800899.137513>,return,
{ok,<9098.166.0>}}
in function gen_server:decode_msg/9 (gen_server.erl, line 481)
ancestors: [<9098.165.0>]
message_queue_len: 0
messages: []
links: []
dictionary: []
trap_exit: true
status: running
heap_size: 1598
stack_size: 29
reductions: 3483
neighbours:
I can't seem to figure out what causes the error and if there's anything I need to add to my gen_server code to fix it. Would really appreciate some help on this one!
The gen_server in the remote node is linked to an ephemeral process created for the rpc call.
As this ephemeral process exits with a term that's different from normal (the actual result of the rpc call), the exit signal propagates to the gen_server, killing it.
You can use gen_server:start instead of gen_server:start_link or, if you want the gen_server to be part of the supervission tree, instruct its supervisor to spawn it:
rpc:call('bar#My-MacBook-Pro', my_gen_sup, start_child, ["config_bar.txt"]).

Testing a concurrent server with multiple clients on localhost: error,econnrefused

I can't get multiple clients to communicate with my concurrent echo server. Here are my results:
Server Terminal window:
1> c(s).
{ok,s}
2> s:init(15555).
Server started on port: 15555
Client Terminal window:
1> c(cl).
{ok,cl}
2> cl:test().
[<0.64.0>,<0.65.0>,<0.66.0>,<0.67.0>,<0.68.0>]
3>
=ERROR REPORT==== 21-May-2017::21:21:39 ===
Error in process <0.68.0> with exit value:
{{badmatch,{error,econnrefused}},[{cl,client,2,[{file,"cl.erl"},{line,5}]}]}
=ERROR REPORT==== 21-May-2017::21:21:39 ===
Error in process <0.67.0> with exit value:
{{badmatch,{error,econnrefused}},[{cl,client,2,[{file,"cl.erl"},{line,5}]}]}
...
...
In the shell, if I start my server, then connect one client, my client and server can communicate back and forth without error:
Server Terminal window:
1> c(s).
{ok,s}
2> s:init(15555).
Server started on port: 15555
Client Terminal window:
1> c(cl).
{ok,cl}
2> cl:client(1, 15555).
Client1: sent -->hello
Client1: received <--hello
ok
In my failing concurrent test, I do this:
test() ->
Port = 1555,
[spawn(?MODULE, client, [Id, Port]) || Id <- lists:seq(1, 5)].
Here's my echo server:
-module(s).
-compile(export_all).
init(Port) ->
{ok, ServerSocket} = gen_tcp:listen(Port, [binary, {active,true},
{packet,4}, {reuseaddr,true}] ),
io:format("Server started on port: ~w~n", [Port]),
server(ServerSocket).
server(ServerSocket) ->
{ok, ClientSocket} = gen_tcp:accept(ServerSocket),
spawn(?MODULE, server, [ServerSocket]),
timer:sleep(rand:uniform(3) * 1000),
loop(ClientSocket).
loop(ClientSocket) ->
receive
{tcp, ClientSocket, CompleteMsg} ->
io:format("Server: received ~s~n", [CompleteMsg]),
gen_tcp:send(ClientSocket, CompleteMsg);
{tcp_closed, ClientSocket} ->
io:format("Server: client closed socket.~n")
end,
loop(ClientSocket).
Here's my client:
-module(cl).
-compile(export_all).
client(Id, Port) ->
{ok, Socket} = gen_tcp:connect(localhost, Port, [binary, {active,true},
{packet,4},
{reuseaddr, true}] ),
Msg = "hello",
gen_tcp:send(Socket, Msg),
io:format("Client~w: sent -->~s~n", [Id, Msg]),
receive
{tcp, Socket, CompleteMsg} ->
io:format("Client~w: received <--~s~n", [Id, CompleteMsg]);
{tcp_closed, Socket} ->
io:format("Server closed the socket.~n")
end,
gen_tcp:close(Socket).
test() ->
Port = 1555,
[spawn(?MODULE, client, [Id, Port]) || Id <- lists:seq(1, 5)].
It's my understanding that a TCP socket is nothing but a tuple containing four numbers:
{senderPort, senderAddress, destinationPort, destinationAddress}
I think that each of my clients must have the same senderPort and senderAddress, therefore they are all trying to use the same TCP socket. But I would think that one of my clients would be able to successfully establish a TCP connection while the rest got a connection refused error, yet all of my concurrent clients get a connection refused error.
It seems to me that gen_tcp:connect() somehow picks a senderPort and retrieves the senderAddress, which along with the ServerAddress and ServerPort arguments, defines the socket. How can I make each of my clients use a different senderPort so that each client creates a unique socket?
Is there a way to programmatically test a concurrent server with multiple clients on localhost?

Elixir Phoenix RabbitMQ MatchError

I am creating messaging app where app A need to send message to app B using rabbitMQ. I am developing using Phoenix and on rabbitMQ web site I found tutorial how to implement rabbitmq with elixir but I don't know how to use it in my Phoenix app. I tried to add code, which I find on rabbit tutorial web site, to my Phoenix page_controller.ex
defmodule ApplicationA.PageController do
use ApplicationA.Web, :controller
use AMQP
def index(conn, _params) do
{:ok, connection} = AMQP.Connection.open
{:ok, channel} = AMQP.Channel.open(connection)
AMQP.Queue.declare(channel, "hello")
AMQP.Basic.publish(channel, "", "hello", "Hello World!")
IO.puts " [x] Sent 'Hello World!'"
AMQP.Connection.close(connection)
render conn, "index.html"
end
end
but I get this error
no match of right hand side value: {:error, :econnrefused}
in line 6
{:ok, connection} = AMQP.Connection.open
Con somebody help me how I should do this on the good way?
You need to specify connection settings for RabbitMQ.
Add in your config/dev.exs something like:
config :my_app, :rabbitmq,
host: "${RABBITMQ_HOSTNAME}",
port: 5672,
username: "${RABBITMQ_UID}",
password: "${RABBITMQ_PWD}"
and then load them:
rabbit_settings = Application.get_env :my_app, :rabbitmq
{:ok, connection} = AMQP.Connection.open(rabbit_settings)

How to start Inets httpd server?

I try to start Inets httpd server and have some documents in the document_root, but I can not start up the server. How can I start it?
This is the config I start it with:
>{ok, Pid} = inets:start(httpd, [{port, 8070}, {server_name, "myhttpd"},
>{server_root, "/Users/jonas/code"},
>{document_root, "/Users/jonas/code/mydocs"},
>{bind_address, "localhost"}]).
** exception error: no match of right hand side value {error, inets_not_started}
You should first call inets:start/0.

How would I start more than one instance of webmachine in an erlang application?

I'm trying to create two instances of webmachine in one erlang application. Each instance is to run on a different port and has its own specific configuration. Following the webmachine doc here, I have added the following processes to be started in my supervisor spec (application_sup.erl):
{
webmachine_instance_1,
{ webmachine_mochiweb, start,
[
[
{ ip, "0.0.0.0"},
{ port, 8000},
{ dispatch, [ {["*"], file_resource, []} ] }
]
]
},
permanent,
5000,
worker,
dynamic
},
{
webmachine_instance_2,
{ webmachine_mochiweb, start,
[
[
{ ip, "0.0.0.0"},
{ port, 8080},
{ dispatch, [ {["*"], file_resource, []} ] }
]
]
},
permanent,
5000,
worker,
dynamic
}
When I include both instances, I get a start error and cannot start my erlang application. After just trying to run the application with a single instance of webmachine (webmachine_instance_1 OR webmachine_instance_2), my application starts up fine.
Here is the specific error:
=PROGRESS REPORT==== 11-Mar-2014::17:00:31 ===
supervisor: {local, application_sup}
started: [{pid,<0.230.0>},
{name,webmachine_instance_1},
{mfargs,
{webmachine_mochiweb,start,
[[{ip,"0.0.0.0"},
{port,8000},
{dispatch, [{['*'],
file_resource,
[]
}]}]
]
}
},
{restart_type,permanent},
{shutdown,5000},
{child_type,worker}]
=SUPERVISOR REPORT==== 11-Mar-2014::17:00:31 ===
Supervisor: {local, application_sup}
Context: start_error
Reason: {'EXIT',
{undef,
[{webmachine_mochiweb,start,
[{ip,"0.0.0.0"},
{port,8080},
{dispatch,[{["*"],file_resource,[]}]}],
[]},
{supervisor,do_start_child,2,
[{file,"supervisor.erl"},{line,303}]},
{supervisor,start_children,3,
[{file,"supervisor.erl"},{line,287}]},
{supervisor,init_children,2,
[{file,"supervisor.erl"},{line,253}]},
{gen_server,init_it,6,
[{file,"gen_server.erl"},{line,304}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,227}]}]}}
Offender: [{pid,undefined},
{name,webmachine_instance_2},
{mfargs,
{webmachine_mochiweb,start,
[{ip,"0.0.0.0"},
{port,8080},
{dispatch,[{["*"],file_resource,[]}]}]}},
{restart_type,permanent},
{shutdown,5000},
{child_type,worker}]
I am fairly new to erlang and might not quite understand the underlying issues here - according to the webmachine doc we should be able to start two instances of the same application but with different configurations in an erlang app.
Thanks for any help/discussion on this issue!
Your child process config should have the following form:
{Name,
{webmachine_mochiweb, start, [WebConfig]},
permanent, 5000, worker, [mochiweb_socket_server]}
where Name and WebConfig must be unique to your webmachine instance. The WebConfig part should include name and dispatch_group properties. For example:
WebConfig = [{name,instance1},
{dispatch_group,instance1},
{ip, Ip},
{port, Port},
{log_dir, "priv/log"},
{dispatch, Dispatch}],
So, for multiple instances you might have something like this for your supervisor spec:
WebConfig1 = [{name,instance1},
{dispatch_group,instance1},
{ip, Ip},
{port, Port},
{log_dir, "priv/log"},
{dispatch, Dispatch}],
WebConfig2 = [{name,instance2},
{dispatch_group,instance2},
{ip, Ip},
{port, Port+1},
{log_dir, "priv/log"},
{dispatch, Dispatch}],
Web1 = {instance1,
{webmachine_mochiweb, start, [WebConfig1]},
permanent, 5000, worker, [mochiweb_socket_server]},
Web2 = {instance2,
{webmachine_mochiweb, start, [WebConfig2]},
permanent, 5000, worker, [mochiweb_socket_server]},
Processes = [Web1, Web2],
{ok, { {one_for_one, 10, 10}, Processes} }.
One other thing: judging from the name application_sup appearing in your question, you may have run the webmachine ./scripts/new_webmachine.sh and specified the application name as application. If so, don't do this, since application is the name of a key Erlang OTP module, and your code will clash with it and cause all kinds of problems.

Resources