Class: SubscribeUserWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Worker
Defined in:
app/workers/subscribe_user_worker.rb

Overview

Background job to subscribe a user to a feed.

This is a Sidekiq worker

Instance Method Summary collapse

Instance Method Details

#perform(user_id, feed_url, job_state_id) ⇒ Object

Subscribe a user to a feed

Receives as arguments:

  • id of the user

  • url of the feed

  • id of the SubscribeJobState instance that reflects the state of the job

The state field of the SubscribeJobState instance will be updated when the job finishes, to reflect whether it finished successfully or with an error.

This method is intended to be invoked from Sidekiq, which means it is performed in the background.


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'app/workers/subscribe_user_worker.rb', line 24

def perform(user_id, feed_url, job_state_id)
  # Find the SubscribeJobState instance for this job, if it exists
  if SubscribeJobState.exists? job_state_id
    job_state = SubscribeJobState.find job_state_id
    # Check that the subscribe_job_state is in state "RUNNING"
    if job_state.state != SubscribeJobState::RUNNING
      Rails.logger.error "Processing SubscribeUserWorker for subscribe_job_state_id #{job_state_id}, it should be in state RUNNING but it is in state #{job_state.state}. Aborting."
      return
    end
  else
    Rails.logger.error "Processing SubscribeUserWorker for subscribe_job_state_id #{job_state_id}, but no job state with that ID exists. Aborting."
    return
  end

  # Check if the user actually exists
  if !User.exists? user_id
    Rails.logger.error "Trying to add subscription to non-existing user @#{user_id}, aborting job"
    job_state.destroy if job_state.present?
    return
  end
  user = User.find user_id

  Rails.logger.info "Subscribing user #{user.id} - #{user.email} to feed #{feed_url}"
  feed = user.subscribe feed_url

  # Set job state to "SUCCESS" and save the id of the actually subscribed feed
  job_state.update state: SubscribeJobState::SUCCESS, feed_id: feed.id if job_state.present?
rescue RestClient::Exception,
    RestClient::RequestTimeout,
    SocketError,
    Net::HTTPBadResponse,
    Errno::ETIMEDOUT,
    Errno::ECONNREFUSED,
    Errno::EHOSTUNREACH,
    Errno::ECONNRESET,
    Zlib::GzipFile::Error,
    Zlib::DataError,
    OpenSSL::SSL::SSLError,
    AlreadySubscribedError,
    EmptyResponseError,
    FeedAutodiscoveryError,
    FeedFetchError,
    OpmlImportError => e
  # all these errors mean the feed cannot be subscribed, but the job itself has not failed. Do not re-raise the error
  Rails.logger.warn "Controlled error subscribing user #{user&.id} - #{user&.email} to feed URL #{feed_url}: #{e.message}"
  job_state.update state: SubscribeJobState::ERROR if job_state.present?
rescue => e
  Rails.logger.error "Uncontrolled error subscribing user #{user&.id} - #{user&.email} to feed URL #{feed_url}"
  Rails.logger.error e.message
  Rails.logger.error e.backtrace
  job_state.update state: SubscribeJobState::ERROR if job_state.present?
  # The job has failed. Re-raise the exception so that Sidekiq takes care of it
  raise e
end