This example will show how to manage the persistence of message-related data using Rocket.Chat Apps-Engine.
Doing this involves creating a class MessagePersistence in the Apps root folder that interacts with Rocket.Chat persistence layer. This class will host static methods to add, remove, and query data associated with messages, rooms, and specific IDs.
import { IPersistence, IPersistenceRead } from '@rocket.chat/apps-engine/definition/accessors';
import { RocketChatAssociationModel, RocketChatAssociationRecord } from '@rocket.chat/apps-engine/definition/metadata';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms';
export class MessagePersistence {
// add records
public static async persist(persis: IPersistence, room: IRoom, id: string): Promise<boolean> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
new RocketChatAssociationRecord(RocketChatAssociationModel.ROOM, room.id),
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, id),
];
try {
await persis.updateByAssociations(associations, { id }, true);
} catch (err) {
console.warn(err);
return false;
}
return true;
}
// query all records within the "scope" - message
public static async findAll(persis: IPersistenceRead): Promise<Array<string>> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
];
let result: Array<string> = [];
try {
const records: Array<{ id: string }> = (await persis.readByAssociations(associations)) as Array<{ id: string }>;
if (records.length) {
result = records.map(({ id }) => id);
}
} catch (err) {
console.warn(err);
}
return result;
}
// query all records by room within the "scope" - message
public static async findByRoom(persis: IPersistenceRead, room: IRoom): Promise<Array<string>> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
new RocketChatAssociationRecord(RocketChatAssociationModel.ROOM, room.id),
];
let result: Array<string> = [];
try {
const records: Array<{ id: string }> = (await persis.readByAssociations(associations)) as Array<{ id: string }>;
if (records.length) {
result = records.map(({ id }) => id);
}
} catch (err) {
console.warn(err);
}
return result;
}
// remove all records by room within the "scope" - message
public static async removeByRoom(persis: IPersistence, room: IRoom): Promise<boolean> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
new RocketChatAssociationRecord(RocketChatAssociationModel.ROOM, room.id),
];
try {
await persis.removeByAssociations(associations);
} catch (err) {
console.warn(err);
return false;
}
return true;
}
// remove all records by id within the "scope" - message
public static async removeById(persis: IPersistence, id: string): Promise<boolean> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, id),
];
try {
await persis.removeByAssociations(associations);
} catch (err) {
console.warn(err);
return false;
}
return true;
}
// remove all records within the "scope" - message
public static async clear(persis): Promise<boolean> {
const associations: Array<RocketChatAssociationRecord> = [
new RocketChatAssociationRecord(RocketChatAssociationModel.MISC, 'message'),
];
try {
await persis.removeByAssociations(associations);
} catch (err) {
console.warn(err);
return false;
}
return true;
}
}The following was achieved from the code block above:
The
persistmethod adds or updates a record in the persistence layer and associates it with a specific room and message ID.findAllmethod fetches all records associated withmessageand returns an array of their IDs.The
findByRoommethod retrieves all message IDs associated with a specific room.removeByRoommethod removes all records associated with a specific room within themessagescope. It returns true if successful and false otherwise.removeByIddeletes all records associated with a specific message ID within themessagescope.clearDeletes all records in themessagescope.
The executePostMessageSent class can be modified to the code below:
import { IAppAccessors, IHttp, ILogger, IModify, IPersistence, IRead } from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IMessage, IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { IRoom } from '@rocket.chat/apps-engine/definition/rooms';
// Import the MessagePersistence class
import { MessagePersistence } from './MessagePersistence';
export class MyRocketChatApp extends App implements IPostMessageSent {
constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
super(info, logger, accessors);
}
public async executePostMessageSent(
message: IMessage,
read: IRead,
http: IHttp,
persistence: IPersistence,
modify: IModify
): Promise<void> {
const room: IRoom = message.room;
const messageId: string = message.id ?? 'default-id';
// Example: Persist the message ID
const success = await MessagePersistence.persist(persistence, room, messageId);
if (success) {
this.getLogger().log(`Message ID ${messageId} persisted successfully.`);
} else {
this.getLogger().error(`Failed to persist message ID ${messageId}.`);
}
// Example: Retrieve all message IDs
const allMessageIds = await MessagePersistence.findAll(read.getPersistenceReader());
this.getLogger().log(`All message IDs: ${allMessageIds.join(', ')}`);
// Example: Remove all messages by room
const removeSuccess = await MessagePersistence.removeByRoom(persistence, room);
if (removeSuccess) {
this.getLogger().log(`All messages in room ${room.id} removed successfully.`);
} else {
this.getLogger().error(`Failed to remove messages in room ${room.id}.`);
}
}
}Here, the MessagePersistence class is imported, and the methods persist, findAll, and removeByRoom are called to store the message ID, get all the messages stored in the message scope, and delete all the messages associated with the room.
Send a few messages in a channel to observe the code in action. Then, navigate to Marketplace > Private Apps. Select the app you deployed and access the logs. Among the various logs, locate the one labeled executePostMessageSent. Open it, and you should find a message that resembles the following:

The image above shows the logs after sending messages to the general channel.