• 帖子为什么没有置顶呢?连一些招聘贴都可以置顶。这个不应该顶一下?

  • param[:type_id] = params[:thirdCategory] || params[:secondCategory] || params[:topCategory]
    
  • 之前其实没出现过这个问题。自从用了 sendcloud 作为邮件服务器以后才出现的,所以怀疑是smtp超时导致的。但是看代码 net/smtp 这个库在初始化的时候已经设置超时时间了。所以也不知道该咋办了。

    # Creates a new Net::SMTP object.
    #
    # +address+ is the hostname or ip address of your SMTP
    # server.  +port+ is the port to connect to; it defaults to
    # port 25.
    #
    # This method does not open the TCP connection.  You can use
    # SMTP.start instead of SMTP.new if you want to do everything
    # at once.  Otherwise, follow SMTP.new with SMTP#start.
    #
    def initialize(address, port = nil)
      @address = address
      @port = (port || SMTP.default_port)
      @esmtp = true
      @capabilities = nil
      @socket = nil
      @started = false
      @open_timeout = 30
      @read_timeout = 60
      @error_occurred = false
      @debug_output = nil
      @tls = false
      @starttls = false
      @ssl_context = nil
    end
    
  • 下面三段代码可以回答你的问题。sidekiq会先设置一段时间让正在执行的任务执行。如果在一定时间内没执行完成的就会强行关掉并重新把任务塞回到redis里面,启动的时候执行。

    https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/launcher.rb#L37

    module Sidekiq
      class Launcher
        # Shuts down the process.  This method does not
        # return until all work is complete and cleaned up.
        # It can take up to the timeout to complete.
        def stop
          deadline = Time.now + @options[:timeout]
    
          @done = true
          @manager.quiet
          @poller.terminate
    
          @manager.stop(deadline)
    
          # Requeue everything in case there was a worker who grabbed work while stopped
          # This call is a no-op in Sidekiq but necessary for Sidekiq Pro.
          strategy = (@options[:fetch] || Sidekiq::BasicFetch)
          strategy.bulk_requeue([], @options)
    
          clear_heartbeat
        end
      end
    end
    

    https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/manager.rb#L62

    module Sidekiq
      class Manager
        def stop(deadline)
          quiet
          fire_event(:shutdown, reverse: true)
    
          # some of the shutdown events can be async,
          # we don't have any way to know when they're done but
          # give them a little time to take effect
          sleep PAUSE_TIME
          return if @workers.empty?
    
          logger.info { "Pausing to allow workers to finish..." }
          remaining = deadline - Time.now
          while remaining > PAUSE_TIME
            return if @workers.empty?
            sleep PAUSE_TIME
            remaining = deadline - Time.now
          end
          return if @workers.empty?
    
          hard_shutdown
        end
      end
    end
    

    https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/manager.rb#L107

    module Sidekiq
      class Manager
        def hard_shutdown
          # We've reached the timeout and we still have busy workers.
          # They must die but their jobs shall live on.
          cleanup = nil
          @plock.synchronize do
            cleanup = @workers.dup
          end
    
          if cleanup.size > 0
            jobs = cleanup.map {|p| p.job }.compact
    
            logger.warn { "Terminating #{cleanup.size} busy worker threads" }
            logger.warn { "Work still in progress #{jobs.inspect}" }
    
            # Re-enqueue unfinished jobs
            # NOTE: You may notice that we may push a job back to redis before
            # the worker thread is terminated. This is ok because Sidekiq's
            # contract says that jobs are run AT LEAST once. Process termination
            # is delayed until we're certain the jobs are back in Redis because
            # it is worse to lose a job than to run it twice.
            strategy = (@options[:fetch] || Sidekiq::BasicFetch)
            strategy.bulk_requeue(jobs, @options)
          end
    
          cleanup.each do |processor|
            processor.kill
          end
        end
    
      end
    end
    

frech@foxmail.com