add a lazyload for large rooms

This commit is contained in:
emerson 2022-02-18 17:07:51 -05:00
parent 5124e98a49
commit 06b2d86017
5 changed files with 26 additions and 15 deletions

View file

@ -29,9 +29,6 @@ You can't send a PM to individual users, since a "PM" in Matrix is just another
### Spaces ### Spaces
There's no IRC equivalent to Spaces (I'll probably write a spec for it since it's widely used elsewhere). Since they are just regular rooms, they show up in IRC as just regular rooms. You aren't supposed to send messages to them, once I implement mode handling I'll use `+m` to disallow sending. There's no IRC equivalent to Spaces (I'll probably write a spec for it since it's widely used elsewhere). Since they are just regular rooms, they show up in IRC as just regular rooms. You aren't supposed to send messages to them, once I implement mode handling I'll use `+m` to disallow sending.
### Client overload
If you're in a ton of channels, or several big ones, your IRC client/CPU might melt slightly on initial sync. I'm working on a "lazy-loading" channel list to fix that. Joining `#matrix:matrix.org` using WeeChat pegs a CPU core for a good 45 seconds.
### Highlighting users ### Highlighting users
In order to highlight users, you need to prefix their nick with an `@`, so `@emerson: hi`. Reflection automatically expands this to the user's MXID, so even though it's annoying, it's needed to stop inadvertent highlights for now. In order to highlight users, you need to prefix their nick with an `@`, so `@emerson: hi`. Reflection automatically expands this to the user's MXID, so even though it's annoying, it's needed to stop inadvertent highlights for now.

View file

@ -2,5 +2,6 @@
"serverName": "testing.", "serverName": "testing.",
"port": 6697, "port": 6697,
"certFile": "reflection.pem", "certFile": "reflection.pem",
"keyFile": "reflection.key" "keyFile": "reflection.key",
"lazyLoadLimit": 500
} }

View file

@ -9,6 +9,7 @@ export class Channel {
// <nick, PL number> // <nick, PL number>
public powerLevels: Map<string, number> public powerLevels: Map<string, number>
public topic: Map<string, string>; public topic: Map<string, string>;
public channelModes: Map<string, string>;
public eventIDsSeen: Set<string>; public eventIDsSeen: Set<string>;
public historyVisibility: string public historyVisibility: string
public guestAccess: string public guestAccess: string
@ -21,11 +22,13 @@ export class Channel {
this.matrixUsers.set(initialMatrixUser.nick, initialMatrixUser); this.matrixUsers.set(initialMatrixUser.nick, initialMatrixUser);
this.powerLevels = new Map(); this.powerLevels = new Map();
this.topic = new Map([['text', ''], ['timestamp', '0'], ['setter', 'matrix']]); this.topic = new Map([['text', ''], ['timestamp', '0'], ['setter', 'matrix']]);
this.channelModes = new Map([['n', '']]);
this.eventIDsSeen = new Set(); this.eventIDsSeen = new Set();
this.historyVisibility = ""; this.historyVisibility = "";
this.guestAccess = ""; this.guestAccess = "";
this.joinRules = ""; this.joinRules = "";
this.syncLocks = new Set(); this.syncLocks = new Set();
this.syncLocks.add('isDM');
this.doInitialSync(); this.doInitialSync();
this.initialSyncID = setInterval(this.checkChannelSync.bind(this), 2000); this.initialSyncID = setInterval(this.checkChannelSync.bind(this), 2000);
} }
@ -66,9 +69,14 @@ export class Channel {
this.syncLocks.add("m.room.members"); this.syncLocks.add("m.room.members");
axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/joined_members?access_token=${this.ircUser.accessToken}`).then(response => { axios.get(`https://${this.ircUser.homeserver}/_matrix/client/v3/rooms/${this.roomId}/joined_members?access_token=${this.ircUser.accessToken}`).then(response => {
const allMembers = response.data["joined"]; const allMembers = response.data["joined"];
for (const member of Object.keys(allMembers)) { const allMxids = Object.keys(allMembers);
const nextMatrixUser = this.ircUser.getOrCreateMatrixUser(member); if (allMxids.length > this.ircUser.server.config["lazyLoadLimit"]) {
this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser); this.channelModes.set('u', '');
} else {
for (const member of allMxids) {
const nextMatrixUser = this.ircUser.getOrCreateMatrixUser(member);
this.matrixUsers.set(nextMatrixUser.nick, nextMatrixUser);
}
} }
this.syncLocks.delete("m.room.members") this.syncLocks.delete("m.room.members")
}).catch(e => { }).catch(e => {
@ -98,14 +106,15 @@ export class Channel {
}) })
} }
checkChannelSync() { checkChannelSync() {
if (this.isSynced()) { if (this.syncLocks.size === 1) {
if (this.matrixUsers.size === 2 && this.name === this.roomId) { if (this.matrixUsers.size === 2 && this.name === this.roomId) {
const otherUser = [...this.matrixUsers.values()].filter(m => m.nick !== this.ircUser.nick); const otherUser = [...this.matrixUsers.values()].filter(m => m.nick !== this.ircUser.nick);
const directRoomsForUser = this.ircUser.directRooms.get(otherUser[0].mxid); const directRoomsForUser = this.ircUser.directRooms.get(otherUser[0].mxid);
if (directRoomsForUser && directRoomsForUser.includes(this.roomId)) if (directRoomsForUser && directRoomsForUser.includes(this.roomId))
this.name = `&${otherUser[0].mxid.substring(1)}` this.name = `&${otherUser[0].mxid.substring(1)}`
} }
this.syncLocks.delete('isDM');
this.ircUser.finishChannelSync(this); this.ircUser.finishChannelSync(this);
clearInterval(this.initialSyncID); clearInterval(this.initialSyncID);
} }

View file

@ -202,7 +202,10 @@ export class Client {
for (const roomId of Object.keys(rooms.join)) { for (const roomId of Object.keys(rooms.join)) {
const targetChannel = this.user.getOrCreateIRCChannel(roomId); const targetChannel = this.user.getOrCreateIRCChannel(roomId);
//@ts-ignore //@ts-ignore
rooms.join[roomId].state.events.forEach((nextEvent: any) => this.user.routeMatrixEvent(nextEvent, targetChannel)); rooms.join[roomId].state.events.forEach((nextEvent: any) => {
if (targetChannel.isSynced() && this.user)
this.user.routeMatrixEvent(nextEvent, targetChannel)
});
} }
} }
if (this.user === null) if (this.user === null)
@ -351,7 +354,8 @@ export class Client {
} }
if (!this.checkIfInChannel(targetChannel)) return; if (!this.checkIfInChannel(targetChannel)) return;
if (message.params.length === 1) { if (message.params.length === 1) {
this.sendMessage(this.server.name, "324", [this.user.nick, targetChannel.name, `+n`]); const chanModes = [...targetChannel.channelModes.keys()].sort().join('');
this.sendMessage(this.server.name, "324", [this.user.nick, targetChannel.name, `+${chanModes}`]);
return; return;
} }
} }
@ -569,10 +573,10 @@ export class Client {
this.sendMessage(this.server.name, '001', numerics['001'](this.user.nick, this.server.name)); this.sendMessage(this.server.name, '001', numerics['001'](this.user.nick, this.server.name));
this.sendMessage(this.server.name, '002', numerics['002'](this.user.nick, this.server.name, '0.0.1')); this.sendMessage(this.server.name, '002', numerics['002'](this.user.nick, this.server.name, '0.0.1'));
this.sendMessage(this.server.name, '003', numerics['003'](this.user.nick, 'yesterday')); this.sendMessage(this.server.name, '003', numerics['003'](this.user.nick, 'yesterday'));
this.sendMessage(this.server.name, '004', numerics['004'](this.user.nick, this.server.name, '0.0.1', 'i', 'Lhionpsv')); this.sendMessage(this.server.name, '004', numerics['004'](this.user.nick, this.server.name, '0.0.1', 'i', 'hnovu'));
const iSupportArray = [ const iSupportArray = [
'CASEMAPPING=ascii', 'CASEMAPPING=ascii',
'CHANMODES=,,,Linps', 'CHANMODES=,,,nu',
'CHANTYPES=#&!', 'CHANTYPES=#&!',
'MAXTARGETS=1', 'MAXTARGETS=1',
'PREFIX=(ohv)@%+', 'PREFIX=(ohv)@%+',

View file

@ -24,7 +24,7 @@ export class IRCUser {
private isSyncing: boolean private isSyncing: boolean
private currentSyncTime: number private currentSyncTime: number
private syncIntervalID: NodeJS.Timeout; private syncIntervalID: NodeJS.Timeout;
constructor(public mxid: string, public accessToken: string, public homeserver: string, private server: Server) { constructor(public mxid: string, public accessToken: string, public homeserver: string, public server: Server) {
this.clients = new Set(); this.clients = new Set();
this.channels = new Map(); this.channels = new Map();
this.roomIdToChannel = new Map(); this.roomIdToChannel = new Map();
@ -251,7 +251,7 @@ export class IRCUser {
case 'org.matrix.msc3381.poll.start': case 'org.matrix.msc3381.poll.start':
break; break;
default: default:
console.log(nextEvent); console.log(`${targetChannel.name}: ${nextEvent}`);
break; break;
} }
} }