bk5115545
bk5115545

Reputation: 69

Long sleep in Ruby

I have a rather large Sinatra app (about 4k lines) and one portion of it involves generating reports for the user to download.

I want the reports to auto-delete after so many days even if the webserver is restarted. I don't have a daemon process on the server and it's Windows or else I would just throw up some cron.

How is this kind of thing normally done?

I was thinking about something like the below but it wouldn't persist after server restart.

report_filename = "asdasdsad.pdf"
generate report(report_filename)
Thread.new {
  sleep((60*60*24) * 7) # wait 7 days
  File.delete(report_filename)
}

Upvotes: 0

Views: 234

Answers (3)

mwp
mwp

Reputation: 8467

Normally you would use cron or some kind of job queue like delayed_job or Sidekiq. You can do cron jobs in Windows with the Task Scheduler or the command-line AT command. If that isn't an option for some other reason, you can do something like wp-cron, which uses incoming requests as a kind of timer to see if there are any jobs that need to be run. It would look like:

require 'sinatra'
require 'date'

class App < Sinatra::Base
  configure do
    set :report_dir, '/path/to/reports'
    set :keep_for, 7 # days
  end

  helpers do
    def generate
      # write .pdf to settings.report_dir and return path to pdf
    end

    def cleanup
      Dir.glob(File.expand_path('*.pdf', settings.report_dir)) do |pdf|
        stat = File.lstat(pdf)
        File.unlink(pdf) if stat.file? and Date.today - stat.ctime.to_date > settings.keep_for
      end
    rescue Errno::ENOENT
      # another thread is working
    end
  end

  post '/generate_report' do
    send_file generate
  end

  after do
    Thread.new { cleanup } if rand < 0.01 # 1% of requests trigger cleanup
  end
end

This is obviously a simplistic example to get you started. You might consider using a mutex as well if you're concerned about multiple cleanup threads running concurrently and interfering with each other, and catching the ENOENT becomes expensive.

Upvotes: 1

koffeinfrei
koffeinfrei

Reputation: 2055

Either

  1. Use the windows task scheduler (there is an equivalent to cronjobs on windows, see https://stackoverflow.com/a/132975/232838 for more info)
  2. Just check for old files to be deleted every time you create a new report. I don't assume that it's a problem for reports to lie around a bit too long (I assume you want to delete the old files for storage reasons).

Upvotes: 1

mcfinnigan
mcfinnigan

Reputation: 11638

How is this kind of thing normally done?

A couple of ways in the event you don't have cron or similar schedulers on the system.

  1. A messaging server such as RabbitMQ, onto which you place a message with some sort of property that prevents the message from being processed and consumed until after a certain amount of time has elapsed.

  2. A service such as resque

  3. A daemon job in your server which checks the reports folder once a day (perhaps at 2am or some other less busy time) and removes files created more than a week prior

  4. Similar to above, a daemon job which checks a db table that lists the filenames, and issues deletes for files created more than a week ago.

Upvotes: 3

Related Questions