Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small performance fixes #1192

Merged
merged 6 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/1192.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve the performance of sending messages by speeding up some function calls
2 changes: 1 addition & 1 deletion src/DebugApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ export class DebugApi {
return undefined;
}
return {
channels: client.chanList,
channels: [...client.chanList],
dead: client.isDead(),
server: client.server.domain,
nick: client.nick,
Expand Down
6 changes: 3 additions & 3 deletions src/bridge/AdminRoomHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,14 +409,14 @@ export class AdminRoomHandler {
"notice", "You are not currently connected to this irc network"
));
}
if (client.chanList.length === 0) {
if (client.chanList.size === 0) {
return this.ircBridge.sendMatrixAction(room, this.botUser, new MatrixAction(
"notice", "You are connected, but not joined to any channels."
));
}

let chanList = `You are joined to ${client.chanList.length} rooms: \n\n`;
let chanListHTML = `<p> You are joined to <code>${client.chanList.length}</code> rooms: </p><ul>`;
let chanList = `You are joined to ${client.chanList.size} rooms: \n\n`;
let chanListHTML = `<p> You are joined to <code>${client.chanList.size}</code> rooms: </p><ul>`;
for (const channel of client.chanList) {
const rooms = await this.ircBridge.getStore().getMatrixRoomsForChannel(server, channel);
chanList += `- \`${channel}\` which is bridged to ${rooms.map((r) => r.getId()).join(", ")}`;
Expand Down
4 changes: 2 additions & 2 deletions src/bridge/MatrixHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ export class MatrixHandler {

for (let i = 0; i < clients.length; i++) {
const bridgedClient = clients[i];
if (bridgedClient.chanList.length === 0) {
if (bridgedClient.chanList.size === 0) {
req.log.info(
`Bridged client for ${userId} is not in any channels ` +
`on ${bridgedClient.server.domain}`
Expand All @@ -294,7 +294,7 @@ export class MatrixHandler {
// Get all rooms that the bridgedClient is in
const uniqueRoomIds = new Set<string>();
(await Promise.all(
bridgedClient.chanList.map(
[...bridgedClient.chanList].map(
(channel) => {
return this.ircBridge.getStore().getMatrixRoomsForChannel(
bridgedClient.server, channel
Expand Down
24 changes: 15 additions & 9 deletions src/datastore/postgres/PgDataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,22 @@ import Bluebird from "bluebird";
import { StringCrypto } from "../StringCrypto";
import { toIrcLowerCase } from "../../irc/formatting";
import { NeDBDataStore } from "../NedbDataStore";
import QuickLRU from "quick-lru";

const log = getLogger("PgDatastore");

const FEATURE_CACHE_SIZE = 512;

export class PgDataStore implements DataStore {
private serverMappings: {[domain: string]: IrcServer} = {};

public static readonly LATEST_SCHEMA = 5;
private pgPool: Pool;
private hasEnded = false;
private cryptoStore?: StringCrypto;
private userFeatureCache = new QuickLRU<string, UserFeatures>({
maxSize: FEATURE_CACHE_SIZE,
});

constructor(private bridgeDomain: string, connectionString: string, pkeyPath?: string, min = 1, max = 4) {
this.pgPool = new Pool({
Expand Down Expand Up @@ -465,14 +471,14 @@ export class PgDataStore implements DataStore {
}

public async getUserFeatures(userId: string): Promise<UserFeatures> {
const pgRes = (
await this.pgPool.query("SELECT features FROM user_features WHERE user_id = $1",
[userId])
);
if (pgRes.rowCount === 0) {
return {};
const existing = this.userFeatureCache.get(userId);
if (existing) {
return existing;
}
return pgRes.rows[0].features || {};
const pgRes = await this.pgPool.query("SELECT features FROM user_features WHERE user_id = $1", [userId]);
const features = (pgRes.rows[0] || {});
this.userFeatureCache.set(userId, features);
return features;
}

public async storeUserFeatures(userId: string, features: UserFeatures): Promise<void> {
Expand Down Expand Up @@ -512,7 +518,7 @@ export class PgDataStore implements DataStore {
[username, domain]
);
if (res.rowCount === 0) {
return;
return undefined;
}
else if (res.rowCount > 1) {
log.error("getMatrixUserByUsername returned %s results for %s on %s", res.rowCount, username, domain);
Expand Down Expand Up @@ -540,7 +546,7 @@ export class PgDataStore implements DataStore {
await this.pgPool.query(statement, [userId, Date.now()]);
}

public async getLastSeenTimeForUsers(): Promise<{ user_id: string, ts: number }[]> {
public async getLastSeenTimeForUsers(): Promise<{ user_id: string; ts: number }[]> {
const res = await this.pgPool.query(`SELECT * FROM last_seen`);
return res.rows;
}
Expand Down
8 changes: 5 additions & 3 deletions src/irc/BridgedClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export class BridgedClient extends EventEmitter {
}

public get chanList() {
return Array.from(this._chanList);
return this._chanList;
}

public get status() {
Expand Down Expand Up @@ -320,14 +320,16 @@ export class BridgedClient extends EventEmitter {
}

public async reconnect(reconnectChanList: string[]) {
// XXX: Why do we add these here?
reconnectChanList.forEach((c) => this._chanList.add(c));
await this.connect();
this.log.info(
"Reconnected %s@%s", this.nick, this.server.domain
);
this.log.info("Rejoining %s channels", this.chanList.length);
this.log.info("Rejoining %s channels", this._chanList.size);
// This needs to be synchronous
for (const channel of this.chanList) {
for (const channel of this._chanList) {
// XXX: Why do we not catch these?
await this.joinChannel(channel);
}
this.log.info("Rejoined channels");
Expand Down
8 changes: 4 additions & 4 deletions src/irc/ClientPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ export class ClientPool {
public getNickUserIdMappingForChannel(server: IrcServer, channel: string): {[nick: string]: string} {
const nickUserIdMap: {[nick: string]: string} = {};
for (const [userId, client] of this.virtualClients[server.domain].userIds.entries()) {
if (client.chanList.includes(channel)) {
if (client.inChannel(channel)) {
nickUserIdMap[client.nick] = userId;
}
}
Expand Down Expand Up @@ -584,7 +584,7 @@ export class ClientPool {
const isBot = bridgedClient.isBot;
const chanList = bridgedClient.chanList;

if (chanList.length === 0 && !isBot && disconnectReason !== "iwanttoreconnect") {
if (chanList.size === 0 && !isBot && disconnectReason !== "iwanttoreconnect") {
// Never drop the bot, or users that really want to reconnect.
log.info(
`Dropping ${bridgedClient.id} (${bridgedClient.nick}) because they are not joined to any channels`
Expand Down Expand Up @@ -627,13 +627,13 @@ export class ClientPool {
if (queue === null) {
this.reconnectClient({
cli: cli,
chanList: chanList,
chanList: [...chanList],
});
return;
}
queue.enqueue(cli.id, {
cli: cli,
chanList: chanList,
chanList: [...chanList],
});
}

Expand Down