Skip to content

Commit 6f1f4c4

Browse files
committed
hotfix: pictique message disappearing
1 parent c425752 commit 6f1f4c4

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

platforms/pictique-api/src/services/MessageService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export class MessageService {
77
private chatRepository = AppDataSource.getRepository(Chat);
88

99
async findById(id: string): Promise<Message | null> {
10-
return await this.messageRepository.findOne({
10+
return await this.messageRepository.findOne({
1111
where: { id },
1212
relations: ["chat", "sender"]
1313
});
@@ -23,7 +23,7 @@ export class MessageService {
2323
});
2424

2525
const savedMessage = await this.messageRepository.save(message);
26-
26+
2727
// Update the chat's updatedAt timestamp to reflect the latest message
2828
const chat = await this.chatRepository.findOneBy({ id: chatId });
2929
if (chat) {
@@ -37,4 +37,4 @@ export class MessageService {
3737
async createSystemMessage(chatId: string, text: string): Promise<Message> {
3838
return this.createMessage(null, chatId, text, true);
3939
}
40-
}
40+
}

platforms/pictique-api/src/web3adapter/watchers/subscriber.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const JUNCTION_TABLE_MAP = {
3434
export class PostgresSubscriber implements EntitySubscriberInterface {
3535
private adapter: Web3Adapter;
3636
private pendingChanges: Map<string, number> = new Map();
37+
private recentMessageActivity: Map<string, number> = new Map(); // chatId -> timestamp
3738

3839
constructor() {
3940
this.adapter = adapter;
@@ -42,6 +43,11 @@ export class PostgresSubscriber implements EntitySubscriberInterface {
4243
setInterval(() => {
4344
this.cleanupOldPendingChanges();
4445
}, 5 * 60 * 1000);
46+
47+
// Clean up old message activity every minute
48+
setInterval(() => {
49+
this.cleanupOldMessageActivity();
50+
}, 60 * 1000);
4551
}
4652

4753
/**
@@ -59,6 +65,20 @@ export class PostgresSubscriber implements EntitySubscriberInterface {
5965
}
6066
}
6167

68+
/**
69+
* Clean up old message activity to prevent memory leaks
70+
*/
71+
private cleanupOldMessageActivity(): void {
72+
const now = Date.now();
73+
const maxAge = 10 * 1000; // 10 seconds
74+
75+
for (const [chatId, timestamp] of this.recentMessageActivity.entries()) {
76+
if (now - timestamp > maxAge) {
77+
this.recentMessageActivity.delete(chatId);
78+
}
79+
}
80+
}
81+
6282
/**
6383
* Called after entity is loaded.
6484
*/
@@ -203,6 +223,28 @@ export class PostgresSubscriber implements EntitySubscriberInterface {
203223
const data = this.entityToPlain(entity);
204224
if (!data.id) return;
205225

226+
// For messages, track activity per chat to prevent race conditions
227+
if (tableName === "messages") {
228+
const chatId = data.chat?.id;
229+
if (chatId) {
230+
console.log(`Recording message activity for chat: ${chatId}`);
231+
this.recentMessageActivity.set(chatId, Date.now());
232+
}
233+
}
234+
235+
// For chats, check if there was recent message activity
236+
if (tableName === "chats") {
237+
const chatId = data.id;
238+
const lastMessageActivity = this.recentMessageActivity.get(chatId);
239+
if (lastMessageActivity) {
240+
const timeSinceLastMessage = Date.now() - lastMessageActivity;
241+
if (timeSinceLastMessage < 5000) { // 5 seconds
242+
console.log(`Skipping chat ${chatId} change, recent message activity ${timeSinceLastMessage}ms ago`);
243+
return;
244+
}
245+
}
246+
}
247+
206248
// Create a unique key for this entity change to prevent duplicates
207249
const changeKey = `${tableName}:${entity.id}`;
208250

0 commit comments

Comments
 (0)