Skip to content

Commit

Permalink
Remove MemberJoined and MemberLeft community events (#6989)
Browse files Browse the repository at this point in the history
  • Loading branch information
hpeebles authored Dec 5, 2024
1 parent 898d47a commit 7fb32af
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 38 deletions.
1 change: 1 addition & 0 deletions backend/canisters/community/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
124 changes: 119 additions & 5 deletions backend/canisters/community/impl/src/model/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EventIndex, EventWrapper<CommunityEventInternal>>,
events_map: BTreeMap<EventIndex, EventWrapperInternal<CommunityEventInternal>>,
latest_event_index: EventIndex,
latest_event_timestamp: TimestampMillis,
}

#[derive(Serialize, Deserialize)]
pub struct CommunityEventsPrevious {
events_map: BTreeMap<EventIndex, EventWrapper<CommunityEventInternalOld>>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum CommunityEventInternal {
pub enum CommunityEventInternalOld {
#[serde(rename = "cr", alias = "Created")]
Created(Box<GroupCreated>),
#[serde(rename = "nc", alias = "NameChanged")]
Expand Down Expand Up @@ -66,14 +72,58 @@ pub enum CommunityEventInternal {
GroupImported(Box<GroupImportedInternal>),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum CommunityEventInternal {
#[serde(rename = "cr", alias = "Created")]
Created(Box<GroupCreated>),
#[serde(rename = "nc", alias = "NameChanged")]
NameChanged(Box<GroupNameChanged>),
#[serde(rename = "dc", alias = "DescriptionChanged")]
DescriptionChanged(Box<GroupDescriptionChanged>),
#[serde(rename = "rc", alias = "RulesChanged")]
RulesChanged(Box<GroupRulesChanged>),
#[serde(rename = "ac", alias = "AvatarChanged")]
AvatarChanged(Box<AvatarChanged>),
#[serde(rename = "bc", alias = "BannerChanged")]
BannerChanged(Box<BannerChanged>),
#[serde(rename = "ui", alias = "UsersInvited")]
UsersInvited(Box<UsersInvited>),
#[serde(rename = "mr", alias = "MembersRemoved")]
MembersRemoved(Box<CommunityMembersRemoved>),
#[serde(rename = "rc", alias = "RoleChanged")]
RoleChanged(Box<CommunityRoleChanged>),
#[serde(rename = "ub", alias = "UsersBlocked")]
UsersBlocked(Box<CommunityUsersBlocked>),
#[serde(rename = "uu", alias = "UsersUnblocked")]
UsersUnblocked(Box<UsersUnblocked>),
#[serde(rename = "pc", alias = "PermissionsChanged")]
PermissionsChanged(Box<CommunityPermissionsChanged>),
#[serde(rename = "vc", alias = "VisibilityChanged")]
VisibilityChanged(Box<CommunityVisibilityChanged>),
#[serde(rename = "ic", alias = "InviteCodeChanged")]
InviteCodeChanged(Box<GroupInviteCodeChanged>),
#[serde(rename = "fr", alias = "Frozen")]
Frozen(Box<GroupFrozen>),
#[serde(rename = "uf", alias = "Unfrozen")]
Unfrozen(Box<GroupUnfrozen>),
#[serde(rename = "gu", alias = "GateUpdated")]
GateUpdated(Box<GroupGateUpdatedInternal>),
#[serde(rename = "cd", alias = "ChannelDeleted")]
ChannelDeleted(Box<ChannelDeleted>),
#[serde(rename = "pl", alias = "PrimaryLanguageChanged")]
PrimaryLanguageChanged(Box<PrimaryLanguageChanged>),
#[serde(rename = "gi", alias = "GroupImported")]
GroupImported(Box<GroupImportedInternal>),
}

impl CommunityEvents {
pub fn new(name: String, description: String, created_by: UserId, now: TimestampMillis) -> CommunityEvents {
let event_index = EventIndex::default();
let mut events_map = BTreeMap::new();

events_map.insert(
event_index,
EventWrapper {
EventWrapperInternal {
index: event_index,
timestamp: now,
correlation_id: 0,
Expand All @@ -98,7 +148,7 @@ impl CommunityEvents {

self.events_map.insert(
event_index,
EventWrapper {
EventWrapperInternal {
index: event_index,
timestamp: now,
correlation_id: 0,
Expand Down Expand Up @@ -132,3 +182,67 @@ pub struct GroupImportedInternal {
pub channel_id: ChannelId,
pub members_added: Vec<UserId>,
}

impl TryFrom<CommunityEventInternalOld> for CommunityEventInternal {
type Error = ();

fn try_from(value: CommunityEventInternalOld) -> Result<Self, Self::Error> {
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<CommunityEventsPrevious> 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,
}
}
}
12 changes: 2 additions & 10 deletions backend/canisters/community/impl/src/updates/c2c_join_community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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
}
10 changes: 5 additions & 5 deletions backend/libraries/types/src/event_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ pub struct EventWrapper<T> {

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct EventWrapperInternal<T> {
#[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<TimestampMillis>,
#[serde(rename = "e")]
#[serde(rename = "e", alias = "event")]
pub event: T,
}

Expand Down

0 comments on commit 7fb32af

Please sign in to comment.