Class: PlatformSdk::CanvasApiWrapper::Client
- Inherits:
-
Object
- Object
- PlatformSdk::CanvasApiWrapper::Client
- Defined in:
- lib/platform_sdk/canvas_api/client.rb
Overview
DataPipeline::Client
Constant Summary collapse
- PAGE_SIZE =
10- DEFAULT_RETRY_OPTIONS =
Retries are scoped to Canvas's 429 throttle and nothing else.
retry_statusesis implemented by raising the syntheticFaraday::RetriableResponse, so that class has to stay inexceptionsfor a 429 to be retried at all -- an empty list would let it escape to the caller instead. Naming it as the only entry is what drops faraday-retry's defaultErrno::ETIMEDOUT,Timeout::ErrorandFaraday::TimeoutError: a timed-out request may already have been applied by Canvas, and replaying it is not safe for every endpoint here.update_submission_excused_with_commentPUTs asubmission_commentsentry, which Canvas appends rather than replaces, so a replayed timeout would leave the student duplicate comments.methodsrestates faraday-retry's own IDEMPOTENT_METHODS so the exclusion is visible at the call site: POST is left out because a retry could re-create a module item. PUT is safe on the remaining 429 path because Canvas rejects a throttled request before applying it, so the replay is the first time the write lands.The backoff is deliberately short: Canvas refills the rate-limit bucket continuously, so max: 3 with interval: 1 and backoff_factor: 2 spends about 1.0-1.5s, 2.0-2.5s and 4.0-4.5s (the randomness is additive, not a +/- percentage of the interval) before giving up -- that's 3 retries, 4 attempts total. Callers that need a different budget pass
retry_options:to the constructor.retry_statuses: [429]assumes the hosted Canvas instance hasrequest_throttle.send_429_responseenabled; without it Canvas'sRequestThrottlereturns 403 instead, which won't retry and surfaces asLockedModuleItemErroron the write endpoints below.max_intervalbounds both the exponential backoff and aRetry-Afterheader Canvas might one day send -- without it, a single throttled request could block for as long as that header says (faraday-retry defaultsmax_intervaltoFloat::MAX). { max: 3, interval: 1, interval_randomness: 0.5, backoff_factor: 2, max_interval: 10, retry_statuses: [429], exceptions: [Faraday::RetriableResponse], methods: %i[delete get head options put] }.freeze
Instance Attribute Summary collapse
-
#connection ⇒ Object
readonly
Returns the value of attribute connection.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#token ⇒ Object
readonly
Returns the value of attribute token.
Instance Method Summary collapse
- #assignment(course_id:, assignment_id:) ⇒ Object
- #assignments(course_id:, module_id:) ⇒ Object
- #course_modules(course_id:) ⇒ Object
- #course_students(course_id:) ⇒ Object
- #course_test_student(course_id:) ⇒ Object
- #course_users(course_id:) ⇒ Object
- #create_module(course_id:, body:) ⇒ Hash
- #delete_module_item(course_id:, module_id:, module_item_id:) ⇒ Object
-
#initialize(domain:, token:, retry_options: {}) ⇒ Client
constructor
A new instance of Client.
- #module_item(course_id:, module_id:, module_item_id:) ⇒ Object
- #module_items(course_id:, module_id:) ⇒ Object
- #post_complete_quiz_submission(course_id:, quiz_id:, submission_id:, attempt:, validation_token:) ⇒ Hash
- #post_create_quiz_submission(course_id:, quiz_id:, user_id:) ⇒ Object
- #post_discussion_topic_entry(course_id:, topic_id:, user_id:, message:) ⇒ Object
-
#post_mark_module_item_read(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
Nil.
- #post_module_item(course_id:, module_id:, body:) ⇒ Object
-
#put_mark_module_item_done(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
Nil.
- #put_module_prerequesites(course_id:, module_id:, prerequisite_ids:) ⇒ Object
- #put_publish_module_item(course_id:, module_id:, module_item_id:) ⇒ Object
-
#put_recompute_module_prerequisites(course_id:, module_id:, original_name:) ⇒ Object
renames a module to recompute module prerequisites.
- #put_relock_module(course_id:, module_id:) ⇒ Object
- #quiz(course_id:, quiz_id:) ⇒ Object
- #quiz_submissions(course_id:, quiz_id:, user_id:) ⇒ Array
- #retrieve_discussion_topic(course_id:, topic_id:) ⇒ Object
- #submissions(course_id:, assignment_id:) ⇒ Object
- #update_module(course_id:, module_id:, body:) ⇒ Hash
- #update_submission_excused(course_id:, assignment_id:, user_id:) ⇒ Object
- #update_submission_excused_with_comment(course_id:, assignment_id:, user_id:, comment:) ⇒ Object
- #user_course_modules(course_id:, user_id:) ⇒ Object
- #user_module_item(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
- #user_module_item_content_details(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
- #user_module_items(course_id:, module_id:, user_id:) ⇒ Object
Constructor Details
#initialize(domain:, token:, retry_options: {}) ⇒ Client
Returns a new instance of Client.
65 66 67 68 69 70 71 72 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 65 def initialize(domain:, token:, retry_options: {}) @host = "https://#{domain}" @token = token @retry_options = DEFAULT_RETRY_OPTIONS .merge(retry_block: method(:log_rate_limit_retry)) .merge() @connection = build_connection end |
Instance Attribute Details
#connection ⇒ Object (readonly)
Returns the value of attribute connection.
11 12 13 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 11 def connection @connection end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
11 12 13 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 11 def host @host end |
#token ⇒ Object (readonly)
Returns the value of attribute token.
11 12 13 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 11 def token @token end |
Instance Method Details
#assignment(course_id:, assignment_id:) ⇒ Object
139 140 141 142 143 144 145 146 147 148 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 139 def assignment(course_id:, assignment_id:) uri = "api/v1/courses/#{course_id}/assignments/#{assignment_id}" response = @connection.get(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting quiz submissions#{(response.body)}" end end |
#assignments(course_id:, module_id:) ⇒ Object
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 127 def assignments(course_id:, module_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules/#{module_id}/items?per_page=#{PAGE_SIZE}") handle_rate_limiting response if success?(response.status) assignments = paginated_items headers: response.headers, initial_response: response.body assignments.select { |item| item[:type] == 'Assignment' } else raise "Error getting assignments: #{(response.body)}" end end |
#course_modules(course_id:) ⇒ Object
76 77 78 79 80 81 82 83 84 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 76 def course_modules(course_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules") handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting course modules: #{(response.body)}" end end |
#course_students(course_id:) ⇒ Object
235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 235 def course_students(course_id:) uri = "/api/v1/courses/#{course_id}/users?per_page=#{PAGE_SIZE}" params = { 'enrollment_type[]' => 'student' } response = @connection.get(uri, params) handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting course students: #{(response.body)}" end end |
#course_test_student(course_id:) ⇒ Object
248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 248 def course_test_student(course_id:) uri = "/api/v1/courses/#{course_id}/users" params = { 'enrollment_type[]' => 'student_view' } response = @connection.get(uri, params) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting test students: #{(response.body)}" end end |
#course_users(course_id:) ⇒ Object
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 261 def course_users(course_id:) uri = "/api/v1/courses/#{course_id}/users?per_page=#{PAGE_SIZE}" response = @connection.get(uri) handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting course users: #{(response.body)}" end end |
#create_module(course_id:, body:) ⇒ Hash
431 432 433 434 435 436 437 438 439 440 441 442 443 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 431 def create_module(course_id:, body:) uri = "/api/v1/courses/#{course_id}/modules" response = @connection.post(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = body end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error creating module: #{(response.body)}" end end |
#delete_module_item(course_id:, module_id:, module_item_id:) ⇒ Object
508 509 510 511 512 513 514 515 516 517 518 519 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 508 def delete_module_item(course_id:, module_id:, module_item_id:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}" response = @connection.delete(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error destroying module item: #{(response.body)}" end end |
#module_item(course_id:, module_id:, module_item_id:) ⇒ Object
153 154 155 156 157 158 159 160 161 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 153 def module_item(course_id:, module_id:, module_item_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}") handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting module item: #{(response.body)}" end end |
#module_items(course_id:, module_id:) ⇒ Object
99 100 101 102 103 104 105 106 107 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 99 def module_items(course_id:, module_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules/#{module_id}/items?per_page=#{PAGE_SIZE}") handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting module items: #{(response.body)}" end end |
#post_complete_quiz_submission(course_id:, quiz_id:, submission_id:, attempt:, validation_token:) ⇒ Hash
320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 320 def post_complete_quiz_submission(course_id:, quiz_id:, submission_id:, attempt:, validation_token:) uri = "api/v1/courses/#{course_id}/quizzes/#{quiz_id}/submissions/#{submission_id}/complete" response = @connection.post(uri) do |req| req.headers['Content-Type'] = 'application/json' req.body = { attempt:, validation_token: }.to_json end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else handle_post_response_errors(response, 'Error completing quiz submission') end end |
#post_create_quiz_submission(course_id:, quiz_id:, user_id:) ⇒ Object
303 304 305 306 307 308 309 310 311 312 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 303 def post_create_quiz_submission(course_id:, quiz_id:, user_id:) uri = "api/v1/courses/#{course_id}/quizzes/#{quiz_id}/submissions?as_user_id=#{user_id}" response = @connection.post(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else handle_post_response_errors(response, 'Error creating quiz submission') end end |
#post_discussion_topic_entry(course_id:, topic_id:, user_id:, message:) ⇒ Object
366 367 368 369 370 371 372 373 374 375 376 377 378 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 366 def post_discussion_topic_entry(course_id:, topic_id:, user_id:, message:) uri = "api/v1/courses/#{course_id}/discussion_topics/#{topic_id}/entries?as_user_id=#{user_id}" response = @connection.post(uri) do |req| req.headers['Content-Type'] = 'application/json' req.body = { 'message': .to_s }.to_json end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error posting a reply: #{(response.body)}" end end |
#post_mark_module_item_read(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
Returns nil.
339 340 341 342 343 344 345 346 347 348 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 339 def post_mark_module_item_read(course_id:, module_id:, module_item_id:, user_id:) uri = "api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}/mark_read?as_user_id=#{user_id}" response = @connection.post(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else handle_post_response_errors(response, 'Error marking module items read') end end |
#post_module_item(course_id:, module_id:, body:) ⇒ Object
477 478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 477 def post_module_item(course_id:, module_id:, body:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}/items" response = @connection.post(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = body end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error creating module item: #{(response.body)}" end end |
#put_mark_module_item_done(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
Returns nil.
355 356 357 358 359 360 361 362 363 364 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 355 def put_mark_module_item_done(course_id:, module_id:, module_item_id:, user_id:) uri = "api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}/done?as_user_id=#{user_id}" response = @connection.put(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else handle_post_response_errors(response, 'Error marking module item done') end end |
#put_module_prerequesites(course_id:, module_id:, prerequisite_ids:) ⇒ Object
prerequisite_ids should be a valid module_id, sending and empty array removes all prerequisites.
397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 397 def put_module_prerequesites(course_id:, module_id:, prerequisite_ids:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}" response = @connection.put(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = { 'module[prerequisite_module_ids]' => prerequisite_ids } end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error updating module prerequisite: #{(response.body)}" end end |
#put_publish_module_item(course_id:, module_id:, module_item_id:) ⇒ Object
494 495 496 497 498 499 500 501 502 503 504 505 506 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 494 def put_publish_module_item(course_id:, module_id:, module_item_id:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}" response = @connection.put(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = { 'module_item[published]' => true } end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error publishing module item: #{(response.body)}" end end |
#put_recompute_module_prerequisites(course_id:, module_id:, original_name:) ⇒ Object
renames a module to recompute module prerequisites.
412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 412 def put_recompute_module_prerequisites(course_id:, module_id:, original_name:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}" response = @connection.put(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = { 'module[name]' => original_name } end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error updating refreshing module prerequisite: #{(response.body)}" end end |
#put_relock_module(course_id:, module_id:) ⇒ Object
382 383 384 385 386 387 388 389 390 391 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 382 def put_relock_module(course_id:, module_id:) uri = "api/v1/courses/#{course_id}/modules/#{module_id}/relock" response = @connection.put(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise CanvasClientError, "Error re-locking module: #{(response.body)}" end end |
#quiz(course_id:, quiz_id:) ⇒ Object
274 275 276 277 278 279 280 281 282 283 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 274 def quiz(course_id:, quiz_id:) uri = "/api/v1/courses/#{course_id}/quizzes/#{quiz_id}" response = @connection.get(uri) handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting quiz: #{(response.body)}" end end |
#quiz_submissions(course_id:, quiz_id:, user_id:) ⇒ Array
289 290 291 292 293 294 295 296 297 298 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 289 def quiz_submissions(course_id:, quiz_id:, user_id:) uri = "api/v1/courses/#{course_id}/quizzes/#{quiz_id}/submissions?user=#{user_id}&per_page=#{PAGE_SIZE}" response = @connection.get(uri) handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting quiz submissions#{(response.body)}" end end |
#retrieve_discussion_topic(course_id:, topic_id:) ⇒ Object
521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 521 def retrieve_discussion_topic(course_id:, topic_id:) uri = "/api/v1/courses/#{course_id}/discussion_topics/#{topic_id}" response = @connection.get(uri) do |req| req.headers['Content-Type'] = 'application/json' end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error retrieving discussion topic: #{(response.body)}" end end |
#submissions(course_id:, assignment_id:) ⇒ Object
185 186 187 188 189 190 191 192 193 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 185 def submissions(course_id:, assignment_id:) response = @connection.get("/api/v1/courses/#{course_id}/assignments/#{assignment_id}/submissions/") handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting submissions: #{(response.body)}" end end |
#update_module(course_id:, module_id:, body:) ⇒ Hash
454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 454 def update_module(course_id:, module_id:, body:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}" response = @connection.put(uri) do |req| req.headers['Content-Type'] = 'application/x-www-form-urlencoded' req.body = body end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error updating module: #{(response.body)}" end end |
#update_submission_excused(course_id:, assignment_id:, user_id:) ⇒ Object
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 195 def update_submission_excused(course_id:, assignment_id:, user_id:) uri = "/api/v1/courses/#{course_id}/assignments/#{assignment_id}/submissions/#{user_id}" response = @connection.put(uri) do |req| req.headers["Content-Type"] = "application/json" req.body = { submission: { excuse: true } }.to_json end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error update submissions to excused: #{(response.body)}" end end |
#update_submission_excused_with_comment(course_id:, assignment_id:, user_id:, comment:) ⇒ Object
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 213 def update_submission_excused_with_comment(course_id:, assignment_id:, user_id:, comment:) uri = "/api/v1/courses/#{course_id}/assignments/#{assignment_id}/submissions/#{user_id}" response = @connection.put(uri) do |req| req.headers['Content-Type'] = 'application/json' req.body = { 'comment': { 'text_comment': comment }, 'submission': { 'excuse': true } }.to_json end handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error update submissions to excused: #{(response.body)}" end end |
#user_course_modules(course_id:, user_id:) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 86 def user_course_modules(course_id:, user_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules?as_user_id=#{user_id}") handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting course modules: #{(response.body)}" end end |
#user_module_item(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
163 164 165 166 167 168 169 170 171 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 163 def user_module_item(course_id:, module_id:, module_item_id:, user_id:) response = @connection.get("/api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}?as_user_id=#{user_id}") handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting module item: #{(response.body)}" end end |
#user_module_item_content_details(course_id:, module_id:, module_item_id:, user_id:) ⇒ Object
173 174 175 176 177 178 179 180 181 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 173 def user_module_item_content_details(course_id:, module_id:, module_item_id:, user_id:) response = @connection.get("api/v1/courses/#{course_id}/modules/#{module_id}/items/#{module_item_id}?include[]=content_details&student_id=#{user_id}") handle_rate_limiting response if success?(response.status) MultiJson.load response.body, symbolize_keys: true else raise "Error getting module item: #{(response.body)}" end end |
#user_module_items(course_id:, module_id:, user_id:) ⇒ Object
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/platform_sdk/canvas_api/client.rb', line 113 def user_module_items(course_id:, module_id:, user_id:) uri = "/api/v1/courses/#{course_id}/modules/#{module_id}/items?as_user_id=#{user_id}&per_page=#{PAGE_SIZE}" response = @connection.get(uri) handle_rate_limiting response if success?(response.status) paginated_items headers: response.headers, initial_response: response.body else raise "Error getting module items: #{(response.body)}" end end |