Class: CoalescingPanda::Workers::AccountMiner

Inherits:
Object
  • Object
show all
Defined in:
app/models/coalescing_panda/workers/account_miner.rb

Constant Summary collapse

SUPPORTED_MODELS =
[:courses, :users]
COMPLETED_STATUSES =
['Completed', 'Error']
RUNNING_STATUSES =
['Queued', 'Started']

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(account, options = []) ⇒ AccountMiner

Returns a new instance of AccountMiner.



8
9
10
11
12
13
14
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 8

def initialize(, options = [])
  @account = 
  @options = options
  @batch = setup_batch
  @user_ids = []
  @course_ids = []
end

Instance Attribute Details

#accountObject

Returns the value of attribute account.



6
7
8
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 6

def 
  @account
end

#batchObject

Returns the value of attribute batch.



6
7
8
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 6

def batch
  @batch
end

#course_idsObject

Returns the value of attribute course_ids.



6
7
8
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 6

def course_ids
  @course_ids
end

#optionsObject

Returns the value of attribute options.



6
7
8
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 6

def options
  @options
end

#user_idsObject

Returns the value of attribute user_ids.



6
7
8
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 6

def user_ids
  @user_ids
end

Instance Method Details

#api_clientObject



27
28
29
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 27

def api_client
  @api_client ||= Bearcat::Client.new(prefix: .settings[:base_url], token: .settings[:account_admin_api_token])
end

#process_api_data(key) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 62

def process_api_data(key)
  case key
  when :courses
    collection = api_client.(.).all_pages!
    sync_courses(collection)
  when :users
    collection = api_client.list_users(.).all_pages!
    sync_users(collection)
  else
    raise "API METHOD DOESN'T EXIST"
  end
end

#setup_batchObject



16
17
18
19
20
21
22
23
24
25
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 16

def setup_batch
  batch = .canvas_batches.where(context: ).first
  if batch.present? and RUNNING_STATUSES.include?(batch.status)
    batch
  else
    batch = .canvas_batches.create(context: , status: "Queued")
  end
  batch.update_attributes(options: options)
  batch
end

#should_download?Boolean

Returns:

  • (Boolean)


54
55
56
57
58
59
60
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 54

def should_download?
  return true unless .settings[:canvas_download_interval].present?
  return true unless last_completed_batch = .canvas_batches.where(context: , status: 'Completed').order('updated_at ASC').first
  should_download = last_completed_batch.updated_at < Time.zone.now - .settings[:canvas_download_interval].minutes
  batch.update_attributes(status: 'Canceled') unless should_download
  should_download
end

#standard_attributes(record, attributes) ⇒ Object



119
120
121
122
123
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 119

def standard_attributes(record, attributes)
  new_attributes = attributes.dup
  new_attributes.delete('id')
  new_attributes.delete_if { |key, value| !record.attributes.include?(key) }
end

#start(forced = false) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 31

def start(forced = false)
  unless forced
    return unless batch.status == 'Queued' # don't start if there is already a running job
    return unless should_download?
  end

  begin
    batch.update_attributes(status: "Started", percent_complete: 0)
    index = 1
    SUPPORTED_MODELS.each do |model_key|
      next unless options.include?(model_key)
      process_api_data(model_key.to_sym)
      percent_complete = (index/(options.count.nonzero? || 1).to_f * 100).round(1)
      batch.update_attributes(percent_complete: percent_complete)
      index += 1
    end
    batch.update_attributes(status: "Completed", percent_complete: 100)
  rescue => e
    batch.update_attributes(status: "Error", message: e.message)
  end
end

#sync_courses(collection) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 75

def sync_courses(collection)
  collection.each do |values|
    begin
      values['canvas_course_id'] = values["id"].to_s
      course = .courses.where(canvas_course_id: values['canvas_course_id']).first_or_initialize
      course. = .id
      course.assign_attributes(standard_attributes(course, values))
      course.sis_id = values['sis_course_id'].to_s
      course.save(validate: false)
      course_ids << course.id
    rescue => e
      Rails.logger.error "Error syncing course: #{values} Error: #{e}"
    end
  end
  removed_courses = .courses.where.not(id: course_ids)
  .submissions.where(coalescing_panda_course_id: removed_courses.map(&:id)).destroy_all
  removed_courses.each do |course|
    course.enrollments.destroy_all
  end
removed_courses.destroy_all
end

#sync_users(collection) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'app/models/coalescing_panda/workers/account_miner.rb', line 97

def sync_users(collection)
  collection.each do |values|
    begin
      values['canvas_user_id'] = values["id"].to_s
      user = .users.where(canvas_user_id: values['canvas_user_id']).first_or_initialize
      user. = .id
      user.assign_attributes(standard_attributes(user, values))
      user.sis_id = values['sis_user_id'].to_s
      user.save(validate: false)
      user_ids << user.id
    rescue => e
      Rails.logger.error "Error syncing user: #{values} Error: #{e}"
    end
  end
  removed_users = .users.where.not(id: user_ids)
  .submissions.where(coalescing_panda_user_id: removed_users.map(&:id)).destroy_all
  removed_users.each do |user|
    user.enrollments.destroy_all
  end
  removed_users.destroy_all
end