-
Notifications
You must be signed in to change notification settings - Fork 566
Import resiliency (3/3) #1385
Import resiliency (3/3) #1385
Changes from all commits
9c9914b
f8401ee
f59a44d
6ef3480
83d09b1
b416808
9f8a77c
10f21be
2c602f1
2512e81
baeca08
90bf12d
e6fa568
54d035c
5178c4f
2de8ff1
e2e5774
33ae03e
7d0a98e
2514169
addbf3d
109a9e0
3fb3909
3ab5158
3cde0ff
bbb7eda
15a110d
6700963
eb1d7c9
0ebd551
945f5de
7a06406
ca3081f
3c6ecf4
cc81287
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,32 +19,25 @@ class CreateGitHubRepositoryJob < ApplicationJob | |
def perform(assignment, user) | ||
start = Time.zone.now | ||
|
||
assignment.invitation&.creating_repo! | ||
|
||
creator = Creator.new(assignment: assignment, user: user) | ||
|
||
creator.verify_organization_has_private_repos_available! | ||
|
||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: CREATE_REPO | ||
text: CREATE_REPO, | ||
status: assignment.invitation&.status | ||
) | ||
|
||
assignment_repo = assignment.assignment_repos.build( | ||
github_repo_id: creator.create_github_repository!, | ||
user: user | ||
) | ||
|
||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: ADDING_COLLABORATOR | ||
) | ||
|
||
creator.add_user_to_repository!(assignment_repo.github_repo_id) | ||
|
||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: IMPORT_STARTER_CODE | ||
) | ||
|
||
creator.push_starter_code!(assignment_repo.github_repo_id) if assignment.starter_code? | ||
|
||
begin | ||
|
@@ -54,15 +47,34 @@ def perform(assignment, user) | |
end | ||
|
||
duration_in_millseconds = (Time.zone.now - start) * 1_000 | ||
GitHubClassroom.statsd.timing("exercise_repo.create.time", duration_in_millseconds) | ||
GitHubClassroom.statsd.timing("v2_exercise_repo.create.time", duration_in_millseconds) | ||
GitHubClassroom.statsd.increment("v2_exercise_repo.create.success") | ||
|
||
PorterStatusJob.perform_later(assignment_repo, user) | ||
if assignment.starter_code? | ||
assignment.invitation&.importing_starter_code! | ||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: IMPORT_STARTER_CODE, | ||
status: assignment.invitation&.status | ||
) | ||
PorterStatusJob.perform_later(assignment_repo, user) | ||
else | ||
assignment.invitation&.completed! | ||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: Creator::REPOSITORY_CREATION_COMPLETE, | ||
status: assignment.invitation&.status | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be recording stats about successful repo creation on this vs the old way? if so using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely, we should be recording metrics wherever we think might help us be confident the new porter logic is better and more successful than the old one. I said this in an earlier comment, but we'll also want to have granular metrics so we can distinguish imports made using old logic and new logic. |
||
end | ||
rescue Creator::Result::Error => err | ||
creator.delete_github_repository(assignment_repo.try(:github_repo_id)) | ||
assignment.invitation&.errored! | ||
ActionCable.server.broadcast( | ||
RepositoryCreationStatusChannel.channel(user_id: user.id), | ||
text: err | ||
text: err, | ||
status: assignment.invitation&.status | ||
) | ||
GitHubClassroom.statsd.increment("v2_exercise_repo.create.fail") | ||
raise err | ||
end | ||
# rubocop:enable MethodLength | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ | |
class AssignmentInvitation < ApplicationRecord | ||
include ShortKey | ||
|
||
enum status: %i[unaccepted accepted creating_repo importing_starter_code completed errored] | ||
|
||
default_scope { where(deleted_at: nil) } | ||
|
||
update_index("stafftools#assignment_invitation") { self } | ||
|
@@ -20,12 +22,18 @@ class AssignmentInvitation < ApplicationRecord | |
|
||
after_initialize :assign_key | ||
|
||
after_initialize :set_defaults, unless: :persisted? | ||
|
||
delegate :title, to: :assignment | ||
|
||
# Public: Redeem an AssignmentInvtiation for a User invitee. | ||
# | ||
# Returns a AssignmentRepo::Creator::Result. | ||
def redeem_for(invitee) | ||
# | ||
# rubocop:disable MethodLength | ||
# rubocop:disable AbcSize | ||
def redeem_for(invitee, import_resiliency: false) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of using a kwarg here, can we just directly check the feature flag? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't use the feature dependency here because we are outside of a controller (feature 🚩s are defined on |
||
accepted! | ||
if (repo_access = RepoAccess.find_by(user: invitee, organization: organization)) | ||
assignment_repo = AssignmentRepo.find_by(assignment: assignment, repo_access: repo_access) | ||
return AssignmentRepo::Creator::Result.success(assignment_repo) if assignment_repo.present? | ||
|
@@ -36,8 +44,14 @@ def redeem_for(invitee) | |
|
||
return AssignmentRepo::Creator::Result.failed("Invitations for this assignment have been disabled.") unless enabled? | ||
|
||
AssignmentRepo::Creator.perform(assignment: assignment, user: invitee) | ||
if import_resiliency | ||
AssignmentRepo::Creator::Result.pending | ||
else | ||
AssignmentRepo::Creator.perform(assignment: assignment, user: invitee) | ||
end | ||
end | ||
# rubocop:enable MethodLength | ||
# rubocop:enable AbcSize | ||
|
||
def to_param | ||
key | ||
|
@@ -52,4 +66,8 @@ def enabled? | |
def assign_key | ||
self.key ||= SecureRandom.hex(16) | ||
end | ||
|
||
def set_defaults | ||
self.status ||= :unaccepted | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this method defined? I wasn't able to find it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it's an enum helper, nevermind!