Fix https://github.com/matrix-org/matrix-public-archive/issues/46
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/71
Summary:
- Changes the "Jump to next activity in room" to actually continue you to the next 100 messages ahead. Previously, it only jumped you to the single next event in the room which meant a lot of backwards overlap each time.
- Jumping this direction will also start your scroll position at the top of the timeline to continue reading seamlessly `?continue=top`
- Adds "Jump to previous activity in room" to the top of the timeline to continue reading the previous part of the conversation.
[1]: There is a caveat with seamless here which is also commented on in the code:
> XXX: This is flawed in the fact that when we go `/messages?dir=b` it could backfill messages which will fill up the response before we perfectly connect and continue from the position they were jumping from before. When `/messages?dir=f` backfills, we won't have this problem anymore because any messages backfilled in the forwards direction would be picked up the same going backwards.
(need forwards fill MSC)
This helps when someone just pastes a room alias on the end of the domain,
- `/#room-alias:server` -> `/r/room-alias:server`
- `/r/#room-alias:server/date/2022/10/27` -> `/r/room-alias:server/date/2022/10/27`
Since these redirects happen on the client, we can't write any e2e tests. Those e2e tests do everything but run client-side JavaScript.
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/107
Part of https://github.com/matrix-org/matrix-public-archive/issues/25
Also does friendly redirects if you don't exactly use the right URL pattern.
For example, if you paste the full room ID with the `!` like `/roomid/!foo:bar`,
it will properly redirect you to `/roomid/foo:bar`. It also does this sort of
thing for URL encoded room ID's and aliases.
Fix https://github.com/matrix-org/matrix-public-archive/issues/25
Page-load with the correct homeserver selected (according to `?homeserver`).
Fix https://github.com/matrix-org/matrix-public-archive/issues/92
Also makes sure that the `?homeserver` is always available somewhere in the list; whether that be in the available homeserver list or the added homeserver list depending on it someone cleared it out or never had it because they visited from someone else's link.
Fix https://github.com/matrix-org/matrix-public-archive/issues/80
```
RethrownError: Unable to fetch rooms from room directory (homeserver=http://localhost:8008/)
searchTerm=, paginationToken=undefined, limit=9
at matrix-public-archive\server\routes\room-directory-routes.js:55:13
--- Original Error ---
Error: HTTP Error Response: 500 Internal Server Error: {"errcode":"M_UNKNOWN","error":"Internal server error"}
URL=http://localhost:8008/_matrix/client/v3/publicRooms?
at checkResponseStatus (matrix-public-archive\server\lib\fetch-endpoint.js:21:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async fetchEndpoint (matrix-public-archive\server\lib\fetch-endpoint.js:38:3)
at async fetchEndpointAsJson (matrix-public-archive\server\lib\fetch-endpoint.js:63:15)
at async fetchPublicRooms (matrix-public-archive\server\lib\matrix-utils\fetch-public-rooms.js:26:26)
at async matrix-public-archive\server\tracing\trace-utilities.js:31:24
at async matrix-public-archive\server\routes\room-directory-routes.js:45:62
```
Regressed in https://github.com/matrix-org/matrix-public-archive/pull/61 where we tried to serve this under `/css/hydrogen-styles.css` but it doesn't work because all of the image and font references in the CSS file expect it to be at the domain root so just reverted back to serving at the root `/`.
This isn't spawning from any previous security issue. Just adding an extra check to help ensure we don't ever regress this in the future.
```
AssertionError [ERR_ASSERTION]: We should not be leaking the `config.matrixAccessToken` to the Hydrogen render function because this will reach the client!
at renderHydrogenToString (matrix-public-archive\server\hydrogen-render\render-hydrogen-to-string.js:24:3)
at renderHydrogenVmRenderScriptToPageHtml (matrix-public-archive\server\hydrogen-render\render-hydrogen-vm-render-script-to-page-html.js:22:36)
at matrix-public-archive\server\routes\room-directory-routes.js:53:28
at processTicksAndRejections (node:internal/process/task_queues:96:5)
```
1. Add surrounding messages to the given messages so we have a full screen of content to make it feel lively even in quiet rooms
- As you scroll around the timeline across different days, the date changes in the URL, calendar, etc
2. Add summary item to the bottom of the timeline that explains if we couldn't find any messages in the specific day requested
- Also allows you to the jump to the next activity in the room. Adds `/:roomId/jump?ts=xxx&dir=[f|b]` to facilitate this.
- Part of https://github.com/matrix-org/matrix-public-archive/issues/46
3. Add developer options modal which is linked from the bottom of the right-panel
- Adds an option so you can debug the `IntersectionObserver` and how it's selecting the active day from the top-edge of the scroll viewport.
- In the future, this will also include a nice little visualization of the backend timing traces
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/36
Render pipeline separation of concerns:
1. Run in `child_process`
2. Hydrogen render
It's now just a generic `child_process` runner that runs the Hydrogen render in it. This eliminates the windy path of the 1-4 steps that was only held together by the file names themselves.
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/51
Better `child_process` error handling for a couple scenarios with the finger pointing at it 👉
Also make sure we handle all of these scenarios:
1. Child process fork script throws an `uncaughtException` or `unhandledRejection`
- These are captured and serialized back to the parent and stored in `childErrors` and exposed if we never get a successful rendered HTML response.
2. Child process fails to startup
- Render process is rejected in the `child.on('error', ...` callback
3. 👉 Child process times out and is aborted
- Render process is rejected in the `child.on('error', ...` callback and any `childErrors` encountered are logged
4. 👉 Child process fork script throws an error in scope of in `process.on('message', async (renderOptions) => {`
- Child exits with code 1 and we reject the render process with the error
5. Child process exits with code 1 (error)
- Render process is rejected with any `childError` info
6. Child process exits with code 0 (success) but never sends back any HTML
- We have a `returnedData` data check and any child errors encountered are logged
Add test to make sure the archive doesn't fail when event for event relation is missing and not included in list of provided events. Like if someone is replying to an event that was from long ago out of our range.
In the case of missing relations, Hydrogen does `_loadContextEntryNotInTimeline` because it can't find the event locally which throws an `uncaughtException`. Before https://github.com/matrix-org/matrix-public-archive/pull/51, the `uncaughtException` killed the Hydrogen `child_process` before it could pass back the HTML. Now this PR mainly just adds a test to make sure it works.
```
TypeError: Cannot read properties of undefined (reading 'storeNames')
at TimelineReader.readById (hydrogen-web\target\lib-build\hydrogen.cjs.js:12483:33)
at Timeline._getEventFromStorage (hydrogen-web\target\lib-build\hydrogen.cjs.js:12762:46)
at Timeline._loadContextEntryNotInTimeline (hydrogen-web\target\lib-build\hydrogen.cjs.js:12747:35)
at Timeline._loadContextEntriesWhereNeeded (hydrogen-web\target\lib-build\hydrogen.cjs.js:12741:14)
at Timeline.addEntries (hydrogen-web\target\lib-build\hydrogen.cjs.js:12699:10)
at mountHydrogen (4-hydrogen-vm-render-script.js:204:12)
at 4-hydrogen-vm-render-script.js:353:1
at Script.runInContext (node:vm:139:12)
at _renderHydrogenToStringUnsafe (matrix-public-archive\server\hydrogen-render\3-render-hydrogen-to-string-unsafe.js:102:41)
at async process.<anonymous> (matrix-public-archive\server\hydrogen-render\2-render-hydrogen-to-string-fork-script.js:18:27)
```
Split off from https://github.com/matrix-org/matrix-public-archive/pull/43
Listen to `process.on('uncaughtException', ...)` and handle the async errors ourselves so it no longer fails the child process.
And if the process does exit with status code 1 (error), we have those underlying errors serialized and shown.
OpenTelemetry tracing so we can see spans where the app is taking time.
For the user, we specifically show the spans for the external API HTTP requests
that are slow (so we know when the Matrix API is being slow).
Enable tracing:
- `npm run start -- --tracing`
- `npm run start-dev -- --tracing`
What does this PR change:
- Adds OpenTelemetry tracing with some of the automatic instrumentation (includes HTTP and express)
- We ignore traces for serving static assets (just noise)
- Adds `X-Trace-Id` to the response headers
- Adds `window.tracingSpansForRequest` which includes the external HTTP API requests made during the request
- Adds a fancy 504 timeout page that includes trace details and lists the slow HTTP requests
- Adds `jaegerTracesEndpoint` configuration to export tracing spans to Jaeger
- Related to, https://github.com/matrix-org/matrix-public-archive/issues/26
We now run the Hydrogen render in a `child_process` so we can exit the whole render process. We still use the `vm` to setup the browser-like globals. With a `vm`, everything continues to run even after it returns and there isn't a way to clean up, stop, kill, terminate the vm script or context so we need this extra `child_process` now to clean up. I don't like the complexity necessary for this though. I wish the `vm` API allowed for this use case. The only way to stop a `vm` is the `timeout` and we want to stop as soon as we return.
Fix https://github.com/matrix-org/matrix-public-archive/issues/34
`renderHydrogenToString` is a pure function (probably) which means it will give the same output given the same input. This means, that if we give it a certain input and an error occurs, we should be able to reproduce it again if we have the arguments. This PR exposes those arguments in the logged error so we can investigate what's going wrong.
Added so we can investigate https://github.com/matrix-org/matrix-public-archive/issues/34 better and reproduce locally.
Remove `matrix-bot-sdk` usage in tests because it didn't have timestamp massaging `?ts` and it's not really necessary to rely on since we can just call the API directly 🤷. `matrix-bot-sdk` is also very annoying having to build rust crypto packages.
We're now using direct `fetch` requests against the Matrix API and lightweight `client` object.
All 3 current tests pass ✅
Get this project running again after a few months of changes
from `hydrogen-view-sdk` and now finally after
https://github.com/vector-im/hydrogen-web/pull/693
merged to make the SDK friendly to locally link and develop on.
Because we had to update the `assets` `export` to avoid the following deprecation warning:
```
(node:133896) [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./assets/" in the "exports" field module resolution of the package at C:\Users\MLM\Documents\GitHub\element\matrix-public-archive\node_modules\hydrogen-view-sdk\package.json.
Update this package.json to use a subpath pattern like "./assets/*".
(Use `node --trace-deprecation ...` to show where the warning was created)
```
`hydrogen-view-sdk` `package.json` before:
```json
{
"exports": {
".": {
"import": "./lib-build/hydrogen.es.js",
"require": "./lib-build/hydrogen.cjs.js"
},
"./paths/vite": "./paths/vite.js",
"./style.css": "./style.css",
"./assets/": "./asset-build/assets/"
}
}
```
`hydrogen-view-sdk` `package.json` after:
```json
{
"exports": {
".": {
"import": "./lib-build/hydrogen.es.js",
"require": "./lib-build/hydrogen.cjs.js"
},
"./paths/vite": "./paths/vite.js",
"./style.css": "./style.css",
"./assets/*": "./asset-build/assets/*"
}
}
```