Drop the legacy `X` suffix from `GetMasterX` and `GetReplicaX`. The
presence of the suffix suggests there's a `non-X` version: but in fact
we migrated these away a long time ago, so remove the cognitive
overhead.
As an aside, this additionally helps avoid trip up LLMs that interpret
this as "something to fix".
We were incorrectly not broadcasting status cache updates
inspite of that being an LRU cache.
We were also not doing it for profilesInChannel cache.
Now we fix it by properly checking the invalidationEvent
which is something local to the cache itself rather
than the cache provider.
https://mattermost.atlassian.net/browse/MM-62077
```release-note
NONE
```
This introduces a new entry in the `Main Menu -> About` modal with the hostname of the currently connected websocket. This will be used to aid debugging issues in clustered environments by showing which node in the cluster is servicing requests for a particular websocket.
This information is only visible in self-managed instances. It will not be visible on cloud instances.
We don't clear the Redis cache for every test.
This can cause issues because the cache is shared
across test. We fix that with this PR.
```release-note
NONE
```
And re-order the server initialization (AGAIN).
For the nth time, we found several bugs in the initialization
process.
1. filestore.NewExportFileBackend and filestore.NewFileBackend
depended on license, but the license wasn't even loaded until
later!
2. The `ps.sqlStore.UpdateLicense` call also didn't work
because the license wouldn't get loaded. It only accidentally
worked because of `ps.AddLicenseListener` which would update
the license later on. We remove that.
Ideally, we would have loaded the license first and then
checked for redis client, but it's very difficult to do that.
Reasons are explained in the code comment.
So we just wait until the license is loaded, and simply throw an
error later.
https://mattermost.atlassian.net/browse/MM-61229
```release-note
NONE
```
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
The Store variable was written to _after_ the server
started which was causing the race.
We simply move it to before we start the server.
While we are here, we fix yet another race condition
which was unrelated, but doing it in one sweep. This
was related to the user props access. When a user is updated,
there was 3 ws events that get sent out, 2 were deep-copied
whereas 1 was not. This led to race condition in postgres
binary-param mode where we were trying to set the user props.
https://mattermost.atlassian.net/browse/MM-61700
Tests at very high scale indicates that the iteration
of all connections during websocket broadcast starts
to become a bottleneck.
To optimize this, we move the channelMember cache from
inside web_conn.go to the hubConnectionIndex.
This involves adding a new map keyed by the channelID
and containing all webConns where the user is a member
of that channel. Subsequently, a new method needed to
be added to invalidate the cache which previously
used to happen in web_conn.
And as a last step, we remove the cache from web_conn
to reduce SQL queries to the DB.
https://mattermost.atlassian.net/browse/MM-61130
```release-note
NONE
```
This test actually tested that there is no race
_if_ session pooling is there. But there is no session pooling
any more so this test is irrelevant.
https://mattermost.atlassian.net/browse/MM-61225
```release-note
NONE
```
This originated from https://github.com/mattermost/mattermost/issues/15249.
However, the original idea was discarded https://github.com/mattermost/mattermost/issues/15249#issuecomment-709713065
as being too complicated to implement. Then I had another
idea to implement it just for session objects.
My thinking was that since every single request allocates a new
session struct, it would be good to use a sync.Pool for that.
However, 4 years later, now we know that the primary bottleneck
in app performance comes from websocket event marshalling.
Therefore, while it would be good to do this, it is difficult
to do it correctly (as shown by the numerous racy tests).
Hence, reverting this.
```release-note
NONE
```
We sprinkle a bit of generic magic to refactor a lot
of duplicate code.
To avoid exposing unnecessary code, I duplicated the function
twice. But let me know if you have strong opinions about this.
https://mattermost.atlassian.net/browse/MM-60171
```release-note
NONE
```
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
On user login, we were aggressively clearing the channel member
cache when it wasn't necessary. There is no channel membership
info that is changing on a user login.
Additionally, we fix some more issues with pointer passing
to the cache. It's a known problem that our value passing
style isn't consistent when we fetch items from cache.
Sometimes we pass pointer-to-pointer, sometimes it's just a
pointer. This is also the reason for https://github.com/mattermost/mattermost/pull/27830.
We fix 2 such cases where we passed pointer-to-pointer
but didn't handle the special case inside the cache.
This time, we actually fix it in the app layer instead
of the cache layer and also add a test for good measure.
https://mattermost.atlassian.net/browse/MM-60480
```release-note
NONE
```
Co-authored-by: Mattermost Build <build@mattermost.com>
- Update library version.
- Added MaxFlush delay to help reduce CPU usage.
- Fall back to LRU cache for the caches which use SCAN.
- Added mattermost-redis and running for all api layer
tests in Postgres.
https://mattermost.atlassian.net/browse/MM-59934
```release-note
NONE
```
PR: https://github.com/mattermost/mattermost/pull/27204 fixed the issue
where `invalidateWebConnSessionCacheForUser` was not broadcasted across
the cluster. However, we became too conservative and started to invalidate
the session cache as well.
But the session cache only contains the session details for the user
and the team membership. There is no channel membership related info.
Therefore, we avoid that and improve performance as well.
https://mattermost.atlassian.net/browse/MM-60478
```release-note
NONE
```
Co-authored-by: Mattermost Build <build@mattermost.com>
* Adds status sync to shared channels
To allow for status to be synced, this changes add a new type of
shared channel internal task. This task has its contents pre-fetched
and stored in the `existingMsg` property, and it is keyed with a user
ID besides a channel ID, so it doesn't conflict with channel-driven
synchronization tasks.
All status synchronizations are triggered from the app layer, so there
is no need of watching for new WebSocket events. Although right now
we're only syncing one user status per message, the changes account
for a list of statuses in case we want to batch them in the future.
The feature is gated by a configuration property and can be disabled
independently of the rest of Shared Channels if it's necessary. It is
backwards compatible as well, and should cause no problems with
servers running older Mattermost versions.
* Adds status sync error management and retry
* Adds DisableSharedChannelsStatusSync to the telemetry report
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
We were invalidating the userProfileByIds cache unnecessarily
when it wasn't really needed. It's just that the InvalidateCacheForUser
method wiped off all user related caches, when we just needed to wipe
user-channel related caches.
To fix this, we split the user cache invalidation method into two
and just call the InvalidateChannelCacheForUser method from app/channel.go.
https://mattermost.atlassian.net/browse/MM-59827
```release-note
NONE
```
- We introduce 2 new APIs:
1. Scan: this allows incremental iteration
without blocking the Redis server and is the
recommended way to iterate over keys. With this,
we have entirely removed the need for Keys.
2. RemoveMulti: this allows deletion of multiple
keys in a single operation which optimizes
network round trips.
- While here, we make a small improvement to
GetStatusFromCache, where we remove the shallow
copy which wasn't necessary because we always
serialize the data from the cache.
- We do not use Redis for session cache because of
frequent requests to iterate the entire cache which leads
to a lot of `SCAN` calls.
- Avoid broadcasting status update messages for Redis case.
- Setting cache expiry for status cache
- Removing .Set method altogether to prevent
any chances of setting an item with no expiry.
https://mattermost.atlassian.net/browse/MM-59932
```release-note
NONE
```
Overall, there is no bug here. But opportunities for
improvement.
- Used the maps.Clone function.
- Handled the error while writing to the network.
https://mattermost.atlassian.net/browse/MM-59283
```release-note
NONE
```
* Adds Remote Cluster related API endpoints
New endpoints for the following routes are added:
- Get Remote Clusters at `GET /api/v4/remotecluster`
- Create Remote Cluster at `POST /api/v4/remotecluster`
- Accept Remote Cluster invite at `POST
/api/v4/remotecluster/accept_invite`
- Generate Remote Cluster invite at `POST
/api/v4/remotecluster/{remote_id}/generate_invite`
- Get Remote Cluster at `GET /api/v4/remotecluster/{remote_id}`
- Patch Remote Cluster at `PATCH /api/v4/remotecluster/{remote_id}`
- Delete Remote Cluster at `DELETE /api/v4/remotecluster/{remote_id}`
These endpoints are planned to be used from the system console, and
gated through the `manage_secure_connections` permission.
* Update server/channels/api4/remote_cluster_test.go
Co-authored-by: Doug Lauder <wiggin77@warpmail.net>
* Fix AppError names
---------
Co-authored-by: Doug Lauder <wiggin77@warpmail.net>
Co-authored-by: Mattermost Build <build@mattermost.com>