Elixir exrm release crashes on eredis start_link - erlang

I'm fairly new to Elixir and this is the first app that I'm attempting to release using exrm. My app interacts with a Redis database for consuming jobs from a queue (using exq), and also stores results of processed jobs in Redis using eredis.
My app works perfectly when I run it via iex -S mix, and it also runs great when compiled into an escript. However when I use exrm, the application compiles without any issue, but it crashes when I run it.
This is the crash output:
$ ./rel/my_app/bin/my_app console
{"Kernel pid terminated",application_controller,"{application_start_failure,my_app,{bad_return,{{'Elixir.MyApp',start,[normal,[]]},{'EXIT',{{badmatch,{error,{{'EXIT',{{badmatch,{error,{undef,[{eredis,start_link,[],[]},{'Elixir.MyApp.Cache',init,1,[{file,\"lib/my_app/cache.ex\"},{line,8}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,306}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,237}]}]}}},[{'Elixir.MyApp.Cache',start_link,1,[{file,\"lib/my_app/cache.ex\"},{line,21}]},{supervisor,do_start_child,2,[{file,\"supervisor.erl\"},{line,314}]},{supervisor,handle_start_child,2,[{file,\"supervisor.erl\"},{line,685}]},{supervisor,handle_call,3,[{file,\"supervisor.erl\"},{line,394}]},{gen_server,try_handle_call,4,[{file,\"gen_server.erl\"},{line,607}]},{gen_server,handle_msg,5,[{file,\"gen_server.erl\"},{line,639}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,237}]}]}},{child,undefined,'Elixir.MyApp.Cache',{'Elixir.MyApp.Cache',start_link,[[{host,\"127.0.0.1\"},{port,6379},{database,0},{password,[]},{reconnect_timeout,100},{namespace,<<>>},{queues,[<<\"elixir\">>]}]]},permanent,5000,worker,['Elixir.MyApp.Cache']}}}},[{'Elixir.MyApp.Supervisor',start_cache,1,[{file,\"lib/my_app/supervisor.ex\"},{line,17}]},{'Elixir.MyApp.Supervisor',start_link,0,[{file,\"lib/my_app/supervisor.ex\"},{line,9}]},{'Elixir.MyApp',start,2,[{file,\"lib/my_app.ex\"},{line,10}]},{application_master,start_it_old,4,[{file,\"application_master.erl\"},{line,272}]}]}}}}}"}
Here is the mix.exs for my application:
defmodule MyApp.Mixfile do
use Mix.Project
def project do
[
app: :my_app,
version: "0.0.1",
name: "MyApp",
elixir: "~> 1.0",
escript: escript_config,
deps: deps
]
end
def application do
[
applications: app_list(Mix.env),
mod: { MyApp, [] },
env: [ queue: 'elixir']
]
end
def included_applications do
[ :logger, :httpoison, :eredis, :exq, :dotenv, :exjsx, :ex_doc, :oauth2, :sweet_xml ]
end
defp app_list(:dev), do: [:dotenv | app_list]
defp app_list(_), do: app_list
defp app_list, do: [:logger, :httpoison]
def escript_config do
[ main_module: MyApp ]
end
defp deps do
[
{ :dotenv, github: "avdi/dotenv_elixir" },
{ :eredis, github: "wooga/eredis", tag: "v1.0.5" },
{ :exjsx, "~> 3.1.0" },
{ :exq, "~> 0.1.0", app: false },
{ :exrm, "~> 0.16.0" },
{ :ex_doc, github: "elixir-lang/ex_doc" },
{ :httpoison, "~> 0.4" },
{ :oauth2, "~> 0.1.1" },
{ :sweet_xml, "~> 0.2.1" }
]
end
end
The crash appears to be happening in the following init function, where I call :eredis.start_link:
defmodule MyApp.Cache do
use GenServer
require Logger
def init(client_opts) do
{ :ok, client } = :eredis.start_link(
client_opts[:host],
client_opts[:port],
client_opts[:database],
client_opts[:password],
client_opts[:reconnect_timeout])
end
end
Could it be because eredis is an Erlang library as opposed to Elixir?

You need to add :eredis to your app_list function, so that it is packaged with the release, that goes for the rest of your dependencies as well.

Related

Rails + CarrierwaveDirect: Unable to download and process image after successful direct upload to S3

Using Rails 6 and CarrierWaveDirect, we're able to successfully POST a file to a presigned S3 URL, but then we encounter an error when trying to download the file from S3 to our server for processing.
Our model and uploader look like this:
# model
class FileAttachment < ApplicationRecord
mount_uploader :file, FileUploader
end
# uploader
class FileUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
end
S3 responds to our direct uploads (POST) as expected with something like this:
{
"bucket" => "my-bucket",
"key" => "uploads/abcde-my-file.pdf",
"etag" => "12345"
}
Following the docs, we handle the response by saving the returned key attribute to a new model like so:
#file_attachment = FileAttachment.new file_key: params[:key]
#file_attachment.save
This seems to work fine, however, when it tries to download the file from S3 to our server for processing, that fails due to a 400 Bad Request:
irb(main)> #file_attachment.remote_file_url = #file_attachment.file.url
=> "https://my-bucket.s3-us-west-2.amazonaws.com/uploads/abcde-my-file.pdf?X-Amz-Expires=600&X-Amz-Date=20211009T202903Z&X-Amz-Algorithm=...&X-Amz-Credential=...&X-Amz-SignedHeaders=host&X-Amz-Signature=..."
irb(main)> #file_attachment.save
=> false
irb(main)> #file_attachment.errors.full_messages
=> ["File could not download file: 400 Bad Request"]
Despite the 400, I can confirm that #file_attachment.file.url is a valid, working URL, and when accessing the URL through a browser, the file is able to be downloaded just fine. For some reason though, it can't be downloaded from our app.
Can anyone spot what we're doing wrong? Or does anyone know of a better way to debug this ("400 Bad Request" isn't enough information). Thanks in advance!
Here's our bucket CORS:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"POST",
"PUT"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
And our environment details:
ruby '2.7.2'
gem 'rails', '~> 6.0.3'
gem 'carrierwave', '~> 2.1.0'
gem 'carrierwave_direct', '~> 2.1.0'
Thanks in advance!
Bumping CarrierWave versions from 2.1.0 to 2.2.0 ended up fixing this. No other changes were necessary.

Aws CostExplorer Api giving exception using ruby sdk

I found this reference https://docs.aws.amazon.com/sdkforruby/api/Aws/CostExplorer/Client.html#initialize-instance_method for finding cost of ec2 instance usages ,while in implementing phase i got exception.
in gem file i used this
gem 'aws-sdk', '~> 3'
cost_client = Aws::CostExplorer::Client.new(
region: "us-east-1",
access_key_id: "XXXX",
secret_access_key: "XXX"
)
resp = cost_client.get_cost_and_usage({
time_period: { # required
start: "2019-01-01", # required
end: "2019-05-01", # required
},
granularity: "DAILY", # accepts DAILY, MONTHLY, HOURLY
filter: {
or: [
{
# recursive Expression
},
],
and: [
{
# recursive Expression
},
],
not: {
# recursive Expression
},
dimensions: {
key: "AZ", # accepts AZ, INSTANCE_TYPE, LINKED_ACCOUNT, OPERATION, PURCHASE_TYPE, REGION, SERVICE, USAGE_TYPE, USAGE_TYPE_GROUP, RECORD_TYPE, OPERATING_SYSTEM, TENANCY, SCOPE, PLATFORM, SUBSCRIPTION_ID, LEGAL_ENTITY_NAME, DEPLOYMENT_OPTION, DATABASE_ENGINE, CACHE_ENGINE, INSTANCE_TYPE_FAMILY, BILLING_ENTITY, RESERVATION_ID
values: ["Value"],
},
tags: {
key: "TagKey",
values: ["Value"],
},
},
metrics: ["MetricName"],
group_by: [
{
type: "DIMENSION", # accepts DIMENSION, TAG
key: "GroupDefinitionKey",
},
],
next_page_token: "NextPageToken",
})
i got this excetion NameError: uninitialized constant Aws::CostExplorer.how can i get response from this api?
gems you used are not compatible with costexplorer sdk.
use this-
gem 'aws-sigv4', '~> 1.1'
gem 'aws-sdk-core', '~> 3.52', '>= 3.52.1'
gem 'aws-sdk-costexplorer', '~> 1.22'
Hope this will help you :)
You are using version 3 while your docs point to v2.
Check https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/CostExplorer.html, specially the following
This module provides support for AWS Cost Explorer Service. This
module is available in the aws-sdk-costexplorer gem.

How to get webpack2 and underscore-template loader + babel to work without getting "Module build failed: SyntaxError: 'with' in strict mode (5:0)"

I have a underscore template loader in my webpack2 config that is transpiled with babel. It fails at compile time because with is used in the code compiled code. Here is the relevant part in my loaders in webpack.config.js:
I have this section under loaders:
{
test: /\.html$/,
use: [
{
loader: 'babel-loader',
query: {
presets: [
['es2015', { modules: false }],
'es2016',
'es2017',
'stage-3',
],
},
},
{
loader: 'ejs-loader',
},
],
};
This is what I want and I get:
ERROR in ./src/table/row.html
Module build failed: SyntaxError: 'with' in strict mode (5:0)
3 | var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
4 | function print() { __p += __j.call(arguments, '') }
> 5 | with (obj) {
| ^
6 |
7 | _.each(tableKeys, (k) => { ;
8 | __p += '\n <td>' +
If I remove the babel part completely it works but with ES6 code not transpiled:
{
test: /\.html$/,
use: [
{
loader: 'ejs-loader',
},
],
};
I have also seen this question about removing strict mode and have tried several things related to es2015 applying strict. I think I have tried every solution in that question including hotpatching workaround and I still get the same error. In the end i tried this:
{
test: /\.html$/,
use: [
{
loader: 'babel-loader',
query: {
presets: [
],
},
},
{
loader: 'ejs-loader',
},
],
};
I though this should do the same as without the bable pass, but I get the same error here. Somehow without any presets I get the same error.
EDIT
I have also tried to work around it by passing variable in query and I have made that work with ejs-loader, however I'm not looking for a solution where all the templates need changing.
I have made a repository which illustrates the problem. The master branch has babel-loader commented out and works with with while the transpile branch will have compile errors even though { modules: false } is passed and I have a branch called transpile-no-presets where all presets in package.json is removed and the error is still showing.
By default Underscore .template put your data in the scope using a with statement. See Underscore docs.
I think the cleanest solution is to instruct your ejs-loader to not compile to with statements but to use a temporary variable instead:
{
loader: 'ejs-loader?variable=data',
},
...and change your templates to reference the temporary variable.
From:
<ul>
<% _.each(test, (n) => { %>
<li>This is line number <%- n %></li>
<% }); %>
</ul>
to:
<ul>
<% _.each(data.test, (n) => { %>
<li>This is line number <%- n %></li>
<% }); %>
</ul>
Use version 1.0 of underscore-template-loader instead.

Remote Execute Command using SSH from Rails Application

I have a Rails Application from which I will call one Ruby Definition in the controller, like this.
ssh root#host "uptime" >> /tmp/output
When I doing this, only the /tmp/output is created but not the content.
When I running the same from simple Ruby script its working fine.
my controller definition
def chefclient1
`ssh root#host "uptime" >> /tmp/output`
#time = Time.now
end
my view
= link_to('Start uptime', host_chefclient1_path)
You can use net-ssh gem to access remote host via ssh fo a ruby app. Set your environment up to:
HOSTNAME = 'host'
USER = 'root'
PASS = 'password'
Add to your_helper.rb: something like:
def chefclient1
result = nil
Net::SSH.start( ENV[ 'HOSTNAME' ], ENV[ 'USER' ], :password => ENV[ 'PASS' ] ) do| ssh |
result = ssh.exec! 'uptime'
puts result
end
File.open( '/tmp/output', 'w' ) {| f | f.puts result }
end
And use the helper method as you with from a view.

Fail to integrate CKeditor in rails_admin gem (use gem rich)

I follow the link GitHub gem rich to install CKeditor to rails_admin
but I get the error: Unsupported field datatype: rich_editor
My model
edit do
field :title
field :description, :rich_editor do
config({
:insert_many => true
})
end
field :autho
field :book_type
end
How can I fix this error? Or that's an issue?
EDIT:
I tried it, and it worked
field :content, :text do
ckeditor do true end
end
I couldn't get the Rich gem to work with a Rails 4 project using Rails admin, so I decided to use the standard CK Editor Gem which is the recommended course of action by the authors. It took all of 5 minutes to get it working following this:
https://github.com/sferik/rails_admin/wiki/CKEditor
Then I configured my CK_Editor to use a small subset of the available functionality.
After adding the CK_Editor gem and configuring my rails admin initializer, I created a new javascript file in my project at:
/app/assets/javascripts/ckeditor/config.js
with the following contents:
CKEDITOR.config.toolbar = [
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ],
items: [ 'Bold', 'Italic', 'Underline', 'Strike', '-', 'RemoveFormat' ] },
{ name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ],
items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote',
'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
{ name: 'links', items: [ 'Link', 'Unlink' ] },
];
Remember to restart your Rails server!
I have the same issue. I think it is an issue in rails_admin or in rich. I have successfully integrate these two together in past (but with old versions of both).
I have created github issues for this in rich (https://github.com/bastiaanterhorst/rich/issues/80) and rails_admin (https://github.com/sferik/rails_admin/issues/1585) repos.

Resources