simplify metadata retrieval

This commit is contained in:
nvms 2025-04-22 10:53:45 -04:00
parent 209614c3e8
commit 48b41c9d19
2 changed files with 163 additions and 3 deletions

View File

@ -10,9 +10,19 @@ export { Status } from "../common/status";
export { applyPatch } from "fast-json-patch";
export type PresenceUpdate =
| { type: "join"; connectionId: string }
| { type: "leave"; connectionId: string }
| { type: "state"; connectionId: string; state: Record<string, any> | null };
| {
type: "join" | "leave";
connectionId: string;
roomName: string;
timestamp?: number;
}
| {
type: "state";
connectionId: string;
roomName: string;
state: any;
timestamp?: number;
};
export type PresenceUpdateCallback = (
update: PresenceUpdate
@ -766,4 +776,102 @@ export class MeshClient extends EventEmitter {
return false;
}
}
/**
* Gets metadata for a specific room.
*
* @param {string} roomName - The name of the room to get metadata for.
* @returns {Promise<any>} A promise that resolves with the room metadata.
*/
async getRoomMetadata(roomName: string): Promise<any> {
try {
const result = await this.command("mesh/get-room-metadata", {
roomName,
});
return result.metadata;
} catch (error) {
console.error(
`[MeshClient] Failed to get metadata for room ${roomName}:`,
error
);
return null;
}
}
/**
* Gets metadata for a connection.
*
* @param {string} [connectionId] - The ID of the connection to get metadata for. If not provided, gets metadata for the current connection.
* @returns {Promise<any>} A promise that resolves with the connection metadata.
*/
async getConnectionMetadata(connectionId?: string): Promise<any> {
try {
if (connectionId) {
const result = await this.command("mesh/get-connection-metadata", {
connectionId,
});
return result.metadata;
} else {
const result = await this.command("mesh/get-my-connection-metadata");
return result.metadata;
}
} catch (error) {
const idText = connectionId ? ` ${connectionId}` : "";
console.error(
`[MeshClient] Failed to get metadata for connection${idText}:`,
error
);
return null;
}
}
/**
* Register a callback for the connect event.
* This event is emitted when the client successfully connects to the server.
*
* @param {() => void} callback - The function to call when the client connects
* @returns {this} The client instance for chaining
*/
onConnect(callback: () => void): this {
this.on("connect", callback);
return this;
}
/**
* Register a callback for the disconnect event.
* This event is emitted when the client disconnects from the server.
*
* @param {() => void} callback - The function to call when the client disconnects
* @returns {this} The client instance for chaining
*/
onDisconnect(callback: () => void): this {
this.on("disconnect", callback);
return this;
}
/**
* Register a callback for the reconnect event.
* This event is emitted when the client successfully reconnects to the server
* after a disconnection.
*
* @param {() => void} callback - The function to call when the client reconnects
* @returns {this} The client instance for chaining
*/
onReconnect(callback: () => void): this {
this.on("reconnect", callback);
return this;
}
/**
* Register a callback for the reconnect failed event.
* This event is emitted when the client fails to reconnect after reaching
* the maximum number of reconnect attempts.
*
* @param {() => void} callback - The function to call when reconnection fails
* @returns {this} The client instance for chaining
*/
onReconnectFailed(callback: () => void): this {
this.on("reconnectfailed", callback);
return this;
}
}

View File

@ -576,6 +576,58 @@ export class MeshServer extends WebSocketServer {
return { success: true };
}
);
this.exposeCommand<{ connectionId: string }, { metadata: any }>(
"mesh/get-connection-metadata",
async (ctx) => {
const { connectionId } = ctx.payload;
// Try to get the local connection first
const connection =
this.connectionManager.getLocalConnection(connectionId);
if (connection) {
// If we have the connection locally, use it to get metadata
const metadata = await this.connectionManager.getMetadata(connection);
return { metadata };
} else {
// If the connection is not local, we need to get metadata directly from Redis
// This is a workaround since we don't have direct access to the connection
const metadata = await this.redisManager.redis.hget(
"mesh:connections",
connectionId
);
return { metadata: metadata ? JSON.parse(metadata) : null };
}
}
);
this.exposeCommand<{}, { metadata: any }>(
"mesh/get-my-connection-metadata",
async (ctx) => {
const connectionId = ctx.connection.id;
const connection =
this.connectionManager.getLocalConnection(connectionId);
if (connection) {
const metadata = await this.connectionManager.getMetadata(connection);
return { metadata };
} else {
const metadata = await this.redisManager.redis.hget(
"mesh:connections",
connectionId
);
return { metadata: metadata ? JSON.parse(metadata) : null };
}
}
);
this.exposeCommand<{ roomName: string }, { metadata: any }>(
"mesh/get-room-metadata",
async (ctx) => {
const { roomName } = ctx.payload;
const metadata = await this.roomManager.getMetadata(roomName);
return { metadata };
}
);
}
private registerRecordCommands() {