In Rails application I am trying to generate PDF basing on HTML page using Grover gem:
https://github.com/Studiosity/grover
PDF is generated properly, but just after that my Docker container is instantly killed. Problem doesn't occur in local environment, only inside docker.
Controller action:
def generate_pdf
grover = Grover.new('http://google.com', format: 'A4')
pdf = grover.to_pdf
send_data(pdf, filename: 'dummypdf.pdf', type: 'application/pdf')
end
config/initializers/grover.rb
Grover.configure do |config|
config.options = {
format: 'A4',
margin: {
top: '5px',
bottom: '10cm'
},
viewport: {
width: 640,
height: 480
},
prefer_css_page_size: true,
emulate_media: 'screen',
cache: false,
timeout: 0, # Timeout in ms. A value of `0` means 'no timeout'
request_timeout: 10000, # Timeout when fetching the content (overloads the `timeout` option)
convert_timeout: 20000, # Timeout when converting the content (overloads the `timeout` option, only applies to PDF conversion)
launch_args: ['--font-render-hinting=medium', '--no-sandbox', '--lang=ja', '--disable-dev-shm-usage', '--disable-gpu', '--disable-setuid-sandbox'],
wait_until: 'domcontentloaded'
}
end
Server log:
test_container_1 | 14:54:11 rails.1 | 2022-02-18 14:54:11.885970 I [7:puma server threadpool 003] {request_id: d9fc817c-1a51-4c25-80ac-da0f5c224f34} (4.743s) ProfilesController -- Completed #generate_pdf -- { :controller => "ProfilesController", :action => "generate_pdf", :params => { "kid_id" => "2" }, :format => "HTML", :method => "GET", :path => "/records/2/profile/generate_pdf", :status => 200, :view_runtime => 7.61, :allocations => 51203, :status_message => "OK" }
test_container_1 | 14:54:12 | exited with code 0
test_container_1 | 14:54:12 system | sending SIGTERM to all processes
test_container_1 | 14:54:12 | exited with code 0
test_container_1 | 14:54:12 rails.1 | - Gracefully stopping, waiting for requests to finish
test_container_1 | 14:54:12 rails.1 | Exiting
test_container_1 | 14:54:12 | exited with code 0
test_container_1 | 14:54:12 rails.1 | terminated by SIGTERM
test_container_1 | 14:54:12 webpack.1 | exited with code 0
I will be grateful for any suggestions how to deal with this issue (I also tried Dhalang gem instead of Grover but the result was the same)
Related
I've read countless articles, including this which sounded almost exactly like my setup/issue:
Xdebug inside Docker on Mac M1 2021 is not working
I'm getting the error message mentioned in the title, still.
Here is how I spin up the container (which ships with PHPUnit and XDebug):
docker run --rm -it -v $(pwd):/app -v $(pwd)/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini jitesoft/phpunit /bin/ash
Here is the debug.ini I use to overwrite the defaults:
;
; NOTE: We want to echo these contents to this file location
;
; PATH: /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
;
zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20220829/xdebug.so
xdebug.mode=debug
xdebug.idekey=PHPSTORM
xdebug.start_with_request=yes
xdebug.discover_client_host=0
xdebug.client_host=host.docker.internal
xdebug.log=/var/log/xdebug.log
Here is the debug config dump:
[1m__ __ _ _
[1m\ \ / / | | | |
[1m \ V / __| | ___| |__ _ _ __ _
[1m > < / _` |/ _ \ '_ \| | | |/ _` |
[1m / . \ (_| | __/ |_) | |_| | (_| |
[1m/_/ \_\__,_|\___|_.__/ \__,_|\__, |
[1m __/ |
[1m |___/
[0mVersion => 3.2.0
Support Xdebug on Patreon, GitHub, or as a business: https://xdebug.org/support
Enabled Features (through 'XDEBUG_MODE' env variable)
Feature => Enabled/Disabled
Development Helpers => ✘ disabled
Coverage => ✔ enabled
GC Stats => ✘ disabled
Profiler => ✘ disabled
Step Debugger => ✘ disabled
Tracing => ✘ disabled
Optional Features
Compressed File Support => no
Clock Source => clock_gettime
'xdebug://gateway' pseudo-host support => yes
'xdebug://nameserver' pseudo-host support => no
Systemd Private Temp Directory => not enabled
Diagnostic Log
No messages
PHP
Build Configuration
Version (Run Time) => 8.2.1
Version (Compile Time) => 8.2.1
Debug Build => no
Thread Safety => disabled
Settings
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => (none)
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
Additional .ini files parsed => /usr/local/etc/php/conf.d/date_timezone.ini,
/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini,
/usr/local/etc/php/conf.d/memory-limit.ini
Directive => Local Value => Master Value
xdebug.mode (through XDEBUG_MODE) => coverage => debug
xdebug.start_with_request => yes => yes
xdebug.start_upon_error => default => default
xdebug.output_dir => /tmp => /tmp
xdebug.use_compression => 0 => 0
xdebug.trigger_value => no value => no value
xdebug.file_link_format => no value => no value
xdebug.filename_format => no value => no value
xdebug.log => /var/log/xdebug.log => /var/log/xdebug.log
xdebug.log_level => 7 => 7
xdebug.var_display_max_children => 128 => 128
xdebug.var_display_max_data => 512 => 512
xdebug.var_display_max_depth => 3 => 3
xdebug.max_nesting_level => 256 => 256
xdebug.cli_color => 0 => 0
xdebug.force_display_errors => Off => Off
xdebug.force_error_reporting => 0 => 0
xdebug.halt_level => 0 => 0
xdebug.max_stack_frames => -1 => -1
xdebug.show_error_trace => Off => Off
xdebug.show_exception_trace => Off => Off
xdebug.show_local_vars => Off => Off
xdebug.dump.COOKIE => no value => no value
xdebug.dump.ENV => no value => no value
xdebug.dump.FILES => no value => no value
xdebug.dump.GET => no value => no value
xdebug.dump.POST => no value => no value
xdebug.dump.REQUEST => no value => no value
xdebug.dump.SERVER => no value => no value
xdebug.dump.SESSION => no value => no value
xdebug.dump_globals => On => On
xdebug.dump_once => On => On
xdebug.dump_undefined => Off => Off
xdebug.profiler_output_name => cachegrind.out.%p => cachegrind.out.%p
xdebug.profiler_append => Off => Off
xdebug.cloud_id => no value => no value
xdebug.client_host => host.docker.internal => host.docker.internal
xdebug.client_port => 9003 => 9003
xdebug.discover_client_host => Off => Off
xdebug.client_discovery_header => HTTP_X_FORWARDED_FOR,REMOTE_ADDR => HTTP_X_FORWARDED_FOR,REMOTE_ADDR
xdebug.idekey => PHPSTORM => PHPSTORM
xdebug.connect_timeout_ms => 200 => 200
xdebug.scream => Off => Off
xdebug.gc_stats_output_name => gcstats.%p => gcstats.%p
xdebug.trace_output_name => trace.%c => trace.%c
xdebug.trace_format => 0 => 0
xdebug.trace_options => 0 => 0
xdebug.collect_assignments => Off => Off
xdebug.collect_return => Off => Off
Here is the result on the console when I try and run index.php for debugging:
[docker://jitesoft/phpunit:latest/]:php -dxdebug.mode=debug -dxdebug.client_port=9000 -dxdebug.client_host=host.docker.internal -dxdebug.client_host=host.docker.internal /opt/project/index.php
Process finished with exit code 0
Two things jump out at me
The top of the debug configure dump suggests step debugging is still disabled???
The path to the php script I want to execute on the docker side is /app/index.php not /opt/project/index.php
Thoughts?
There is a chain of state machine callbacks that invoke ActiveJob::Base classes to process sequential phases of an order lifecycle.
I am running into a problem where the second job in the sequence is not being enqueued and no errors are being printed to the terminal.
The second job is
class WriteEncodedPreviewImageToFilesJob < ActiveJob::Base
queue_as :imagery_queue
def perform(order)
run_phase_of_order_lifecycle(order)
end
private
def run_phase_of_order_lifecycle(order)
begin
BackgroundWorkers::EncodedPreviewImageWriter.work(order)
ensure
order.render_final_image
end
end
end
And it is being invoked here:
class PreAuthorizeStripePaymentJob < ActiveJob::Base
queue_as :stripe_queue
def perform(order)
run_phase_of_order_lifecycle(order)
end
private
def run_phase_of_order_lifecycle(order)
response = create_stripe_charge(order)
if response['failure_code'] == nil
order.stripe_charge_id = response['id']
order.save!
order.write_encoded_preview_image_to_files # this line here!!!
end
response
end
def create_stripe_charge(order)
Stripe::Charge.create(
:amount => (order.original[:order][:price] * 100).round,
:currency => 'gbp',
:capture => false,
:source => order.stripe_id,
:description => "Charge for Order with id: #{order.id}",
:receipt_email => order.original[:order][:user_email]
)
end
end
Because of the callback defined in this module (please scroll down):
module OrderLifecycle
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
state_machine :initial => :pending do
# States
event :pre_authorize_stripe_payment do
transition :pending => :stripe_payment_pre_authorized
end
event :write_encoded_preview_image_to_files do
transition :stripe_payment_pre_authorized => :encoded_preview_image_written_to_files # this line here!!! and...
end
event :render_final_image do
transition :encoded_preview_image_written_to_files => :final_image_rendered
end
event :upload_composition_to_parse do
transition :final_image_rendered => :composition_uploaded_to_parse
end
event :upload_print_file_to_printer do
transition :composition_uploaded_to_parse => :print_file_uploaded_to_printer
end
event :call_to_process_message do
transition :print_file_uploaded_to_printer => :process_message_called
end
event :capture_stripe_payment do
transition :process_message_called => :stripe_payment_captured
end
event :mark_as_complete do
transition :stripe_payment_captured => :complete
end
# Callbacks
before_transition :on => :pre_authorize_stripe_payment do |order|
PreAuthorizeStripePaymentJob.perform_later order
end
before_transition :on => :write_encoded_preview_image_to_files do |order|
WriteEncodedPreviewImageToFilesJob.perform_later order # this line here!!!
end
before_transition :on => :render_final_image do |order|
RenderFinalImageJob.perform_later order
end
before_transition :on => :upload_composition_to_parse do |order|
UploadCompositionToParseJob.perform_later order
end
before_transition :on => :upload_print_file_to_printer do |order|
UploadPrintFileToPrinterJob.perform_later order
end
before_transition :on => :call_to_process_message do |order|
CallToProcessMessageJob.perform_later order
end
before_transition :on => :capture_stripe_payment do |order|
CaptureStripePaymentJob.perform_later order
end
end
end
end
My config/sidekiq.yml is
---
:verbose: true
:queues:
- imagery_queue
- parse_queue
- stripe_queue
- printer_api_queue
When I start Sidekiq initially the output to the terminal is:
2015-12-14T03:00:25.339Z 7664 TID-akza0 INFO: Booting Sidekiq 3.5.0 with redis options {:url=>"redis://localhost:6379"}
m,
`$b
.ss, $$b .,d$
`$$P,d$P' .,md$$P' ____ _ _ _ _
,$$$$$$bmmd$$$^' / ___|(_) __| | ___| | _(_) __ _
,d$$$$$$$$$$$P \___ \| |/ _` |/ _ \ |/ / |/ _` |
$s^' `"^$$$' ___) | | (_| | __/ <| | (_| |
$: ,$$P |____/|_|\__,_|\___|_|\_\_|\__, |
`b :$$ |_|
$$:
$$
.d$$
2015-12-14T03:00:28.076Z 7664 TID-akza0 INFO: Running in ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
2015-12-14T03:00:28.077Z 7664 TID-akza0 INFO: See LICENSE and the LGPL-3.0 for licensing details.
2015-12-14T03:00:28.077Z 7664 TID-akza0 INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org
2015-12-14T03:00:28.091Z 7664 TID-akza0 DEBUG: Middleware: Sidekiq::Middleware::Server::Logging, Sidekiq::Middleware::Server::RetryJobs, Sidekiq::Middleware::Server::ActiveRecord
2015-12-14T03:00:28.091Z 7664 TID-akza0 INFO: Starting processing, hit Ctrl-C to stop
2015-12-14T03:00:28.104Z 7664 TID-wjesw DEBUG: {:queues=>["imagery_queue", "parse_queue", "stripe_queue", "printer_api_queue"], :labels=>[], :concurrency=>25, :require=>".", :environment=>nil, :timeout=>8, :poll_interval_average=>nil, :average_scheduled_poll_interval=>15, :error_handlers=>[#<Sidekiq::ExceptionHandler::Logger:0x00000002a28dc8>], :lifecycle_events=>{:startup=>[], :quiet=>[], :shutdown=>[]}, :dead_max_jobs=>10000, :dead_timeout_in_seconds=>15552000, :verbose=>true, :config_file=>"config/sidekiq.yml", :strict=>true, :tag=>"xxxxxxxxx"}
The problem was in calling the write_encoded_preview_image_to_files method prematurely. Substituting write_encoded_preview_image_to_files! and inserting a binding.pry revealed:
9: def run_phase_of_order_lifecycle(order)
10: response = create_stripe_charge(order)
11: if response['failure_code'] == nil
12: order.stripe_charge_id = response['id']
13: order.save!
14: binding.pry
15: order.write_encoded_preview_image_to_files!
16: end
=> 17: response
18: end
[1] pry(#<PreAuthorizeStripePaymentJob>)> order.state
=> "pending"
[2] pry(#<PreAuthorizeStripePaymentJob>)> order.write_encoded_preview_image_to_files!
StateMachines::InvalidTransition: Cannot transition state via :write_encoded_preview_image_to_files from :pending (Reason(s): State cannot transition via "write encoded preview image to files")
from /home/*****/.rvm/gems/ruby-2.2.2/gems/state_machines-0.4.0/lib/state_machines/event.rb:224:in `block in add_actions'
[3] pry(#<PreAuthorizeStripePaymentJob>)> order.write_encoded_preview_image_to_files
Then checking the order's state in the rails console after the job had been processed:
2.2.2 :044 > Order.last.state
Order Load (1.2ms) SELECT "orders".* FROM "orders" ORDER BY "orders"."id" DESC LIMIT 1
=> "stripe_payment_pre_authorized"
2.2.2 :045 >
Therefore this problem may be solved by adding the following callback to the OrderLifecycle module:
after_transition :on => :pre_authorize_stripe_payment do |order|
order.write_encoded_preview_image_to_files
end
When trying to run rspec spec/controllers/api_controller_spec.rb:406 --color command on linux machine. We already have redis server running at port 6379 but as below error Unable to load rspec spec_helper configuration & getting error:
Code:
REDIS_PID = "/var/run/redis.pid"
REDIS_CACHE_PATH = "tmp/cache/"
Dir.mkdir "#{Rails.root}/tmp" unless Dir.exists? "#{Rails.root}/tmp"
Dir.mkdir "#{Rails.root}/tmp/pids" unless Dir.exists? "#{Rails.root}/tmp/pids"
Dir.mkdir "#{Rails.root}/tmp/cache" unless Dir.exists? "#{Rails.root}/tmp/cache"
config.before(:suite) do
redis_options = {
"daemonize" => 'yes',
"pidfile" => 7528,
"port" => 6379,
"timeout" => 300,
"save 900" => 1,
"save 300" => 1,
"save 60" => 10000,
"dbfilename" => "dump.rdb",
"dir" => REDIS_CACHE_PATH,
"loglevel" => "debug",
"logfile" => "stdout",
"databases" => 16
}.map { |k, v| "#{k} #{v}" }.join("\n")
`echo '#{redis_options}' | redis-server -`
end
config.after(:suite) do
%x{
cat #{REDIS_PID} | xargs kill -QUIT
rm -f #{REDIS_CACHE_PATH}dump.rdb
}
end
Error:
------------
------------
------------
Finished searching in 0.09762763977050781 seconds.
Request#<ActionController::TestRequest:0x00000004139f58>
^[[?1;2c^[[?1;2c^[[?1;2c^[[?1;2c^[[?1;2c^[[?1;2cFcat: /var/run/redis.pid: No such file or directory
usage: kill [ -s signal | -p ] [ -a ] pid ...
kill -l [ signal ]
------------
------------
------------
Restart the redis server redis-server stop/start. The redis.pid file generated and rspec is able to access the redis configuration during background processing.
An integration spec includes:
click_on "submit_order"
order = Order.last
binding.pry_remote
Why, then, is the following possible?
And how do I fix it?
From: /Users/steven/Dropbox/Testivate/spec/features/order_spec.rb # line 44 :
43: order = Order.last
=> 44: binding.pry_remote
[1] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1>)> order
=> nil
[2] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_1>)> Order.last
+----+----------+----------+----------+----------+----------+---------+----------+----------+----------+----------+
| id | company | url | comp1 | comp2 | comp3 | user_id | guest... | guest... | creat... | updat... |
+----+----------+----------+----------+----------+----------+---------+----------+----------+----------+----------+
| 1 | The Nile | http:... | http:... | http:... | http:... | 1 | | | 2014-... | 2014-... |
+----+----------+----------+----------+----------+----------+---------+----------+----------+----------+----------+
1 row in set
UPDATE:
I tried:
Order.connection.reconnect!
No change.
UPDATE II
When you change the integration spec to read...
click_on "submit_order"
save_and_open_page
order = Order.last
...the Order table reloads correctly and order is the last Order.
But why?
There are no callbacks on Order or User.
The HTTP POST operation is not synchronous with the database update, so your Order.last method call is likely getting completed before the database write has been completed. You would "fix" this by awaiting some positive confirmation that the submission has been completed (e.g. redirect, flash message, etc.).
I want to have URL like www.mydomain.com/category/parent/child so my routes are get '/category/:name(/:name)' => 'categories#show'
I got a table 'categories' like
> desc categories;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| public_id | int(11) | YES | | NULL | |
| name | varchar(255) | YES | | NULL | |
| root | int(11) | YES | | NULL | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
I populate the database like this
Category.create(:public_id => 60, :name => "nues", :root => 0)
Category.create(:public_id => 61, :name => "artistiques", :root => 60)
Category.create(:public_id => 62, :name => "glamours", :root => 60)
Category.create(:public_id => 63, :name => "fetichiste", :root => 60)
Category.create(:public_id => 69, :name => "autres", :root => 60)
So if root = 0 so it's a parent category. If root > 0the category is a child from the root value
My Categorie_Controller show action. The problem is that categories got the same name like 'Nature -> Others' and 'Portrait -> Others'. So my find_by_name doesn't work properly
def show
if request.get?
#photographs = Category.find_by_name(params[:name]).photographs
end
end
Is-it possible to do what I want with my routes system ?
Don't pick the same name for the param variables.
# config/routes.rb
get '/category/:name(/:child_name)', to: 'categories#show'
# app/controllers/categories_controller.rb
def show
# Now params[:name] and params[:child_name] are available
# BTW: Only get requests will be routed anyways with your routes definition
#photographs = if params[:child_name].present?
parent = Category.find_by!(name: params[:name])
Category.find_by!(name: params[:child_name], root: parent.id)
else
Category.find_by!(name: params[:name])
end
end
Hope these hints help.
Additionally, you can see your incoming params by raising them in the controller action:
raise params.inspect