Skip to content
Open
Changes from all 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
13 changes: 12 additions & 1 deletion packages/federation-sdk/src/repositories/event.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,18 @@ export class EventRepository {
constructor(
@inject('EventCollection')
private readonly collection: Collection<EventStore>,
) {}
) {
this.collection.createIndex({
'event.room_id': 1,
'nextEventId': 1,
'event.depth': 1,
'createdAt': 1,
});
this.collection.createIndex({
'event.room_id': 1,
'event.type': 1,
});
}
Comment on lines +12 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unhandled promises from createIndex() calls.

createIndex() returns a Promise<string> that is neither awaited nor has error handling attached. This means:

  1. Index creation errors will be silently swallowed as unhandled rejections.
  2. There's no guarantee indexes are ready before the first query executes.

Since this is a @singleton() managed by tsyringe, consider adding an explicit async init() method that the application can await during startup, or at minimum handle the promise rejection:

Option 1: Add error handling (minimal change)
 	constructor(
 		`@inject`('EventCollection')
 		private readonly collection: Collection<EventStore>,
 	) {
-		this.collection.createIndex({
+		this.collection.createIndex({
 			'event.room_id': 1,
 			'nextEventId': 1,
 			'event.depth': 1,
 			'createdAt': 1,
-		});
-		this.collection.createIndex({
+		}).catch((err) => console.error('Failed to create event index (room_id, nextEventId, depth, createdAt):', err));
+		this.collection.createIndex({
 			'event.room_id': 1,
 			'event.type': 1,
-		});
+		}).catch((err) => console.error('Failed to create event index (room_id, type):', err));
 	}
Option 2: Separate initialization method (recommended for startup guarantees)
 	constructor(
 		`@inject`('EventCollection')
 		private readonly collection: Collection<EventStore>,
-	) {
-		this.collection.createIndex({
-			'event.room_id': 1,
-			'nextEventId': 1,
-			'event.depth': 1,
-			'createdAt': 1,
-		});
-		this.collection.createIndex({
-			'event.room_id': 1,
-			'event.type': 1,
-		});
-	}
+	) {}
+
+	async ensureIndexes(): Promise<void> {
+		await Promise.all([
+			this.collection.createIndex({
+				'event.room_id': 1,
+				'nextEventId': 1,
+				'event.depth': 1,
+				'createdAt': 1,
+			}),
+			this.collection.createIndex({
+				'event.room_id': 1,
+				'event.type': 1,
+			}),
+		]);
+	}

Then call await eventRepository.ensureIndexes() during application bootstrap.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
) {
this.collection.createIndex({
'event.room_id': 1,
'nextEventId': 1,
'event.depth': 1,
'createdAt': 1,
});
this.collection.createIndex({
'event.room_id': 1,
'event.type': 1,
});
}
constructor(
`@inject`('EventCollection')
private readonly collection: Collection<EventStore>,
) {
this.collection.createIndex({
'event.room_id': 1,
'nextEventId': 1,
'event.depth': 1,
'createdAt': 1,
}).catch((err) => console.error('Failed to create event index (room_id, nextEventId, depth, createdAt):', err));
this.collection.createIndex({
'event.room_id': 1,
'event.type': 1,
}).catch((err) => console.error('Failed to create event index (room_id, type):', err));
}
Suggested change
) {
this.collection.createIndex({
'event.room_id': 1,
'nextEventId': 1,
'event.depth': 1,
'createdAt': 1,
});
this.collection.createIndex({
'event.room_id': 1,
'event.type': 1,
});
}
constructor(
`@inject`('EventCollection')
private readonly collection: Collection<EventStore>,
) {}
async ensureIndexes(): Promise<void> {
await Promise.all([
this.collection.createIndex({
'event.room_id': 1,
'nextEventId': 1,
'event.depth': 1,
'createdAt': 1,
}),
this.collection.createIndex({
'event.room_id': 1,
'event.type': 1,
}),
]);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/federation-sdk/src/repositories/event.repository.ts` around lines 12
- 23, The createIndex() calls in the constructor are fire-and-forget which
causes unhandled promise rejections and no startup guarantee; remove the direct
createIndex() calls from the constructor and add an async initialization method
(e.g., ensureIndexes() or init()) on the EventRepository class that awaits each
this.collection.createIndex(...) call (or wraps them in Promise.all), surrounds
them with try/catch to log or rethrow errors, and then call await
eventRepository.ensureIndexes() from app bootstrap so indexes are created before
queries run; alternatively, if you prefer minimal change, at least append
.catch(...) to each this.collection.createIndex(...) in the class to handle
errors and avoid unhandled rejections.


async findById(eventId: EventID): Promise<EventStore | null> {
return this.collection.findOne({ _id: eventId });
Expand Down