Skip to content
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

fix: add cache disabling option #1442

Merged
merged 15 commits into from
Jan 22, 2025
Merged

Conversation

isekovanic
Copy link
Contributor

@isekovanic isekovanic commented Jan 21, 2025

CLA

  • I have signed the Stream CLA (required).
  • Code changes are tested

Description of the changes, What, Why and How?

Fixes the issues mentioned in this Zendesk ticket.

Mainly, this flag is meant to be used for a very niche' usecase of the LLC when it's used purely as a REST API on the backend. The issue boils down to a couple of things:

  • For performance reasons, we often do caching of various heavy operations/entities within the LLC (such as channels, polls and similar) in order to be able to look already seen things quickly
  • This works well in principle, however if used on the backend it can quickly increase the LLC's memory and likely crash any pod it's being run on

As an example - let us say that we have 10000 users and each user has 5 distinct channels (some group ones, maybe some direct messaging channels etc.). The first time one of these users runs queryChannels towards the custom backend (which in turn runs client.queryChannels), the entities will end up in both client.activeChannels and client.configs until the pod is restarted.

On the client side app this works fine because you physically would not be able to query through so many channels given a userId.

Provided below is a quick summary on why it's okay to do this in a REST API setting:

  • The only place where client.activeChannels is being used in this setting is here, the rest are either WS event handlers or state dispatchers (none of which we need given the constraints)
  • The client.configs object is only really used to get a channel configuration in the client-side SDKs, in the case of a REST API they can use the config returned from the HTTP request
  • The pollCache is something we do not need on the server-side, as again we have other ways to get a poll (and it also comes baked in its own messages)

Changelog

Copy link
Contributor

github-actions bot commented Jan 21, 2025

Size Change: +601 B (+0.13%)

Total Size: 467 kB

Filename Size Change
dist/browser.es.js 102 kB +121 B (+0.12%)
dist/browser.full-bundle.min.js 57.3 kB +112 B (+0.2%)
dist/browser.js 103 kB +124 B (+0.12%)
dist/index.es.js 102 kB +121 B (+0.12%)
dist/index.js 103 kB +123 B (+0.12%)

compressed-size-action

src/types.ts Outdated Show resolved Hide resolved
src/client.ts Outdated Show resolved Hide resolved
@MartinCupela
Copy link
Contributor

@isekovanic Is it possible that due to Channel._checkIsInitialized some methods interacting with the BE will not work? (channel.sendEvent, channel.deleteReaction, ...)

@isekovanic
Copy link
Contributor Author

@MartinCupela I would say no, since the channel instances do exist and are returned adequately - it's just the cache that is not being populated - meaning the channel itself should be initialized as it should if they watch() it (which is typically not something done on the BE as far as I know).

I think that might also be out of scope of the constraints we give to the flag, since this is really only meant to be used as a REST API.

What do you think ?

@MartinCupela
Copy link
Contributor

I realized that the check for being initialized is looking into whether the client is running server-side, so should be ok.

@szuperaz
Copy link
Contributor

@isekovanic I think a nice test for this PR would be to run the chat QA tests - the test use both a client-side client and a server-side client as well (code) - but I assume you don't yet have a chat backend set up locally

@isekovanic
Copy link
Contributor Author

I do not, no @szuperaz - would be happy to though

@szuperaz
Copy link
Contributor

szuperaz commented Jan 21, 2025

@isekovanic did you check that we don't add references here: https://github.com/GetStream/stream-chat-js/blob/master/src/client_state.ts#L14-L16 - this is new to me as well, so I might be missing something, but following source code it seems possible that we'll store data even if cache is disabled

src/poll_manager.ts Outdated Show resolved Hide resolved
@szuperaz
Copy link
Contributor

@isekovanic I went through all activeChannels references and checked if we read from them without null checks. I found two places (it's very much possible you can't reach these without WS connection, still, I think it's better to add null checks everywhere):

@MartinCupela
Copy link
Contributor

@isekovanic I think we should also make sure that client.mutedChannels and client.mutedUsers are not populated server-side. WDYT?

@isekovanic
Copy link
Contributor Author

@szuperaz sounds good, will do that !

@MartinCupela saw those too, however they only every updated through WS events, which we consider out of scope for this. I could add the flag for brevity but would prefer to not touch too many of these places at once if you don't mind

@szuperaz
Copy link
Contributor

PR for chat QA test update: https://github.com/GetStream/chat/pull/7890

@@ -296,7 +296,7 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
// set the key
this.key = key;
this.listeners = {};
this.state = new ClientState<StreamChatGenerics>();
this.state = new ClientState<StreamChatGenerics>({ client: this });
Copy link
Contributor

Choose a reason for hiding this comment

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

I am wandering whether it makes sense to even have client.state when the client is initialized with cache disabled. But that would probably be a breaking change right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not necessarily a breaking change, but I guess it's safer this way for now - I guess it's better to have it there in case the client.state is extended at some point with other things so that we don't have to revisit the stuff here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we even have a attribute called state that keeps user cache only 🤦 .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No idea either :D Hadn't fiddled with it before sadly, hence why it took me a while to reverse engineer everything here

@isekovanic isekovanic merged commit 2bfdacd into master Jan 22, 2025
5 checks passed
@isekovanic isekovanic deleted the fix/add-cache-disabling-option branch January 22, 2025 09:59
@github-actions github-actions bot mentioned this pull request Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants