title: Asynchronous Jobs with large waiting time in Rails?
body: <p>So basically I have two instances, my Webserver and my Worker instance both deployed on Ruby on Rails using AWS ElasticBeanstalk. </p>
  
  <p>I just added a new job on my worker instance so it can create a xlsx file containing all db records from a certain model. This task usually takes up to 40 minutes to complete, the problem is when this job is ejecuting request usually stop working until the process is finished (including the healthcheck link). </p>
  
  <p>How can I make this job be independent from other request so it dosen't affect the ability of my worker instance to handle requests?</p>
  
  <p>Request arrive via SQS and handle by a controller (default Worker ElasticBeanstak profile) which determine what to do.</p>
  
  <p>XLSX files are currently handle by the following Job:</p>
  
  <pre><code>class NotifyJob &lt; ApplicationJob
      require 'json'
      require 'date'
      require 'aws-sdk'
      require 'rubyXL'
  
      queue_as :notify
  
      def perform(type)
        case type
          when 'doctor'
            start = Time.now
            doc = doctores
            S3.put_object({:bucket =&gt; 'cadigen-images', :key =&gt; 'doctor.xlsx', :body =&gt; doc.stream, :content_length =&gt; doc.stream.string.length, :content_type =&gt; doc.content_type.to_s, acl: "public-read"})
            after = Time.now
            link = Aws::S3::Object.new("cadigen-images","doctor.xlsx",:client =&gt; S3).public_url
            NotificationMailer.finished('Relacion Doctores',time(start,after),Doctor.count,"&lt;a href='#{link}'&gt;doctor.xlsx&lt;/a&gt;","frhectorin@gmail.com").deliver_now
          when 'cadi'
            start = Time.now
            cadi = cadis
            S3.put_object({:bucket =&gt; 'cadigen-images', :key =&gt; 'cadi.xlsx', :body =&gt; cadi.stream, :content_length =&gt; cadi.stream.string.length, :content_type =&gt; cadi.content_type.to_s, acl: "public-read"})
            after = Time.now
            link = Aws::S3::Object.new("cadigen-images","cadi.xlsx",:client =&gt; S3).public_url
            NotificationMailer.finished('Relacion CADIs',time(start,after),Cadi.count,"&lt;a href='#{link}'&gt; cadi.xlsx&lt;/a&gt;","frhectorin@gmail.com").deliver_now
          when 'conferencia'
            start = Time.now
            conf = conferencia
            S3.put_object({:bucket =&gt; 'cadigen-images', :key =&gt; 'conferencia.xlsx', :body =&gt; conf.stream, :content_length =&gt; conf.stream.string.length, :content_type =&gt; conf.content_type.to_s, acl: "public-read"})
            after = Time.now
            link = Aws::S3::Object.new("cadigen-images","conferencia.xlsx",:client =&gt; S3).public_url
            NotificationMailer.finished('Relacion Conferencia',time(start,after) ,Conferencia.count,"&lt;a href='#{link}'&gt;conferencia.xlsx&lt;/a&gt;","frhectorin@gmail.com").deliver_now
          else
            render status: 500
        end
      end
  
      def time(start,ending)
        if start != ending
          medidas=["año","mes","dia","hora","minuto","segundo"]
          array=[1970,1,1,0,0,0]
          text = ""
          Time.at(ending-start).utc.to_a.take(6).reverse.each_with_index do |k,i|
            text = "#{text} #{I18n.translate medidas[i].to_sym, count: k-array[i]}"
          end
          text = text.strip.squish
          puts text
          pos = text.rindex(" ",(text.rindex(" ")-1))
          unless pos.nil?
            text = text.insert(pos," y")
          end
          text = text.strip.squish
        else
          "0 segundos"
        end
      end
  
      def doctores
        workbook = RubyXL::Workbook.new
        worksheet = workbook[0]
  
        worksheet.add_cell(0, 0,'ID')
        worksheet.add_cell(0, 1,'Cuenta')
        worksheet.add_cell(0, 2,'Titulo')
        worksheet.add_cell(0, 3,'Nombre')
        worksheet.add_cell(0, 4,'Email')
        worksheet.add_cell(0, 5,'Pais')
        worksheet.add_cell(0, 6,'Verificado')
        worksheet.add_cell(0, 7,'Autoriza Envio de Emails')
        worksheet.add_cell(0, 8,'Activo')
        worksheet.add_cell(0, 9,'Bounce')
        worksheet.add_cell(0, 10,'Complains')
        worksheet.add_cell(0, 11,'CADIS')
  
        doctores = Doctor.order(:id)
  
        doctores.each_with_index do |doctor,i|
          i=i+1
          worksheet.add_cell(i, 0, doctor.id)
          worksheet.add_cell(i, 1, doctor.cuenta)
          worksheet.add_cell(i, 2, doctor.titulo)
          worksheet.add_cell(i, 3, doctor.nombre)
          worksheet.add_cell(i, 4, doctor.email)
          worksheet.add_cell(i, 5, doctor.pais)
          worksheet.add_cell(i, 6, doctor.verified ? 'Si':'No')
          worksheet.add_cell(i, 7, doctor.email_authorized ? 'Si':'No')
          worksheet.add_cell(i, 8, doctor.active ? 'Si':'No')
          worksheet.add_cell(i, 9, doctor.bounce ? 'Si':'No')
          worksheet.add_cell(i, 10, doctor.complains ? 'Si':'No')
          worksheet.add_cell(i, 11, doctor.count)
        end
  
        return workbook
  
        #send_data workbook.stream.string, filename: "doctor.xlsx", disposition: 'attachment'
  
      end
  
      def conferencia
        workbook = RubyXL::Workbook.new
        worksheet = workbook[0]
  
        worksheet.add_cell(0, 0,'ID')
        worksheet.add_cell(0, 1,'Conferencia')
        worksheet.add_cell(0, 2,'Conferencista')
        worksheet.add_cell(0, 3,'Numero de Conferencia')
        worksheet.add_cell(0, 4,'Fecha')
        worksheet.add_cell(0, 5,'Tema')
        worksheet.add_cell(0, 6,'Patrocinador')
        worksheet.add_cell(0, 7,'Estatus')
        worksheet.add_cell(0, 8,'Acreditaciones')
  
        conferencias = Conferencia.order(:id)
  
        conferencias.each_with_index do |conferencia,i|
          i=i+1
          worksheet.add_cell(i, 0, conferencia.id)
          worksheet.add_cell(i, 1, conferencia.conferencia)
          worksheet.add_cell(i, 2, conferencia.conferencista)
          worksheet.add_cell(i, 3, conferencia.numero_conferencia)
          worksheet.add_cell(i, 4, conferencia.fecha.strftime('%d-%m-%Y %H:%M:%S'))
          worksheet.add_cell(i, 5, conferencia.tema)
          worksheet.add_cell(i, 6, conferencia.patrocinador)
          worksheet.add_cell(i, 7, conferencia.status ? 'Acreditada':'Sin Acreditar')
          worksheet.add_cell(i, 8, conferencia.count)
        end
  
        return workbook
  
        #send_data workbook.stream.string, filename: "doctor.xlsx", disposition: 'attachment'
  
      end
  
      def cadis
        workbook = RubyXL::Workbook.new
        worksheet = workbook[0]
  
        worksheet.add_cell(0, 0,'ID')
        worksheet.add_cell(0, 1,'Numero de CADI')
        worksheet.add_cell(0, 2,'Email')
        worksheet.add_cell(0, 3,'Cuenta')
        worksheet.add_cell(0, 4,'Conferencia')
  
        cadis = Cadi.order(:id)
  
        cadis.each_with_index do |cadi,i|
          i=i+1
          worksheet.add_cell(i, 0, cadi.id)
          worksheet.add_cell(i, 1, cadi.numero_cadi)
          worksheet.add_cell(i, 2, cadi.doctor.email)
          worksheet.add_cell(i, 3, cadi.doctor.cuenta)
          worksheet.add_cell(i, 4, cadi.conferencia.conferencia)
        end
  
        return workbook
  
        #send_data workbook.stream.string, filename: "doctor.xlsx", disposition: 'attachment'
  
      end
  end
  </code></pre>
  
  <p>And call using</p>
  
  <pre><code>NotifyJob.perform_now(type)
  </code></pre>
  
  <p>My queue handler is <a href="https://github.com/tawan/active-elastic-job" rel="nofollow noreferrer">active-elastic-job</a></p>