Community

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jacob_anavisca
New Member

Why does the grade_change live event prefix all the ids in the body?

Jump to solution

Currently, we are trying to use the live event webhooks to send notifications to users of our app. When an event occurs Canvas hits our API, the API parses out the needed info (like user_id) and makes a request to an internal API that sends a push notification to our app users.

We are testing this out first with the Grades events since the user_id is included in the body, making it easier to send to the user it pertains to.

While testing I noticed that a course_grade_change event will have the user_id set as expected like so:

{
  user_id: '90',
  course_id: '70',
  workflow_state: 'active',
  created_at: '2020-09-22T20:12:57Z',
  updated_at: '2021-04-14T15:39:44Z',
  current_score: 96.67,
  old_current_score: 93.33,
  final_score: 31.52,
  old_final_score: 30.43,
  unposted_current_score: 96.67,
  old_unposted_current_score: 93.33,
  unposted_final_score: 31.52,
  old_unposted_final_score: 30.43
}

but the grade_change event seems to prefix all ids, including the user_id, with a random number like so:

{
  submission_id: '111910000000000846',
  assignment_id: '111910000000000083',
  assignment_name: '.NET',
  grade: '143',
  old_grade: '145',
  score: { numberStr: '143.0' },
  old_score: { numberStr: '145.0' },
  points_possible: { numberStr: '150.0' },
  old_points_possible: { numberStr: '150.0' },
  grader_id: '111910000000000066',
  student_id: '111910000000000090',
  user_id: '111910000000000090',
  grading_complete: true,
  muted: false
}

So I guess this brings about two questions. Is this expected? If so how should I go about determining what the prefix is in order to get all the correct ids? I could assume that I just need to parse out the numbers in the end after all the zeros but that seems fragile.

Labels (3)
0 Kudos
1 Solution

Accepted Solutions
ColinMurtaugh
Community Member

Hi Jacob,

I can't speak to whether or not this is expected in these particular live events, but the long numbers are Canvas' globally-unique IDs. Many objects in Canvas have a local (to a particular Canvas instance) ID and a globally-unique ID. The Canvas IDs are relatively short, like your user_id of 90 below.  The globally-unique IDs are long (like 111910000000000090), and incorporate the unique "shard ID" of the specific Canvas instance that they belong to.  

From your example events, I can tell that the shard ID for your Canvas instance is 11191. This value is available as a custom LTI launch parameter that Canvas can send to your tool -- search for "Canvas.shard.id" on this page: https://canvas.instructure.com/doc/api/file.tools_variable_substitutions.html for more info.  

The formula for converting between local Canvas IDs and globally-unique IDs is:

(shard_id * 10000000000000) + local_id = global_id

or 

global_id - (shard_id * 10000000000000) = local_id

Hope this is helpful!

--Colin

View solution in original post

4 Replies
ColinMurtaugh
Community Member

Hi Jacob,

I can't speak to whether or not this is expected in these particular live events, but the long numbers are Canvas' globally-unique IDs. Many objects in Canvas have a local (to a particular Canvas instance) ID and a globally-unique ID. The Canvas IDs are relatively short, like your user_id of 90 below.  The globally-unique IDs are long (like 111910000000000090), and incorporate the unique "shard ID" of the specific Canvas instance that they belong to.  

From your example events, I can tell that the shard ID for your Canvas instance is 11191. This value is available as a custom LTI launch parameter that Canvas can send to your tool -- search for "Canvas.shard.id" on this page: https://canvas.instructure.com/doc/api/file.tools_variable_substitutions.html for more info.  

The formula for converting between local Canvas IDs and globally-unique IDs is:

(shard_id * 10000000000000) + local_id = global_id

or 

global_id - (shard_id * 10000000000000) = local_id

Hope this is helpful!

--Colin

Hey Colin,

That's very helpful. I completely skipped over the Live Events Metadata section where that info is explained. I was able to parse out the local_id based on that.

Thank you!

Jacob

Hey Colin,

Since there's always going to be the same amount of zeros I could regex replace /\d+00000000000(\d+)/ with $1. Do you think I need to get the shardid in order to get the localid or is it fine to use a regex to determine the localid? Mostly asking because we aren't using an LTI and not sure if there's some way to determine the shardid through an event handler.

Best,

Jacob

That's a good question; my gut is that a regex would probably work fine, but out of curiosity I looked to see how Canvas computes these IDs itself, and I found the details in Instructure's Switchman library:

https://github.com/instructure/switchman/blob/master/app/models/switchman/shard.rb

I don't really read Ruby, but I worked out that it's essentially using this logic: 

To get the local ID from a global ID:

local_id = global_id % 10000000000000

To get the shard ID from a global ID:

shard_id = int( global_id / 10000000000000 )

That's pretty straightforward, and should be safe since that's how Canvas does it! 🙂 

--Colin