Merge pull request #5678 from matrix-org/hs/fix-usage-alerts

Fix MAU usage alerts
This commit is contained in:
Travis Ralston 2021-02-24 11:21:03 -07:00 committed by GitHub
commit 83078a67c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 5 deletions

View file

@ -107,7 +107,9 @@ interface IState {
errcode: string; errcode: string;
}; };
}; };
usageLimitDismissed: boolean;
usageLimitEventContent?: IUsageLimit; usageLimitEventContent?: IUsageLimit;
usageLimitEventTs?: number;
useCompactLayout: boolean; useCompactLayout: boolean;
} }
@ -151,6 +153,7 @@ class LoggedInView extends React.Component<IProps, IState> {
syncErrorData: undefined, syncErrorData: undefined,
// use compact timeline view // use compact timeline view
useCompactLayout: SettingsStore.getValue('useCompactLayout'), useCompactLayout: SettingsStore.getValue('useCompactLayout'),
usageLimitDismissed: false,
}; };
// stash the MatrixClient in case we log out before we are unmounted // stash the MatrixClient in case we log out before we are unmounted
@ -302,14 +305,27 @@ class LoggedInView extends React.Component<IProps, IState> {
} }
}; };
private onUsageLimitDismissed = () => {
this.setState({
usageLimitDismissed: true,
});
}
_calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) { _calculateServerLimitToast(syncError: IState["syncErrorData"], usageLimitEventContent?: IUsageLimit) {
const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED"; const error = syncError && syncError.error && syncError.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED";
if (error) { if (error) {
usageLimitEventContent = syncError.error.data; usageLimitEventContent = syncError.error.data;
} }
if (usageLimitEventContent) { // usageLimitDismissed is true when the user has explicitly hidden the toast
showServerLimitToast(usageLimitEventContent.limit_type, usageLimitEventContent.admin_contact, error); // and it will be reset to false if a *new* usage alert comes in.
if (usageLimitEventContent && this.state.usageLimitDismissed) {
showServerLimitToast(
usageLimitEventContent.limit_type,
this.onUsageLimitDismissed,
usageLimitEventContent.admin_contact,
error,
);
} else { } else {
hideServerLimitToast(); hideServerLimitToast();
} }
@ -320,10 +336,12 @@ class LoggedInView extends React.Component<IProps, IState> {
if (!serverNoticeList) return []; if (!serverNoticeList) return [];
const events = []; const events = [];
let pinnedEventTs = 0;
for (const room of serverNoticeList) { for (const room of serverNoticeList) {
const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", ""); const pinStateEvent = room.currentState.getStateEvents("m.room.pinned_events", "");
if (!pinStateEvent || !pinStateEvent.getContent().pinned) continue; if (!pinStateEvent || !pinStateEvent.getContent().pinned) continue;
pinnedEventTs = pinStateEvent.getTs();
const pinnedEventIds = pinStateEvent.getContent().pinned.slice(0, MAX_PINNED_NOTICES_PER_ROOM); const pinnedEventIds = pinStateEvent.getContent().pinned.slice(0, MAX_PINNED_NOTICES_PER_ROOM);
for (const eventId of pinnedEventIds) { for (const eventId of pinnedEventIds) {
@ -333,6 +351,11 @@ class LoggedInView extends React.Component<IProps, IState> {
} }
} }
if (pinnedEventTs && this.state.usageLimitEventTs > pinnedEventTs) {
// We've processed a newer event than this one, so ignore it.
return;
}
const usageLimitEvent = events.find((e) => { const usageLimitEvent = events.find((e) => {
return ( return (
e && e.getType() === 'm.room.message' && e && e.getType() === 'm.room.message' &&
@ -341,7 +364,12 @@ class LoggedInView extends React.Component<IProps, IState> {
}); });
const usageLimitEventContent = usageLimitEvent && usageLimitEvent.getContent(); const usageLimitEventContent = usageLimitEvent && usageLimitEvent.getContent();
this._calculateServerLimitToast(this.state.syncErrorData, usageLimitEventContent); this._calculateServerLimitToast(this.state.syncErrorData, usageLimitEventContent);
this.setState({ usageLimitEventContent }); this.setState({
usageLimitEventContent,
usageLimitEventTs: pinnedEventTs,
// This is a fresh toast, we can show toasts again
usageLimitDismissed: false,
});
}; };
_onPaste = (ev) => { _onPaste = (ev) => {

View file

@ -23,7 +23,7 @@ import {messageForResourceLimitError} from "../utils/ErrorUtils";
const TOAST_KEY = "serverlimit"; const TOAST_KEY = "serverlimit";
export const showToast = (limitType: string, adminContact?: string, syncError?: boolean) => { export const showToast = (limitType: string, onHideToast: () => void, adminContact?: string, syncError?: boolean) => {
const errorText = messageForResourceLimitError(limitType, adminContact, { const errorText = messageForResourceLimitError(limitType, adminContact, {
'monthly_active_user': _td("Your homeserver has exceeded its user limit."), 'monthly_active_user': _td("Your homeserver has exceeded its user limit."),
'': _td("Your homeserver has exceeded one of its resource limits."), '': _td("Your homeserver has exceeded one of its resource limits."),
@ -38,7 +38,10 @@ export const showToast = (limitType: string, adminContact?: string, syncError?:
props: { props: {
description: <React.Fragment>{errorText} {contactText}</React.Fragment>, description: <React.Fragment>{errorText} {contactText}</React.Fragment>,
acceptLabel: _t("Ok"), acceptLabel: _t("Ok"),
onAccept: hideToast, onAccept: () => {
hideToast()
if (onHideToast) onHideToast();
},
}, },
component: GenericToast, component: GenericToast,
priority: 70, priority: 70,