I am really newbie to Ruby. I understand the language, but it is really hard for me to get the right way to structure project, there are a lot of articles and tutorials suggest running not with simple ruby
command but for example rackup
. I cannot get an idea of using other commands if my app using multiple gems, there are used as a wrappers ?
As for my project. I am creating simple API with Sinatra
& Rack & Sidekiq
, I am starting my app as follows.
rackup -p1600 --host 192.168.0.130 config.ru
But I've just started using sidekiq
and it required Redis server
I've installed it, now everything works no errors.
But the problem is that my task is not being processed.
Here is my example
My endpoint
post '/items' do
item_url = params[:item_url]
halt(400, {error: 'Item url is not provided'}.to_json) if item_url.nil?
begin
item_handler = ItemHandler.new item_url
item_handler.start_processing
item_handler.item_status.to_json
rescue APIErrors::AlreadyExistsError => e
halt(409, {error: e.message}.to_json)
rescue APIErrors::InvalidPayloadError => e
halt(400, {error: e.message}.to_json)
end
end
And my ItemHandler
Sidekiq.configure_server do |config|
config.redis = {password: 'password'}
end
Sidekiq.configure_client do |config|
config.redis = {password: 'password'}
end
class ItemHandler
...
...
...
def start_processing
ItemWorker.perform_async(@item.id)
end
And finnally ItemWorker
require 'sidekiq'
class ItemWorker
include Sidekiq::Worker
attr_accessor :item
def perform(id)
# Get item model
@item = ItemModel.where(_id: id)
logger.info "Doing hard work"
puts @item.status
# Start item processing
process_item
end
def process_item
logger.info "Doing hard work"
puts 'Start processing'
@item.status = ItemModel::STATUS[:downloading]
@item.save
result = download_item_file
if result > RESULT_OK
@item.status = ItemModel::STATUS[:failed_download]
@item.save
puts 'Failed to download file'
else
puts 'File downloaded'
@item.status = ItemModel::STATUS[:downloaded]
@item.save
end
end
def download_item_file
return if @item.nil?
dl_command = EXTERNAL_DOWNLOAD.dup
dl_command['|url|'] = @item.url
system dl_command
$?.exitstatus
end
end
And nothing happens, no output in console, nothing. Previously I've use fork
instead of sidekiq
and it worked fine.
Please help me to find the problem.
P.S. If I am doing something other in a wrong way (don't follow best practices & guidelines) please let me know.
Here is a complete example app using
sidekiq/redis
andsinatra
:sinatra_app.rb:
item_handler.rb:
item_worker.rb:
config.ru:
To get things up and running:
1) Download and install redis(not the same as the redis gem), then in terminal_window1 start redis:
2) Install the
sidekiq gem
(which will also install theredis gem
because it's a dependency):3) Start sidekiq in terminal_window2:
4) Launch the Sinatra app in terminal_window3:
5) Send a post request to your app in terminal_window4:
Immediately, the curl window will display the output:
and the sidekiq window will display the output:
Five seconds later, the sidekiq window will display:
And if you send three curl requests in rapid succession(up_arrow + Return):
then in the sideqik window you will see:
...time goes by...
Instead of taking a total of 15 seconds to run all three workers, after 5 seconds all three workers finished.