Skip to content

rtc: Cache RTC discovery in the MatrixClient - #5470

Merged
BillCarsonFr merged 15 commits into
developfrom
valere/rtc/cache_dicovery
Aug 8, 2026
Merged

rtc: Cache RTC discovery in the MatrixClient#5470
BillCarsonFr merged 15 commits into
developfrom
valere/rtc/cache_dicovery

Conversation

@BillCarsonFr

@BillCarsonFr BillCarsonFr commented Aug 5, 2026

Copy link
Copy Markdown
Member

Allow the matrix-js-sdk to cache the rtc/transport discovery result as it is doing with similar other server side calls (well-known or capabilities)

This would allow the widget driver (in Element-web) to use this cached value instead of fetching every time element-hq/element-web#34393

EW has added it's own caching in CallStore, but I think this should be done in the js-sdk.

This is best reviewed commit by commit?

  • 510824a introduces the cachedValue generic mecanism and use it for transport discovery
  • b965545 Refactors the client to use the same mecanism for well-known (there is a behavior changes, it is getting retry on transient/quota errors)

Checklist

  • Tests written for new code (and old code if feasible).
  • New or updated public/exported symbols have accurate TSDoc documentation.
  • Linter and other CI checks pass.
  • Sign-off given on the changes (see CONTRIBUTING.md).

@BillCarsonFr BillCarsonFr added the T-Task Tasks for the team like planning label Aug 5, 2026
Comment thread src/clientCachedValue.ts Outdated
/**
* Defines a generic mechanism to fetch and cache values for the client.
*/
export abstract class ClientCachedValue<ValueType> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems like more than just caching, it's actively re-fetching on a timer.

Also, I think we are trying to move away from inheritance as a way of getting functionality which I think is considered a bit of an anti-pattern in favour of aggregation, ie. instantiating an object that does the thing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

True, I renamed to ClientPollingCachedValue, it is better but naming is hard.

I also did the refactoring to avoid inheritence, by having a concrete class doing the mecanism and having a factory with configuration option.
This is easier to review commit by commit I think, I am adding the commits for convinience:
6844353 Do the renaming
e08796b The factory refactoring

Comment thread src/clientCachedValue.ts Outdated
* @param TTL The time-to-live in milliseconds.
*/
public setTTLMillis(TTL: number): void {
this.ttlMillis = TTL;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

wouldn't we expect this to update the timeout?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That's true, but given this was always set once and before the start, I moved it as a parameter of the start to avoid this caveat 0e6487c

Comment thread src/pollingCachedValue.ts
return false;
}

private async doFetch(force: boolean = false): Promise<void> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

docs please, it's not clear what 'force' means here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

updated f70d8ca

Comment thread src/clientCachedValue.ts Outdated
this.fetchPromise = this.fetchWithRetryPolicy();

try {
const value = await this.fetchPromise;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why use the value variable rather than just assigning to this.cached?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

done

Comment thread src/pollingCachedValue.ts
if (this.ttlMillis) {
this.ttlTimeoutHandle = setTimeout(() => {
this.fetchPromise = undefined;
void this.doFetch();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This in particular feels like a weird hybrid between periodic updating where you would probably try to refresh the value in advance of it expiring and a cache that expires but is then just repopulated the next time it's needed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agree, I tried to keep it mostly to accomodate the pre-existing well-known behavior that was doing that, so I can refactor both value to use the new mecanism

Comment thread src/clientCachedValue.ts Outdated
try {
await this.doFetch();
} catch (error) {
// Ignore errors, as wait should not throw

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

shouldn't it? what if the value can't be fetched? This feels like something for the function's tsdoc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You are right, I changed it. f20518b

@dbkr dbkr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks, yeah - it's the awkward situation of two things that share very similar logic but not the same.

@BillCarsonFr
BillCarsonFr added this pull request to the merge queue Aug 7, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 7, 2026
@BillCarsonFr

BillCarsonFr commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

The upstream fails because of a test I fixed in this PR https://github.com/element-hq/element-web/pull/34581/changes

The test was accessing a non-public API?
client["clientWellKnown"] = {

Replaced by a spyOn vi.spyOn(client, "getClientWellKnown").mockResolvedValue(wn);

FWIW created an upstream PR resolve the problem element-hq/element-web#34618

@BillCarsonFr
BillCarsonFr added this pull request to the merge queue Aug 8, 2026
Merged via the queue into develop with commit 178dc65 Aug 8, 2026
34 checks passed
@BillCarsonFr
BillCarsonFr deleted the valere/rtc/cache_dicovery branch August 8, 2026 17:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-Task Tasks for the team like planning

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants