From 7fb32af78aec93ab97a11babc395b8d37612332f Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Thu, 5 Dec 2024 15:22:34 +0000 Subject: [PATCH] Remove `MemberJoined` and `MemberLeft` community events (#6989) --- backend/canisters/community/CHANGELOG.md | 1 + .../community/impl/src/model/events.rs | 124 +++++++++++++++++- .../impl/src/updates/c2c_join_community.rs | 12 +- .../impl/src/updates/c2c_leave_community.rs | 20 +-- backend/libraries/types/src/event_wrapper.rs | 10 +- 5 files changed, 129 insertions(+), 38 deletions(-) diff --git a/backend/canisters/community/CHANGELOG.md b/backend/canisters/community/CHANGELOG.md index d8377b3abd..99e41dbe71 100644 --- a/backend/canisters/community/CHANGELOG.md +++ b/backend/canisters/community/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Remove community members from being stored on the heap ([#6984](https://github.com/open-chat-labs/open-chat/pull/6984)) - Avoid iterating over community events ([#6986](https://github.com/open-chat-labs/open-chat/pull/6986)) - Make `summary` match `c2c_summary` so that `c2c_summary` can be removed ([#6988](https://github.com/open-chat-labs/open-chat/pull/6988)) +- Remove `MemberJoined` and `MemberLeft` community events ([#6989](https://github.com/open-chat-labs/open-chat/pull/6989)) ## [[2.0.1498](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1498-community)] - 2024-12-04 diff --git a/backend/canisters/community/impl/src/model/events.rs b/backend/canisters/community/impl/src/model/events.rs index c4616f6319..d72856aaf7 100644 --- a/backend/canisters/community/impl/src/model/events.rs +++ b/backend/canisters/community/impl/src/model/events.rs @@ -4,20 +4,26 @@ use std::collections::BTreeMap; use types::{ AvatarChanged, BannerChanged, ChannelDeleted, ChannelId, ChatId, CommunityMemberLeftInternal, CommunityMembersRemoved, CommunityPermissionsChanged, CommunityRoleChanged, CommunityUsersBlocked, CommunityVisibilityChanged, - DefaultChannelsChanged, EventIndex, EventWrapper, GroupCreated, GroupDescriptionChanged, GroupFrozen, + DefaultChannelsChanged, EventIndex, EventWrapper, EventWrapperInternal, GroupCreated, GroupDescriptionChanged, GroupFrozen, GroupInviteCodeChanged, GroupNameChanged, GroupRulesChanged, GroupUnfrozen, MemberJoinedInternal, PrimaryLanguageChanged, TimestampMillis, UserId, UsersInvited, UsersUnblocked, }; #[derive(Serialize, Deserialize)] +#[serde(from = "CommunityEventsPrevious")] pub struct CommunityEvents { - events_map: BTreeMap>, + events_map: BTreeMap>, latest_event_index: EventIndex, latest_event_timestamp: TimestampMillis, } +#[derive(Serialize, Deserialize)] +pub struct CommunityEventsPrevious { + events_map: BTreeMap>, +} + #[derive(Serialize, Deserialize, Clone, Debug)] -pub enum CommunityEventInternal { +pub enum CommunityEventInternalOld { #[serde(rename = "cr", alias = "Created")] Created(Box), #[serde(rename = "nc", alias = "NameChanged")] @@ -66,6 +72,50 @@ pub enum CommunityEventInternal { GroupImported(Box), } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum CommunityEventInternal { + #[serde(rename = "cr", alias = "Created")] + Created(Box), + #[serde(rename = "nc", alias = "NameChanged")] + NameChanged(Box), + #[serde(rename = "dc", alias = "DescriptionChanged")] + DescriptionChanged(Box), + #[serde(rename = "rc", alias = "RulesChanged")] + RulesChanged(Box), + #[serde(rename = "ac", alias = "AvatarChanged")] + AvatarChanged(Box), + #[serde(rename = "bc", alias = "BannerChanged")] + BannerChanged(Box), + #[serde(rename = "ui", alias = "UsersInvited")] + UsersInvited(Box), + #[serde(rename = "mr", alias = "MembersRemoved")] + MembersRemoved(Box), + #[serde(rename = "rc", alias = "RoleChanged")] + RoleChanged(Box), + #[serde(rename = "ub", alias = "UsersBlocked")] + UsersBlocked(Box), + #[serde(rename = "uu", alias = "UsersUnblocked")] + UsersUnblocked(Box), + #[serde(rename = "pc", alias = "PermissionsChanged")] + PermissionsChanged(Box), + #[serde(rename = "vc", alias = "VisibilityChanged")] + VisibilityChanged(Box), + #[serde(rename = "ic", alias = "InviteCodeChanged")] + InviteCodeChanged(Box), + #[serde(rename = "fr", alias = "Frozen")] + Frozen(Box), + #[serde(rename = "uf", alias = "Unfrozen")] + Unfrozen(Box), + #[serde(rename = "gu", alias = "GateUpdated")] + GateUpdated(Box), + #[serde(rename = "cd", alias = "ChannelDeleted")] + ChannelDeleted(Box), + #[serde(rename = "pl", alias = "PrimaryLanguageChanged")] + PrimaryLanguageChanged(Box), + #[serde(rename = "gi", alias = "GroupImported")] + GroupImported(Box), +} + impl CommunityEvents { pub fn new(name: String, description: String, created_by: UserId, now: TimestampMillis) -> CommunityEvents { let event_index = EventIndex::default(); @@ -73,7 +123,7 @@ impl CommunityEvents { events_map.insert( event_index, - EventWrapper { + EventWrapperInternal { index: event_index, timestamp: now, correlation_id: 0, @@ -98,7 +148,7 @@ impl CommunityEvents { self.events_map.insert( event_index, - EventWrapper { + EventWrapperInternal { index: event_index, timestamp: now, correlation_id: 0, @@ -132,3 +182,67 @@ pub struct GroupImportedInternal { pub channel_id: ChannelId, pub members_added: Vec, } + +impl TryFrom for CommunityEventInternal { + type Error = (); + + fn try_from(value: CommunityEventInternalOld) -> Result { + match value { + CommunityEventInternalOld::Created(e) => Ok(CommunityEventInternal::Created(e)), + CommunityEventInternalOld::NameChanged(e) => Ok(CommunityEventInternal::NameChanged(e)), + CommunityEventInternalOld::DescriptionChanged(e) => Ok(CommunityEventInternal::DescriptionChanged(e)), + CommunityEventInternalOld::RulesChanged(e) => Ok(CommunityEventInternal::RulesChanged(e)), + CommunityEventInternalOld::AvatarChanged(e) => Ok(CommunityEventInternal::AvatarChanged(e)), + CommunityEventInternalOld::BannerChanged(e) => Ok(CommunityEventInternal::BannerChanged(e)), + CommunityEventInternalOld::UsersInvited(e) => Ok(CommunityEventInternal::UsersInvited(e)), + CommunityEventInternalOld::MembersRemoved(e) => Ok(CommunityEventInternal::MembersRemoved(e)), + CommunityEventInternalOld::RoleChanged(e) => Ok(CommunityEventInternal::RoleChanged(e)), + CommunityEventInternalOld::UsersBlocked(e) => Ok(CommunityEventInternal::UsersBlocked(e)), + CommunityEventInternalOld::UsersUnblocked(e) => Ok(CommunityEventInternal::UsersUnblocked(e)), + CommunityEventInternalOld::PermissionsChanged(e) => Ok(CommunityEventInternal::PermissionsChanged(e)), + CommunityEventInternalOld::VisibilityChanged(e) => Ok(CommunityEventInternal::VisibilityChanged(e)), + CommunityEventInternalOld::InviteCodeChanged(e) => Ok(CommunityEventInternal::InviteCodeChanged(e)), + CommunityEventInternalOld::Frozen(e) => Ok(CommunityEventInternal::Frozen(e)), + CommunityEventInternalOld::Unfrozen(e) => Ok(CommunityEventInternal::Unfrozen(e)), + CommunityEventInternalOld::GateUpdated(e) => Ok(CommunityEventInternal::GateUpdated(e)), + CommunityEventInternalOld::ChannelDeleted(e) => Ok(CommunityEventInternal::ChannelDeleted(e)), + CommunityEventInternalOld::PrimaryLanguageChanged(e) => Ok(CommunityEventInternal::PrimaryLanguageChanged(e)), + CommunityEventInternalOld::GroupImported(e) => Ok(CommunityEventInternal::GroupImported(e)), + CommunityEventInternalOld::MemberJoined(_) + | CommunityEventInternalOld::MemberLeft(_) + | CommunityEventInternalOld::DefaultChannelsChanged(_) => Err(()), + } + } +} + +impl From for CommunityEvents { + fn from(value: CommunityEventsPrevious) -> Self { + let mut events_map = BTreeMap::new(); + let mut index = EventIndex::default(); + for old_event in value.events_map.into_values() { + if let Ok(new_event) = CommunityEventInternal::try_from(old_event.event) { + events_map.insert( + index, + EventWrapperInternal { + index, + timestamp: old_event.timestamp, + correlation_id: 0, + expires_at: None, + event: new_event, + }, + ); + index = index.incr(); + } + } + + let last = events_map.values().last().unwrap(); + let latest_event_index = last.index; + let latest_event_timestamp = last.timestamp; + + CommunityEvents { + events_map, + latest_event_index, + latest_event_timestamp, + } + } +} diff --git a/backend/canisters/community/impl/src/updates/c2c_join_community.rs b/backend/canisters/community/impl/src/updates/c2c_join_community.rs index 1801d04ff2..d30b518049 100644 --- a/backend/canisters/community/impl/src/updates/c2c_join_community.rs +++ b/backend/canisters/community/impl/src/updates/c2c_join_community.rs @@ -11,7 +11,7 @@ use gated_groups::{ check_if_passes_gate, CheckGateArgs, CheckIfPassesGateResult, CheckVerifiedCredentialGateArgs, GatePayment, }; use group_community_common::ExpiringMember; -use types::{AccessGate, ChannelId, MemberJoinedInternal, UsersUnblocked}; +use types::{AccessGate, ChannelId, UsersUnblocked}; #[update(guard = "caller_is_user_index_or_local_user_index", msgpack = true)] #[trace] @@ -150,15 +150,7 @@ pub(crate) fn join_community_impl( state.data.invited_users.remove(&args.user_id, now); - if !matches!(result, AddResult::AlreadyInCommunity) { - state.data.events.push_event( - CommunityEventInternal::MemberJoined(Box::new(MemberJoinedInternal { - user_id: args.user_id, - invited_by: referred_by, - })), - now, - ); - } else { + if matches!(result, AddResult::AlreadyInCommunity) { state.data.update_lapsed(args.user_id, None, false, now); } diff --git a/backend/canisters/community/impl/src/updates/c2c_leave_community.rs b/backend/canisters/community/impl/src/updates/c2c_leave_community.rs index cc7bba36fd..a6be091317 100644 --- a/backend/canisters/community/impl/src/updates/c2c_leave_community.rs +++ b/backend/canisters/community/impl/src/updates/c2c_leave_community.rs @@ -1,11 +1,7 @@ -use crate::{ - activity_notifications::handle_activity_notification, model::events::CommunityEventInternal, mutate_state, - run_regular_jobs, RuntimeState, -}; +use crate::{activity_notifications::handle_activity_notification, mutate_state, run_regular_jobs, RuntimeState}; use canister_api_macros::update; use canister_tracing_macros::trace; use community_canister::c2c_leave_community::{Response::*, *}; -use types::CommunityMemberLeftInternal; // Called via the user's user canister #[update(msgpack = true)] @@ -39,19 +35,7 @@ fn c2c_leave_community_impl(state: &mut RuntimeState) -> Response { return LastOwnerCannotLeave; } - let user_id = member.user_id; - - let removed = state.data.remove_user_from_community(user_id, now); - - state.data.events.push_event( - CommunityEventInternal::MemberLeft(Box::new(CommunityMemberLeftInternal { - user_id, - referred_by: removed.and_then(|r| r.referred_by), - })), - now, - ); - + state.data.remove_user_from_community(member.user_id, now); handle_activity_notification(state); - Success } diff --git a/backend/libraries/types/src/event_wrapper.rs b/backend/libraries/types/src/event_wrapper.rs index 13642fedb4..9ee3acbb89 100644 --- a/backend/libraries/types/src/event_wrapper.rs +++ b/backend/libraries/types/src/event_wrapper.rs @@ -16,15 +16,15 @@ pub struct EventWrapper { #[derive(Serialize, Deserialize, Clone, Debug)] pub struct EventWrapperInternal { - #[serde(rename = "i")] + #[serde(rename = "i", alias = "index")] pub index: EventIndex, - #[serde(rename = "t")] + #[serde(rename = "t", alias = "timestamp")] pub timestamp: TimestampMillis, - #[serde(rename = "c", default, skip_serializing_if = "is_default")] + #[serde(rename = "c", alias = "correlation_id", default, skip_serializing_if = "is_default")] pub correlation_id: u64, - #[serde(rename = "x", default, skip_serializing_if = "Option::is_none")] + #[serde(rename = "x", alias = "expires_at", default, skip_serializing_if = "Option::is_none")] pub expires_at: Option, - #[serde(rename = "e")] + #[serde(rename = "e", alias = "event")] pub event: T, }