Class: CourseSyncBatch
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- CourseSyncBatch
- Defined in:
- app/models/course_sync_batch.rb
Overview
Tracks a bulk enrollments content sync operation.
Lifecycle:
pending -> processing -> completed
-> failed
On first GET, the controller shows a preview and creates a batch record
with status: pending to collect the confirmation token. The view renders
two-stage confirmation if total > BULK_SYNC_THRESHOLD.
POST with matching batch_id and confirmation_state progresses the batch
to processing, applies assignments, and marks it completed/failed.
== Schema Information
Table name: course_sync_batches
Database name: primary
id :bigint not null, primary key
course_id :bigint not null
status :string default("pending"), not null
total_topics_to_assign :integer not null
affected_enrollments :integer not null
assigned_count :integer default(0), not null
failed_count :integer default(0), not null
affected_records :jsonb
metadata :jsonb
created_at :datetime not null
updated_at :datetime not null
processed_at :datetime
completed_at :datetime
Indexes
index_course_sync_batches_on_course_id (course_id)
index_course_sync_batches_on_status (status)
Foreign Keys
fk_rails_... (course_id => courses.id)
Constant Summary collapse
- STATUSES =
Statuses.
%w[pending processing completed failed].freeze
- BULK_SYNC_THRESHOLD =
Require second confirmation for >100 assignments
100
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary collapse
-
#affected_enrollments ⇒ Object
readonly
Validates total topics to assign, affected enrollments.
-
#course_id ⇒ Object
readonly
Validates course id.
-
#status ⇒ Object
readonly
Validates status.
-
#total_topics_to_assign ⇒ Object
readonly
Validates total topics to assign, affected enrollments.
Belongs to collapse
-
#course ⇒ Course
The course this record belongs to.
Class Method Summary collapse
-
.active ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are active.
-
.completed ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are completed.
-
.failed ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are failed.
-
.pending ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are pending.
-
.processing ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are processing.
Instance Method Summary collapse
-
#completed? ⇒ Boolean
Whether the record completed.
-
#failed? ⇒ Boolean
Whether the record failed.
-
#large_batch? ⇒ Boolean
Whether the record large batch.
-
#mark_completed!(assigned: 0, failed: 0) ⇒ Object
Mark completed, raising on failure.
-
#mark_failed!(error_message) ⇒ Object
Mark failed, raising on failure.
-
#mark_processing! ⇒ Object
Mark processing, raising on failure.
-
#pending? ⇒ Boolean
Whether the record pending.
-
#processing? ⇒ Boolean
Whether the record processing.
-
#store_affected_records!(additions_map) ⇒ Object
Stores the affected records (enrollment_id -> [topic_ids]) for potential rollback operations.
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Instance Attribute Details
#affected_enrollments ⇒ Object (readonly)
Validates total topics to assign, affected enrollments.
Validations:
- Presence
- Numericality ({ only_integer: true, greater_than_or_equal_to: 0 })
57 |
# File 'app/models/course_sync_batch.rb', line 57 validates :total_topics_to_assign, :affected_enrollments, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } |
#course_id ⇒ Object (readonly)
Validates course id.
Validations:
53 |
# File 'app/models/course_sync_batch.rb', line 53 validates :course_id, presence: true |
#status ⇒ Object (readonly)
Validates status.
Validations:
55 |
# File 'app/models/course_sync_batch.rb', line 55 validates :status, inclusion: { in: STATUSES }, presence: true |
#total_topics_to_assign ⇒ Object (readonly)
Validates total topics to assign, affected enrollments.
Validations:
- Presence
- Numericality ({ only_integer: true, greater_than_or_equal_to: 0 })
57 |
# File 'app/models/course_sync_batch.rb', line 57 validates :total_topics_to_assign, :affected_enrollments, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } |
Class Method Details
.active ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are active. Active Record Scope
63 |
# File 'app/models/course_sync_batch.rb', line 63 scope :active, -> { where(status: %w[pending processing]) } |
.completed ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are completed. Active Record Scope
61 |
# File 'app/models/course_sync_batch.rb', line 61 scope :completed, -> { where(status: 'completed') } |
.failed ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are failed. Active Record Scope
62 |
# File 'app/models/course_sync_batch.rb', line 62 scope :failed, -> { where(status: 'failed') } |
.pending ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are pending. Active Record Scope
59 |
# File 'app/models/course_sync_batch.rb', line 59 scope :pending, -> { where(status: 'pending') } |
.processing ⇒ ActiveRecord::Relation<CourseSyncBatch>
A relation of CourseSyncBatches that are processing. Active Record Scope
60 |
# File 'app/models/course_sync_batch.rb', line 60 scope :processing, -> { where(status: 'processing') } |
Instance Method Details
#completed? ⇒ Boolean
Returns whether the record completed.
70 71 |
# File 'app/models/course_sync_batch.rb', line 70 def completed? = status == 'completed' # @return [Boolean] whether the record failed |
#course ⇒ Course
Returns the course this record belongs to.
50 |
# File 'app/models/course_sync_batch.rb', line 50 belongs_to :course |
#failed? ⇒ Boolean
Returns whether the record failed.
72 |
# File 'app/models/course_sync_batch.rb', line 72 def failed? = status == 'failed' |
#large_batch? ⇒ Boolean
Returns whether the record large batch.
75 76 77 |
# File 'app/models/course_sync_batch.rb', line 75 def large_batch? total_topics_to_assign > BULK_SYNC_THRESHOLD end |
#mark_completed!(assigned: 0, failed: 0) ⇒ Object
Mark completed, raising on failure.
87 88 89 90 91 92 93 94 |
# File 'app/models/course_sync_batch.rb', line 87 def mark_completed!(assigned: 0, failed: 0) update!( status: 'completed', assigned_count: assigned, failed_count: failed, completed_at: Time.current ) end |
#mark_failed!(error_message) ⇒ Object
Mark failed, raising on failure.
98 99 100 101 102 103 104 |
# File 'app/models/course_sync_batch.rb', line 98 def mark_failed!() update!( status: 'failed', completed_at: Time.current, metadata: .merge('error' => ) ) end |
#mark_processing! ⇒ Object
Mark processing, raising on failure.
80 81 82 |
# File 'app/models/course_sync_batch.rb', line 80 def mark_processing! update!(status: 'processing', processed_at: Time.current) end |
#pending? ⇒ Boolean
Returns whether the record pending.
66 67 |
# File 'app/models/course_sync_batch.rb', line 66 def pending? = status == 'pending' # @return [Boolean] whether the record processing |
#processing? ⇒ Boolean
Returns whether the record processing.
68 69 |
# File 'app/models/course_sync_batch.rb', line 68 def processing? = status == 'processing' # @return [Boolean] whether the record completed |
#store_affected_records!(additions_map) ⇒ Object
Stores the affected records (enrollment_id -> [topic_ids]) for potential
rollback operations. Called before applying changes.
109 110 111 112 113 114 115 116 117 |
# File 'app/models/course_sync_batch.rb', line 109 def store_affected_records!(additions_map) # additions_map: { enrollment => [topics] } # Transform to: { enrollment_id => [topic_ids] } for JSON storage records = {} additions_map.each do |enrollment, topics| records[enrollment.id.to_s] = topics.map(&:id) end update!(affected_records: records) end |