Skip to content

Commit

Permalink
Store timestamps on historic users for when they stop being relevant
Browse files Browse the repository at this point in the history
  • Loading branch information
spb committed May 27, 2024
1 parent 6be3735 commit e9701e5
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
1 change: 1 addition & 0 deletions sable_network/src/network/network/account_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl Network {

self.historic_users.update_account(
user,
event.timestamp,
new_account
.as_ref()
.and_then(|id| accounts.get(id).map(|a| a.name)),
Expand Down
40 changes: 32 additions & 8 deletions sable_network/src/network/network/user_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,26 @@ impl HistoricUserStore {

/// Add a user to the store.
///
/// This should be called by the [`Network`] for every change to a client-protocol-visible attribute
/// of the user object.
pub fn add(&mut self, user: &mut state::User, nickname: Nickname, account: Option<Nickname>) {
/// This (or one of the update variants) should be called by the [`Network`] for every change
/// to a client-protocol-visible attribute of the user object.
///
/// The provided timestamp will be applied to the previous historic user corresponding to this
/// user object, to indicate when it ceased to be relevant, and the user object's serial number
/// will be incremented.
pub fn add(
&mut self,
user: &mut state::User,
timestamp: i64,
nickname: Nickname,
account: Option<Nickname>,
) {
if let Some(existing) = self
.users
.get_mut(&HistoricUserId::new(user.id, user.serial))
{
existing.timestamp = Some(timestamp);
}

user.serial += 1;

let historic_user = HistoricUser {
Expand All @@ -31,6 +48,7 @@ impl HistoricUserStore {
realname: user.realname,
away_reason: user.away_reason,
account,
timestamp: None,
};

let new_id = HistoricUserId::new(user.id, user.serial);
Expand All @@ -39,7 +57,7 @@ impl HistoricUserStore {
}

/// Update the details of a user that's already in the store, reusing the existing nickname and account
pub fn update(&mut self, user: &mut state::User) -> HistoricUserId {
pub fn update(&mut self, user: &mut state::User, timestamp: i64) -> HistoricUserId {
let old_id = HistoricUserId::new(user.id, user.serial);

let Some(existing) = self.get_user(&user) else {
Expand All @@ -49,12 +67,17 @@ impl HistoricUserStore {
let nickname = existing.nickname;
let account = existing.account;

self.add(user, nickname, account);
self.add(user, timestamp, nickname, account);
old_id
}

/// Update the details of a user that's already in the store, reusing the existing account
pub fn update_nick(&mut self, user: &mut state::User, nickname: Nickname) -> HistoricUserId {
pub fn update_nick(
&mut self,
user: &mut state::User,
timestamp: i64,
nickname: Nickname,
) -> HistoricUserId {
let old_id = HistoricUserId::new(user.id, user.serial);

let Some(existing) = self.get_user(&user) else {
Expand All @@ -63,14 +86,15 @@ impl HistoricUserStore {

let account = existing.account;

self.add(user, nickname, account);
self.add(user, timestamp, nickname, account);
old_id
}

/// Update the details of a user that's already in the store, reusing the existing nickname
pub fn update_account(
&mut self,
user: &mut state::User,
timestamp: i64,
account: Option<Nickname>,
) -> HistoricUserId {
let old_id = HistoricUserId::new(user.id, user.serial);
Expand All @@ -81,7 +105,7 @@ impl HistoricUserStore {

let nickname = existing.nickname;

self.add(user, nickname, account);
self.add(user, timestamp, nickname, account);
old_id
}

Expand Down
11 changes: 8 additions & 3 deletions sable_network/src/network/network/user_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ impl Network {
let new_binding =
state::NickBinding::new(new_nick, user_id, trigger.timestamp, trigger.id);

let prev_historic_id = self.historic_users.update_nick(user, new_nick);
let prev_historic_id =
self.historic_users
.update_nick(user, trigger.timestamp, new_nick);

// Let translate_historic_user do the work of mapping the account name, then manually fill in
// the old (collided) nick
Expand Down Expand Up @@ -154,7 +156,9 @@ impl Network {
let new_nick = new_binding.nick;
self.nick_bindings.insert(new_nick, new_binding);

let prev_historic_id = self.historic_users.update_nick(user_object, new_nick);
let prev_historic_id =
self.historic_users
.update_nick(user_object, event.timestamp, new_nick);

// Emit UserNickChange update if a nick change happens as a result of this rebinding.
if old_nick.value() != new_nick.value() {
Expand Down Expand Up @@ -209,6 +213,7 @@ impl Network {
// get_mut later on
self.historic_users.add(
&mut user,
event.timestamp,
detail.nickname,
detail
.account
Expand Down Expand Up @@ -259,7 +264,7 @@ impl Network {
let mut old_reason = new_reason;
std::mem::swap(&mut user.away_reason, &mut old_reason);

self.historic_users.update(user);
self.historic_users.update(user, event.timestamp);

let update_user = user.clone();

Expand Down
5 changes: 5 additions & 0 deletions sable_network/src/network/state/historic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub struct HistoricUser {
pub realname: Realname,
pub away_reason: Option<AwayReason>,
pub account: Option<Nickname>,

/// The time until which this historic user state was accurate - if None
/// then this data is current.
pub timestamp: Option<i64>,
}

impl wrapper::WrappedUser for HistoricUser {
Expand Down Expand Up @@ -70,6 +74,7 @@ impl HistoricUser {
visible_host: user.visible_host,
realname: user.realname,
away_reason: user.away_reason,
timestamp: None,
}
}
}
Expand Down

0 comments on commit e9701e5

Please sign in to comment.