-
Notifications
You must be signed in to change notification settings - Fork 17
feat: stateid for all events and state endpoints #171
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
Changes from 24 commits
38e6b89
110ed72
e72a930
4f9fe79
94364ab
ed08cf9
9a1ec5f
605a3d3
e5ed38b
806e088
1d98f08
6d48d3d
a91cd5e
7deff9b
1eaa2f7
01b8fff
bbba720
aa9034e
3bad914
c461b76
3c44859
b432145
3b31b7e
2675b3a
d2be5a1
00a8e6d
23f2ec1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ import { | |
| type PduForType, | ||
| type PduType, | ||
| PersistentEventFactory, | ||
| getAuthChain, | ||
| } from '@hs/room'; | ||
| import { singleton } from 'tsyringe'; | ||
| import type { z } from 'zod'; | ||
|
|
@@ -679,4 +680,129 @@ export class EventService { | |
| await new Promise((resolve) => setTimeout(resolve, 5000)); | ||
| } | ||
| } | ||
|
|
||
| async getStateIds( | ||
| roomId: string, | ||
| eventId: string, | ||
| ): Promise<{ pdu_ids: string[]; auth_chain_ids: string[] }> { | ||
| try { | ||
| // Ensure the event exists and belongs to the requested room | ||
| const persisted = await this.eventRepository.findById(eventId); | ||
| if (!persisted || persisted.event.room_id !== roomId) { | ||
| throw new Error('M_NOT_FOUND'); | ||
| } | ||
|
|
||
| const state = await this.stateService.findStateAtEvent(eventId); | ||
|
|
||
| const pduIds: string[] = []; | ||
| const authChainIds = new Set<string>(); | ||
|
|
||
| // Get room version for the store | ||
| const roomVersion = await this.stateService.getRoomVersion(roomId); | ||
| if (!roomVersion) { | ||
| throw new Error('Room version not found'); | ||
| } | ||
|
|
||
| // Get the event store | ||
| const store = this.stateService._getStore(roomVersion); | ||
|
|
||
| // Extract state event IDs and collect auth chain IDs | ||
| for (const [, event] of state.entries()) { | ||
| // PersistentEventBase has an eventId getter | ||
| pduIds.push(event.eventId); | ||
| // Get the complete auth chain for this event | ||
| try { | ||
| const authChain = await getAuthChain(event, store); | ||
| for (const authEventId of authChain) { | ||
| authChainIds.add(authEventId); | ||
| } | ||
| } catch (error) { | ||
| this.logger.warn( | ||
| `Failed to get auth chain for event ${event.eventId}:`, | ||
| error, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| pdu_ids: pduIds, | ||
| auth_chain_ids: Array.from(authChainIds), | ||
| }; | ||
| } catch (error) { | ||
| this.logger.error(`Failed to get state IDs for room ${roomId}:`, error); | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| async getState( | ||
| roomId: string, | ||
| eventId: string, | ||
| ): Promise<{ | ||
| pdus: Record<string, unknown>[]; | ||
| auth_chain: Record<string, unknown>[]; | ||
| }> { | ||
| try { | ||
| // Ensure the event exists and belongs to the requested room | ||
| const persisted = await this.eventRepository.findById(eventId); | ||
| if (!persisted || persisted.event.room_id !== roomId) { | ||
| throw new Error('M_NOT_FOUND'); | ||
| } | ||
|
|
||
| let state: Map<string, any>; | ||
|
|
||
| // Get state at a specific event | ||
| state = await this.stateService.findStateAtEvent(eventId); | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| const pdus: Record<string, unknown>[] = []; | ||
| const authChainIds = new Set<string>(); | ||
|
|
||
| // Get room version for the store | ||
| const roomVersion = await this.stateService.getRoomVersion(roomId); | ||
| if (!roomVersion) { | ||
| throw new Error('Room version not found'); | ||
| } | ||
|
|
||
| // Get the event store | ||
| const store = this.stateService._getStore(roomVersion); | ||
| // Extract state event objects and collect auth chain IDs | ||
| for (const [, event] of state.entries()) { | ||
| // PersistentEventBase has an event getter that contains the actual event data | ||
| pdus.push(event.event); | ||
|
|
||
| // Get the complete auth chain for this event | ||
| try { | ||
| const authChain = await getAuthChain(event, store); | ||
| for (const authEventId of authChain) { | ||
| authChainIds.add(authEventId); | ||
| } | ||
| } catch (error) { | ||
| this.logger.warn( | ||
| `Failed to get auth chain for event ${event.eventId}:`, | ||
| error, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| // Fetch the actual auth event objects | ||
| const authChain: Record<string, unknown>[] = []; | ||
| if (authChainIds.size > 0) { | ||
| try { | ||
| const authEvents = await store.getEvents(Array.from(authChainIds)); | ||
| for (const authEvent of authEvents) { | ||
| authChain.push(authEvent.event); | ||
| } | ||
| } catch (error) { | ||
| this.logger.warn('Failed to fetch auth event objects:', error); | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| pdus: pdus, | ||
| auth_chain: authChain, | ||
| }; | ||
| } catch (error) { | ||
| this.logger.error(`Failed to get state for room ${roomId}:`, error); | ||
| throw error; | ||
| } | ||
| } | ||
|
Comment on lines
+684
to
+807
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainMap known errors to Matrix codes for controllers to translate. Throw 🏁 Script executed: #!/bin/bash
# Verify whether StateService or controllers already enforce roomId/eventId matching
rg -nP -C2 'findStateBeforeEvent\\s*\\('
rg -nP -C3 'getState\\(|getStateIds\\(' packages/homeserver/src/controllersLength of output: 145 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo ">>> Searching for findStateBeforeEvent occurrences..."
rg -n --hidden -S 'findStateBeforeEvent' || true
echo ">>> Searching for getStateIds/getState usage in controllers..."
rg -n --hidden -S '\bgetStateIds\b' packages/homeserver/src/controllers || true
rg -n --hidden -S '\bgetState\b' packages/homeserver/src/controllers || true
echo ">>> Searching for Matrix error patterns (M_NOT_FOUND / MatrixError / m.not_found)..."
rg -n --hidden -S 'M_NOT_FOUND|m.not_found|MatrixError' || true
echo ">>> Searching for stateService methods used in event.service.ts (getRoomVersion, _getStore)..."
rg -n --hidden -S '\bgetRoomVersion\b|\b_getStore\b|\bstateService\b' packages/federation-sdk/src || true
echo ">>> If event.service.ts exists, dump lines 650-820 for context..."
if [ -f packages/federation-sdk/src/services/event.service.ts ]; then
sed -n '650,820p' packages/federation-sdk/src/services/event.service.ts
else
echo "file not found: packages/federation-sdk/src/services/event.service.ts"
fiLength of output: 31976 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== packages/homeserver/src/controllers/federation/event.controller.ts ==="
sed -n '1,240p' packages/homeserver/src/controllers/federation/event.controller.ts || true
echo
echo "=== packages/core/src/errors.ts ==="
sed -n '1,240p' packages/core/src/errors.ts || true
echo
echo "=== packages/federation-sdk/src/services/state.service.ts (findStateBeforeEvent area) ==="
sed -n '200,260p' packages/federation-sdk/src/services/state.service.ts || true
echo
echo "=== packages/federation-sdk/src/services/event.service.ts (around getState / getStateIds) ==="
sed -n '680,780p' packages/federation-sdk/src/services/event.service.ts || trueLength of output: 13319 Throw Matrix M_NOT_FOUND for missing events/state
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.