canvas-lms/lib/messageable_user.rb

228 lines
7.6 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
#
# Copyright (C) 2013 - present Instructure, Inc.
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class MessageableUser < User
COLUMNS = ['id', 'updated_at', 'pronouns', 'short_name', 'name', 'avatar_image_url', 'avatar_image_source'].map { |col| "users.#{col}" }
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
SELECT = COLUMNS.join(", ")
AVAILABLE_CONDITIONS = "users.workflow_state IN ('registered', 'pre_registered')"
def self.build_select(options = {})
options = {
:common_course_column => nil,
:common_group_column => nil,
:common_role_column => nil
}.merge(options)
bookmark_sql = User.sortable_name_order_by_clause
common_course_sql =
if options[:common_role_column]
raise ArgumentError unless options[:common_course_column]
connection.func(:group_concat,
:"#{options[:common_course_column]}::text || ':' || #{options[:common_role_column]}::text")
else
'NULL::text'
end
common_group_sql =
if options[:common_group_column].is_a?(String)
connection.func(:group_concat, options[:common_group_column].to_sym)
elsif options[:common_group_column]
options[:common_group_column].to_s
else
'NULL::text'
end
"#{SELECT}, #{bookmark_sql} AS bookmark, #{common_course_sql} AS common_courses, #{common_group_sql} AS common_groups"
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end
def self.prepped(options = {})
options = {
:strict_checks => true,
:include_deleted => false
}.merge(options)
# if either of our common course/group id columns are column names (vs.
# integers), they need to go in the group by. we turn the first element
# into an array and add them to that, so that both postgresql/mysql are
# happy (see the documentation on group_concat if you're curious about
# the gory details)
columns = COLUMNS.dup
if options[:common_course_column].is_a?(String) || options[:common_group_column].is_a?(String)
head = [columns.shift]
head << options[:common_course_column] if options[:common_course_column].is_a?(String)
head << options[:common_group_column] if options[:common_group_column].is_a?(String)
columns.unshift(head)
end
scope = self
.select(MessageableUser.build_select(options))
.group(MessageableUser.connection.group_by(*columns))
.order(User.sortable_name_order_by_clause).order(Arel.sql("users.id"))
if options[:strict_checks]
scope.where(AVAILABLE_CONDITIONS)
elsif !options[:include_deleted]
scope.where("users.workflow_state <> 'deleted'")
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
else
scope
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end
end
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
def self.unfiltered(options = {})
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
prepped(options.merge(:strict_checks => false))
end
def self.available(options = {})
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
prepped(options.merge(:strict_checks => true))
end
def self.context_recipients(recipients)
recipients.grep(Calculator::CONTEXT_RECIPIENT)
end
def self.individual_recipients(recipients)
recipients.select { |id|
!id.is_a?(String) ||
id =~ Calculator::INDIVIDUAL_RECIPIENT
}.map(&:to_i)
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end
def common_groups
common_contexts_on_current_shard(global_common_groups)
end
def common_courses
common_contexts_on_current_shard(global_common_courses)
end
# only MessageableUser::Calculator should access these directly. if you're
# outside the calculator, you almost certainly want the versions above that
# transpose to the current shard. additionally, any time you access these,
# make sure you're still on the same shard where common_course_id and/or
# common_group_id were queried
attr_accessor :global_common_courses, :global_common_groups
# this will be executed on the shard where the find was called (I think?).
# as such, we can correctly interpret local ids in the common_courses and
# common_groups
def populate_common_contexts
@global_common_courses = {}
read_attribute(:common_courses)&.to_s&.split(',')&.each do |common_course|
course_id, role = common_course.split(':')
course_id = course_id.to_i
# a course id of 0 indicates admin visibility without an actual shared
# course; don't "globalize" it
course_id = Shard.global_id_for(course_id) unless course_id.zero?
@global_common_courses[course_id] ||= []
@global_common_courses[course_id] << role
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end
@global_common_groups = {}
read_attribute(:common_groups)&.to_s&.split(',')&.each do |group_id|
group_id = Shard.global_id_for(group_id.to_i)
@global_common_groups[group_id] ||= []
@global_common_groups[group_id] << 'Member'
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end
end
after_find :populate_common_contexts
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
proper handling of cross-shard admin visibility when querying common contexts between user A and messageable user B, "0" is used as a special course id to indicate user B has at least one enrollment in an account A admins -- no actual course involved. to manage common contexts cross shard, they are stored with global ids. this was "globalizing" 0 to no longer be zero, causing problems. fix that edge case. additionally, if there were multiple shards with accounts in which B has and enrollment and A is an admin, it would overwrite (given corrected handling of the 0) with the last queried shard's values, rather than combining them. fixes CNVS-6303 test-plan: - have at least two shards - create user A on shard 1, user B on shard 2 - enroll user B as a teacher in a course under account X on shard 2 - add user A as an admin of account X - on shard 1, reload user B via user A's messageable users, e.g.: userB = userA.load_messageable_user(userB) - userB's common courses should include a key of 0 with 'TeacherEnrollment' as the only value - repeat on shard 2 - enroll user B as a student in a course under account Y on shard 1 - add user A as an admin of account Y - on shard 1, reload user B via user A's messageable users (again) - userB's common courses should include a key of 0 with both 'TeacherEnrollment' and 'StudentEnrollment' as values - repeat on shard 2 Change-Id: I014d1f0d7793889de512a4a0262e32027ee5702e Reviewed-on: https://gerrit.instructure.com/21542 Reviewed-by: Cody Cutrer <cody@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2013-06-18 04:13:43 +08:00
def include_common_contexts_from(other)
combine_common_contexts(self.global_common_courses, other.global_common_courses)
combine_common_contexts(self.global_common_groups, other.global_common_groups)
end
def serializable_hash(options = {})
options[:except] ||= []
options[:except] << :bookmark
super(options)
end
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
private
def common_contexts_on_current_shard(common_contexts)
local_common_contexts = {}
target_shard = Shard.current
return local_common_contexts if common_contexts.empty?
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
Shard.partition_by_shard(common_contexts.keys) do |sharded_ids|
sharded_ids.each do |id|
proper handling of cross-shard admin visibility when querying common contexts between user A and messageable user B, "0" is used as a special course id to indicate user B has at least one enrollment in an account A admins -- no actual course involved. to manage common contexts cross shard, they are stored with global ids. this was "globalizing" 0 to no longer be zero, causing problems. fix that edge case. additionally, if there were multiple shards with accounts in which B has and enrollment and A is an admin, it would overwrite (given corrected handling of the 0) with the last queried shard's values, rather than combining them. fixes CNVS-6303 test-plan: - have at least two shards - create user A on shard 1, user B on shard 2 - enroll user B as a teacher in a course under account X on shard 2 - add user A as an admin of account X - on shard 1, reload user B via user A's messageable users, e.g.: userB = userA.load_messageable_user(userB) - userB's common courses should include a key of 0 with 'TeacherEnrollment' as the only value - repeat on shard 2 - enroll user B as a student in a course under account Y on shard 1 - add user A as an admin of account Y - on shard 1, reload user B via user A's messageable users (again) - userB's common courses should include a key of 0 with both 'TeacherEnrollment' and 'StudentEnrollment' as values - repeat on shard 2 Change-Id: I014d1f0d7793889de512a4a0262e32027ee5702e Reviewed-on: https://gerrit.instructure.com/21542 Reviewed-by: Cody Cutrer <cody@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2013-06-18 04:13:43 +08:00
# a context id of 0 indicates admin visibility without an actual shared
# context; don't "globalize" it
global_id = id == 0 ? id : Shard.global_id_for(id)
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
id = global_id unless Shard.current == target_shard
local_common_contexts[id] = common_contexts[global_id]
end
end
local_common_contexts
end
proper handling of cross-shard admin visibility when querying common contexts between user A and messageable user B, "0" is used as a special course id to indicate user B has at least one enrollment in an account A admins -- no actual course involved. to manage common contexts cross shard, they are stored with global ids. this was "globalizing" 0 to no longer be zero, causing problems. fix that edge case. additionally, if there were multiple shards with accounts in which B has and enrollment and A is an admin, it would overwrite (given corrected handling of the 0) with the last queried shard's values, rather than combining them. fixes CNVS-6303 test-plan: - have at least two shards - create user A on shard 1, user B on shard 2 - enroll user B as a teacher in a course under account X on shard 2 - add user A as an admin of account X - on shard 1, reload user B via user A's messageable users, e.g.: userB = userA.load_messageable_user(userB) - userB's common courses should include a key of 0 with 'TeacherEnrollment' as the only value - repeat on shard 2 - enroll user B as a student in a course under account Y on shard 1 - add user A as an admin of account Y - on shard 1, reload user B via user A's messageable users (again) - userB's common courses should include a key of 0 with both 'TeacherEnrollment' and 'StudentEnrollment' as values - repeat on shard 2 Change-Id: I014d1f0d7793889de512a4a0262e32027ee5702e Reviewed-on: https://gerrit.instructure.com/21542 Reviewed-by: Cody Cutrer <cody@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2013-06-18 04:13:43 +08:00
def combine_common_contexts(left, right)
right.each { |key, values| (left[key] ||= []).concat(values) }
proper handling of cross-shard admin visibility when querying common contexts between user A and messageable user B, "0" is used as a special course id to indicate user B has at least one enrollment in an account A admins -- no actual course involved. to manage common contexts cross shard, they are stored with global ids. this was "globalizing" 0 to no longer be zero, causing problems. fix that edge case. additionally, if there were multiple shards with accounts in which B has and enrollment and A is an admin, it would overwrite (given corrected handling of the 0) with the last queried shard's values, rather than combining them. fixes CNVS-6303 test-plan: - have at least two shards - create user A on shard 1, user B on shard 2 - enroll user B as a teacher in a course under account X on shard 2 - add user A as an admin of account X - on shard 1, reload user B via user A's messageable users, e.g.: userB = userA.load_messageable_user(userB) - userB's common courses should include a key of 0 with 'TeacherEnrollment' as the only value - repeat on shard 2 - enroll user B as a student in a course under account Y on shard 1 - add user A as an admin of account Y - on shard 1, reload user B via user A's messageable users (again) - userB's common courses should include a key of 0 with both 'TeacherEnrollment' and 'StudentEnrollment' as values - repeat on shard 2 Change-Id: I014d1f0d7793889de512a4a0262e32027ee5702e Reviewed-on: https://gerrit.instructure.com/21542 Reviewed-by: Cody Cutrer <cody@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2013-06-18 04:13:43 +08:00
end
# both bookmark_for and restrict_scope should always be executed on the
# same shard (not guaranteed, but we don't have to guarantee correctness if
# they aren't). so local ids here and local ids there have identical
# interpretation: local to Shard.current.
class MessageableUser::Bookmarker
def self.bookmark_for(user)
[user.bookmark, user.id]
end
def self.validate(bookmark)
bookmark.is_a?(Array) &&
bookmark.size == 2 &&
bookmark[0].is_a?(String) &&
bookmark[1].is_a?(Integer)
end
# ordering is already guaranteed
def self.restrict_scope(scope, pager)
if pager.current_bookmark
name, id = pager.current_bookmark
if MessageableUser.connection.adapter_name == 'PostgreSQL'
name = MessageableUser.connection.escape_bytea(name)
end
scope_shard = scope.shard_value
id = Shard.relative_id_for(id, Shard.current, scope_shard) if scope_shard
condition = [
<<~SQL,
#{User.sortable_name_order_by_clause} > ? OR
#{User.sortable_name_order_by_clause} = ? AND users.id > ?
SQL
name, name, id
]
if pager.include_bookmark
condition[0] << "OR #{User.sortable_name_order_by_clause} = ? AND users.id = ?"
condition.concat([name, id])
end
scope.where(condition)
else
scope
end
end
end
MessageableUser refactor with sharding Separates, streamlines, and makes shard-aware all use cases of User#messageable_users *other* than searching (call site in SearchController#matching_participants). Produces three new methods that take the bulk of that responsibility: * User#load_messageable_users -- given a set of users, filter out the ones that aren't messageable, and load any common contexts for those that are. * User#load_messageable_user -- as User#load_messageable_users, but for just one user. * User#messageable_users_in_context -- given a context (a course, section, or group), return the list of messageable users in that context. refs CNVS-2519 remaining on CNVS-2519 is to tackle the search application of User#messageable_user. mostly there, but reconciling pagination with ranking by number of shared contexts is proving problematic, so I'm going to separate that into another commit. meanwhile, I've renamed User#messageable_users to User#deprecated_search_messageable_users to discourage any accidental new uses and left it otherwise untouched. searching for users on the same shard should be unaffected. You can still locate messageable users on other shards to insert into conversations by browsing the shared contexts. test-plan: * create user A in shard X * create user B in shard Y * for situations where A could message B if on the same shard: - setup the situation where the common tie is on shard X (e.g. course on shard X and both A and B in it). run exercises below - setup the situation where the common tie is on shard Y. run exercises. - if appropriate, setup the situation where the common tie is on shard Z. run exercises. * for each setup described above, login as A: - A should see the "message this user" button on B's profile - if the common tie is a course, section, or group, A should see B under that context when the context is selected in the recipient browser - if a conversation exists involving both A and B, when A loads the conversation they should see B tagged with the common contexts * regression test searching for messageable users from the same shard Change-Id: Ibba5551f8afc2435fd14a2e827a400bf95eae76a Reviewed-on: https://gerrit.instructure.com/17569 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Clare Hetherington <clare@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2013-02-05 06:18:20 +08:00
end