Allow replies during room creation cooldowns

This commit is contained in:
jjbrunton committed 2026-08-09 16:22:48 +01:00
1 parent c630303b47
commit 910576921b
3 files changed
+55 -6

No files matched your search

+21 -6
View File
@@ -582,7 +582,7 @@ export class ChatService {
async sendChatMessage(chatUrlOrRoomId: string, message: string): Promise<boolean> {
if (!this.accountAuth?.isFullyAuthenticated()) return false;
const active = this.getInvitationCooldown();
if (active) {
if (active && this.blocksExistingRoomSends(active)) {
const secondsLeft = Math.ceil((active.until - Date.now()) / 1000);
this.logger.warn(
`[chat] skipping sendChatMessage — send cooldown active for ${secondsLeft}s (${active.redditCode ?? 'rate-limited'})`,
@@ -607,7 +607,7 @@ export class ChatService {
return true;
} catch (error) {
if (error instanceof MatrixRateLimitError) {
this.setInvitationCooldown(error);
this.setInvitationCooldown(error, 'all-sends');
return false;
}
this.logger.error('[chat] sendChatMessage failed:', error);
@@ -690,7 +690,7 @@ export class ChatService {
return { status: 'sent', chat };
} catch (error) {
if (error instanceof MatrixRateLimitError) {
this.setInvitationCooldown(error);
this.setInvitationCooldown(error, 'room-creation');
const cooldown = this.getInvitationCooldown();
return {
status: 'retryable',
@@ -758,17 +758,21 @@ export class ChatService {
}
/** Record a cooldown after a `MatrixRateLimitError`. Test seam + reuse. */
setInvitationCooldown(error: MatrixRateLimitError): void {
setInvitationCooldown(
error: MatrixRateLimitError,
scope: NonNullable<InvitationCooldown['scope']> = this.inferCooldownScope(error.redditCode),
): void {
const now = Date.now();
// Add a small safety margin so we don't probe again the very second
// the homeserver thinks the window expired.
const margin = 5_000;
this.invitationCooldown = {
until: now + error.retryAfterMs + margin,
scope,
redditCode: error.redditCode,
reason:
error.redditCode === 'rate.invitation_limit_mature_account'
? "Reddit is throttling new chat invitations (\"you've created a lot of chats, take a break\")."
scope === 'room-creation'
? 'Reddit is throttling new chat invitations; replies in existing chats can continue.'
: `Matrix rate-limited: ${error.errcode ?? '429'}`,
setAt: now,
};
@@ -780,6 +784,17 @@ export class ChatService {
void this.cache.persistCooldown();
}
private blocksExistingRoomSends(cooldown: InvitationCooldown): boolean {
return (cooldown.scope ?? this.inferCooldownScope(cooldown.redditCode)) === 'all-sends';
}
private inferCooldownScope(redditCode: string | null): NonNullable<InvitationCooldown['scope']> {
return redditCode === 'rate.room_creation_limit'
|| redditCode === 'rate.invitation_limit_mature_account'
? 'room-creation'
: 'all-sends';
}
// ------------ internals ------------
/** Single delta /sync that updates cache + nextBatch and returns the union. */
+5
View File
@@ -37,6 +37,11 @@ export interface ActiveChat {
export interface InvitationCooldown {
/** Wall-clock ms when sends may resume. */
until: number;
/**
* Operation class affected by the homeserver limit. Optional for caches
* written before cooldowns distinguished new rooms from existing-room sends.
*/
scope?: 'room-creation' | 'all-sends';
/** Reddit-side error code, e.g. `rate.invitation_limit_mature_account`. */
redditCode: string | null;
/** Human-readable explanation suitable for the dashboard. */