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)
Related
I have the following endpoint initialization in lib/flashcards_web/endpoint.ex:
#doc """
Callback invoked for dynamically configuring the endpoint.
It receives the endpoint configuration and checks if
configuration should be loaded from the system environment.
"""
def init(_key, config) do
if config[:load_from_system_env] do
port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
jwt_token_ttl_minutes =
"USER_SESSION_MINUTES"
|> System.get_env
|> String.to_integer
|| raise "expected the USER_SESSION_MINUTES environment variable to be set"
config =
config
|> Keyword.put(:http, [:inet6, port: port])
|> Keyword.put(:jwt_token_ttl_minutes, jwt_token_ttl_minutes)
{:ok, config}
else
{:ok, config}
end
end
and the required load_from_system_env: true line in config/dev.exs:
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with brunch.io to recompile .js and .css sources.
config :flashcards, FlashcardsWeb.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
check_origin: false,
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]],
load_from_system_env: true
However when running
PORT=4000 USER_SESSION_MINUTES=1 iex -S mix phx.server
I get:
iex(1)> Application.get_env(:flashcards, FlashcardsWeb.Endpoint)[:jwt_token_ttl_minutes]
nil
Am I missing something here?
Found the solution to access the dynamic endpoint configuration.
The docs mention that a config/2 function is automatically generated at the endpoint.
The dynamic endpoint configuration can therefore be accessed as follows:
iex(2)> FlashcardsWeb.Endpoint.config(:jwt_token_ttl_minutes)
1
I have an umbrella project compose by:
gateway - Phoenix application
core - business model layer notifications a dedicated app for delivering sms, email, etc… users
user management, role system, and authentication.
The three components are connected via AMQP, so they can send and receive messages between them.
We are using Docker, and drone.io hosted on google cloud’s kubernetes engine. So, what is happening is that randomly the application raises the following exception while running my tests:
{\"status\":\"error\",\"message\":\"%DBConnection.OwnershipError{message: \\\"cannot find ownership process for #PID<0.716.0>.\\\\n\\\\nWhen using ownership, you must manage connections in one\\\\nof the four ways:\\\\n\\\\n* By explicitly checking out a connection\\\\n* By explicitly allowing a spawned process\\\\n* By running the pool in shared mode\\\\n* By using :caller option with allowed process\\\\n\\\\nThe first two options require every new process to explicitly\\\\ncheck a connection out or be allowed by calling checkout or\\\\nallow respectively.\\\\n\\\\nThe third option requires a {:shared, pid} mode to be set.\\\\nIf using shared mode in tests, make sure your tests are not\\\\nasync.\\\\n\\\\nThe fourth option requires [caller: pid] to be used when\\\\nchecking out a connection from the pool. The caller process\\\\nshould already be allowed on a connection.\\\\n\\\\nIf you are reading this error, it means you have not done one\\\\nof the steps above or that the owner process has crashed.\\\\n\\\\nSee Ecto.Adapters.SQL.Sandbox docs for more information.\\\"}\",\"code\":0}"
It’s a Json since we exchange amqp messages in our tests, for instance:
# Given the module FindUserByEmail
def Users.Services.FindUserByEmail do
use GenAMQP.Server, event: "find_user_by_email", conn_name:
Application.get_env(:gen_amqp, :conn_name)
alias User.Repo
alias User.Models.User, as: UserModel
def execute(payload) do
%{ "email" => email } = Poison.decode!(payload)
resp =
case Repo.get_by(UserModel, email: email) do
%UserModel{} = user -> %{status: :ok, response: user}
nil -> ErrorHelper.err(2011)
true -> ErrorHelper.err(2012)
{:error, %Ecto.Changeset{} = changeset} -> ViewHelper.translate_errors(changeset)
end
{:reply, Poison.encode!(resp)}
end
end
# and the test
defmodule Users.Services.FindUserByEmailTest do
use User.ModelCase
alias GenAMQP.Client
def execute(payload) do
resp = Client.call_with_conn(#conn_name, "find_user_by_email", payload)
data = Poison.decode!(resp, keys: :atoms)
assert data.status == "ok"
end
end
Following details my .drone.yaml file:
pipeline:
unit-tests:
image: bitwalker/alpine-elixir-phoenix:1.6.1
environment:
RABBITCONN: amqp://user:pass#localhost:0000/unit_testing
DATABASE_URL: ecto://username:password#postgres/testing
commands:
- mix local.hex --force && mix local.rebar --force
- mix deps.get
- mix compile --force
- mix test
mix.exs file in every app contains the following aliases
defp aliases do
[
"test": ["ecto.create", "ecto.migrate", "test"]
]
end
All ours model_case files contain this configuration:
setup tags do
:ok = Sandbox.checkout(User.Repo)
unless tags[:async] do
Sandbox.mode(User.Repo, {:shared, self()})
end
:ok
end
How can I debug this? it only occurs while testing code inside the container. Would the issue be related to container’s resources?
Any tip or hint would be appreciated.
Try setting onwership_timeout and timeout to a large numbers in your config/tests.exs
config :app_name, User.Repo,
adapter: Ecto.Adapters.Postgres,
username: ...,
password: ...,
database: ...,
hostname: ...,
pool: Ecto.Adapters.SQL.Sandbox,
timeout: 120_000, # i think the default is 5000
pool_timeout: 120_000,
ownership_timeout: 120_000 #i think the default is 5000
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.
i am trying to do simple "hello world" program with bunny on ruby on rails.As basic am trying to get connection with tcp its throwing an error.
Could not estabilish TCP connection to 127.0.0.1:5672:
My code:
require "bunny"
begin
conn = Bunny.new
conn.start
rescue => e
puts e
end
what i have to do, am completely new to this.
def authenticate(username, password)
require 'net-ldap'
ldap = Net::LDAP.new
ldap.host = 'server.local'
ldap.port = 389
ldap.base = 'cn=users, dc=server, dc=local'
ldap.auth username, password
if ldap.bind
puts "authentication succeeded"
else
puts "authentication failed"
end
The above is the code i use in my method and i am not sure why my attempts fail. I am trying to authenticate user. I could not find where i am going wrong? It puts authentication failed every time. why? please help me.
First up see if the computer you are using can talk to the LDAP server
telnet server.local 389
Obviously you want to be replacing server.local with your actual server details. If you can't log into the server this way then port 389 isn't open and you may need to be running on the SSL port 636. Try the previous command with 636 rather than 389 to see if that is the case.
If you are unable to telnet into the server on either of those ports you've either got a firewall rule blocking you from talking to it, LDAP is configured on a non standard port or something else is seriously wrong.
A working port 636 will probably mean you need to run something like the following.
require "net-ldap"
ldap = Net::LDAP.new(
host: "server.local"
port: 636
encryption: :simple_tls
)
ldap.auth username, password
Failing all of that an error message is going to be pretty useful so try running
if ldap.bind
# Yay!
else
puts ldap.get_operation_result
end
With some results from this maybe we can help you a bit more.