Граф коммитов

82 Коммитов

Автор SHA1 Сообщение Дата
Agniva De Sarker
ce9d5d77bb MM-50435: Improve data retention queries on MySQL (#22304)
For some queries MySQL performed poorly until we slightly
tune the query. Here are the results:

Old query
```
// 5.7
mysql> explain SELECT Posts.Id FROM Posts LEFT JOIN Channels ON Posts.ChannelId = Channels.Id WHERE Channels.Id IS NULL LIMIT 3000;
+----+-------------+----------+------------+--------+---------------+--------------------------------+---------+----------------------------+---------+----------+--------------------------------------+
| id | select_type | table    | partitions | type   | possible_keys | key                            | key_len | ref                        | rows    | filtered | Extra                                |
+----+-------------+----------+------------+--------+---------------+--------------------------------+---------+----------------------------+---------+----------+--------------------------------------+
|  1 | SIMPLE      | Posts    | NULL       | index  | NULL          | idx_posts_channel_id_update_at | 116     | NULL                       | 6439997 |   100.00 | Using index                          |
|  1 | SIMPLE      | Channels | NULL       | eq_ref | PRIMARY       | PRIMARY                        | 106     | mattermost.Posts.ChannelId |       1 |   100.00 | Using where; Not exists; Using index |
+----+-------------+----------+------------+--------+---------------+--------------------------------+---------+----------------------------+---------+----------+--------------------------------------+
2 rows in set, 1 warning (0.16 sec)

// 8.0
| -> Limit: 3000 row(s)  (cost=13321292.71 rows=3000) (actual time=14291.753..14291.753 rows=0 loops=1)
    -> Filter: (Channels.Id is null)  (cost=13321292.71 rows=10895918) (actual time=14291.751..14291.751 rows=0 loops=1)
        -> Nested loop antijoin  (cost=13321292.71 rows=10895918) (actual time=14291.749..14291.749 rows=0 loops=1)
            -> Covering index scan on Posts using idx_posts_channel_id_update_at  (cost=1337847.05 rows=10895918) (actual time=6.258..10928.120 rows=11824842 loops=1)
            -> Single-row covering index lookup on Channels using PRIMARY (Id=Posts.ChannelId)  (cost=1.00 rows=1) (actual time=0.000..0.000 rows=1 loops=11824842)
```

New query
```
// 5.7
mysql> EXPLAIN SELECT Posts.Id FROM Posts WHERE Posts.ChannelId NOT IN (SELECT Id FROM Channels) LIMIT 3000;
+----+-------------+----------+------------+-------+---------------+--------------------------------+---------+------+---------+----------+--------------------------+
| id | select_type | table    | partitions | type  | possible_keys | key                            | key_len | ref  | rows    | filtered | Extra                    |
+----+-------------+----------+------------+-------+---------------+--------------------------------+---------+------+---------+----------+--------------------------+
|  1 | PRIMARY     | Posts    | NULL       | index | NULL          | idx_posts_channel_id_update_at | 116     | NULL | 6440001 |   100.00 | Using where; Using index |
|  2 | SUBQUERY    | Channels | NULL       | index | PRIMARY       | idx_channels_update_at         | 9       | NULL |   60964 |   100.00 | Using index              |
+----+-------------+----------+------------+-------+---------------+--------------------------------+---------+------+---------+----------+--------------------------+
2 rows in set, 1 warning (0.17 sec)

// 8.0
| -> Limit: 3000 row(s)  (cost=1337847.05 rows=3000) (actual time=8309.610..8309.610 rows=0 loops=1)
    -> Filter: <in_optimizer>(Posts.ChannelId,Posts.ChannelId in (select #2) is false)  (cost=1337847.05 rows=10895918) (actual time=8309.609..8309.609 rows=0 loops=1)
        -> Covering index scan on Posts using idx_posts_channel_id_update_at  (cost=1337847.05 rows=10895918) (actual time=0.127..2938.252 rows=11824842 loops=1)
        -> Select #2 (subquery in condition; run only once)
            -> Filter: ((Posts.ChannelId = `<materialized_subquery>`.Id))  (cost=57224.17..57224.17 rows=1) (actual time=0.014..0.014 rows=1 loops=136308)
                -> Limit: 1 row(s)  (cost=57224.07..57224.07 rows=1) (actual time=0.013..0.013 rows=1 loops=136308)
                    -> Index lookup on <materialized_subquery> using <auto_distinct_key> (Id=Posts.ChannelId)  (actual time=0.013..0.013 rows=1 loops=136308)
                        -> Materialize with deduplication  (cost=57224.07..57224.07 rows=266638) (actual time=1361.488..1361.488 rows=270959 loops=1)
                            -> Covering index scan on Channels using idx_channels_update_at  (cost=30560.27 rows=266638) (actual time=1.807..264.116 rows=270959 loops=1)
```

We can see that in the base case, MySQL does an anitjoin which is actually fine in most queries
but in this query we are selecting posts.Id, but joining on posts.channelid. In such a case, if we use a nested query,
suddenly MySQL can materialize the sub-query and do only a covering index scan on Posts. Also compare the costs.
Old one has 13321292.71 whereas new one has 1337847.05. So an order of magnitude improvement.

Old query
```
 Limit  (cost=6561.27..655145.99 rows=1 width=27) (actual time=3897.766..3902.683 rows=0 loops=1)
   ->  Gather  (cost=6561.27..655145.99 rows=1 width=27) (actual time=3702.143..3707.058 rows=0 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Parallel Hash Anti Join  (cost=5561.27..654145.89 rows=1 width=27) (actual time=3631.030..3631.032 rows=0 loops=3)
               Hash Cond: ((posts.channelid)::text = (channels.id)::text)
               ->  Parallel Seq Scan on posts  (cost=0.00..627918.55 rows=5510955 width=54) (actual time=0.719..2701.470 rows=4410848 loops=3)
               ->  Parallel Hash  (cost=4874.45..4874.45 rows=54945 width=27) (actual time=193.211..193.212 rows=43956 loops=3)
                     Buckets: 262144  Batches: 1  Memory Usage: 10368kB
                     ->  Parallel Seq Scan on channels  (cost=0.00..4874.45 rows=54945 width=27) (actual time=105.575..146.071 rows=43956 loops=3)
 Planning Time: 41.365 ms
 JIT:
   Functions: 31
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 11.106 ms, Inlining 237.381 ms, Optimization 169.412 ms, Emission 103.889 ms, Total 521.787 ms
 Execution Time: 4297.552 ms
```

New query
```
 Limit  (cost=1000.00..9419975.49 rows=3000 width=27)
   ->  Gather  (cost=1000.00..20761674119.53 rows=6612717 width=27)
         Workers Planned: 2
         ->  Parallel Seq Scan on posts  (cost=0.00..20761011847.83 rows=2755299 width=27)
               Filter: (NOT (SubPlan 1))
               SubPlan 1
                 ->  Materialize  (cost=0.00..7205.04 rows=131869 width=27)
                       ->  Seq Scan on channels  (cost=0.00..5643.69 rows=131869 width=27)
 JIT:
   Functions: 9
   Options: Inlining true, Optimization true, Expressions true, Deforming true
(11 rows)
```

Note: this was so bad, I couldn't even wait to finish EXPLAIN ANALYZE as it was taking more than
10 minutes to finish.

Old query
```
EXPLAIN ANALYZE SELECT Threads.PostId FROM Threads LEFT JOIN Channels ON Threads.ChannelId = Channels.Id WHERE Channels.Id IS NULL LIMIT 3000;
// 8.0
------------------+
| -> Limit: 3000 row(s)  (cost=727387.95 rows=3000) (actual time=725.905..725.905 rows=0 loops=1)
    -> Filter: (Channels.Id is null)  (cost=727387.95 rows=807045) (actual time=725.903..725.903 rows=0 loops=1)
        -> Nested loop antijoin  (cost=727387.95 rows=807045) (actual time=725.901..725.901 rows=0 loops=1)
            -> Covering index scan on Threads using idx_threads_channel_id_last_reply_at  (cost=92668.15 rows=807045) (actual time=0.201..214.332 rows=846313 loops=1)
            -> Single-row covering index lookup on Channels using PRIMARY (Id=Threads.ChannelId)  (cost=0.69 rows=1) (actual time=0.001..0.001 rows=1 loops=846313)
 |
```

New query
```
// 8.0
mysql> EXPLAIN ANALYZE  SELECT Threads.PostId FROM Threads WHERE Threads.ChannelId NOT IN (SELECT Id FROM Channels) LIMIT 3000;
 -> Limit: 3000 row(s)  (cost=92668.15 rows=3000) (actual time=1770.798..1770.798 rows=0 loops=1)
    -> Filter: <in_optimizer>(Threads.ChannelId,Threads.ChannelId in (select #2) is false)  (cost=92668.15 rows=807045) (actual time=1770.796..1770.796 rows=0 loops=1)
        -> Covering index scan on Threads using idx_threads_channel_id_last_reply_at  (cost=92668.15 rows=807045) (actual time=0.191..197.768 rows=846313 loops=1)
        -> Select #2 (subquery in condition; run only once)
            -> Filter: ((Threads.ChannelId = `<materialized_subquery>`.Id))  (cost=56081.83..56081.83 rows=1) (actual time=0.011..0.011 rows=1 loops=114202)
                -> Limit: 1 row(s)  (cost=56081.73..56081.73 rows=1) (actual time=0.011..0.011 rows=1 loops=114202)
                    -> Index lookup on <materialized_subquery> using <auto_distinct_key> (Id=Threads.ChannelId)  (actual time=0.011..0.011 rows=1 loops=114202)
                        -> Materialize with deduplication  (cost=56081.73..56081.73 rows=266638) (actual time=901.592..901.592 rows=270959 loops=1)
                            -> Covering index scan on Channels using idx_channels_update_at  (cost=29417.93 rows=266638) (actual time=0.129..57.806 rows=270959 loops=1)
 |
```

I did not test this query in Community but I expect the same logic to happen. Again, notice
the improvement in cost. 727387.95 vs 727387.95

Old query
```
EXPLAIN ANALYZE SELECT Threads.PostId FROM Threads LEFT JOIN Channels ON Threads.ChannelId = Channels.Id WHERE Channels.Id IS NULL LIMIT 3000;
 Limit  (cost=6561.27..74898.36 rows=1 width=27) (actual time=628.141..630.437 rows=0 loops=1)
   ->  Gather  (cost=6561.27..74898.36 rows=1 width=27) (actual time=628.138..630.433 rows=0 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Parallel Hash Anti Join  (cost=5561.27..73898.26 rows=1 width=27) (actual time=612.672..612.674 rows=0 loops=3)
               Hash Cond: ((threads.channelid)::text = (channels.id)::text)
               ->  Parallel Seq Scan on threads  (cost=0.00..66852.00 rows=396000 width=54) (actual time=0.308..505.021 rows=315151 loops=3)
               ->  Parallel Hash  (cost=4874.45..4874.45 rows=54945 width=27) (actual time=21.031..21.031 rows=43956 loops=3)
                     Buckets: 262144  Batches: 1  Memory Usage: 10336kB
                     ->  Parallel Seq Scan on channels  (cost=0.00..4874.45 rows=54945 width=27) (actual time=0.018..7.959 rows=43956 loops=3)
```

New query
```
[bigdb] # EXPLAIN   SELECT Threads.PostId FROM Threads WHERE Threads.ChannelId NOT IN (SELECT Id FROM Channels) LIMIT 3000;
                                        QUERY PLAN
-------------------------------------------------------------------------------------------
 Limit  (cost=1000.00..9420102.76 rows=3000 width=27)
   ->  Gather  (cost=1000.00..1491986877.26 rows=475200 width=27)
         Workers Planned: 2
         ->  Parallel Seq Scan on threads  (cost=0.00..1491938357.26 rows=198000 width=27)
               Filter: (NOT (SubPlan 1))
               SubPlan 1
                 ->  Materialize  (cost=0.00..7205.04 rows=131869 width=27)
                       ->  Seq Scan on channels  (cost=0.00..5643.69 rows=131869 width=27)
 JIT:
   Functions: 9
   Options: Inlining true, Optimization true, Expressions true, Deforming true
```

As expected, Postgres behaves correctly in the original query.

https://mattermost.atlassian.net/browse/MM-50435

```release-note
NONE
```
2023-02-13 20:33:45 +05:30
Anurag Shivarathri
6a93d46556 [MM-48010] Fetch Threads since parameter should return threads with new replies. (#22228)
* Fix

* Test fix and condition is GtOrEq
2023-02-03 19:50:10 +05:30
Agniva De Sarker
079f752478 MM-49546: Sentry crash: fix nil pointer dereference (#22018)
We return a store error always to be handled correctly
at the app layer.

https://mattermost.atlassian.net/browse/MM-49546

```release-note
NONE
```

Co-authored-by: Mattermost Build <build@mattermost.com>
2023-01-09 22:25:29 +05:30
Kyriakos Z
c44d37629a MM-46410: adds urgency on mention counts (#20999)
* MM-46410: adds urgency on mention counts

We have introduced priority for posts in
https://github.com/mattermost/mattermost-webapp/pull/10951.
We do need to color the mention badges in the webapp with a prominent
color when a mention is posted in an urgent message.
A thread has urgent mentions if the root post is marked as urgent, and
the replies contain mentions to the user viewing the thread.

This PR adds a column, urgentmentioncount, in channelmembers.
Furthermore when asking for team/thread mention counts, we also return
urgent mention counts for the user.

Adds a new table to hold posts priorities
Refactors priority out of the props and into the new table

We are nilifying Metadata when post.ForPlugin(), which didn't save Priority
for a post when Boards was enabled.
This commit copies metadata again to the post, so metadata are
reinstated.

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Vishal Choudhary <vish9812@gmail.com>
2022-11-23 21:08:21 +02:00
Shota Gvinepadze
98e685f07c Move Thread.GetPosts to PostStore.GetPostsByThread (#21633)
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-11-16 13:42:26 +04:00
Shota Gvinepadze
44dd185506 Fix bad merge (#21632) 2022-11-10 11:30:49 +04:00
Jesse Hallam
5a0a3e6d13 Inline ThreadStore.MarkAllAsUnreadByTeam (#20958)
* Add teamId to Threads table

* Get rid of multiple teamId reads

* Fix failed test

* Inline ThreadStore.MarkAllAsUnreadByTeam

The query to `MarkAllAsUnreadByTeam` first fetched all thread memberships, then fed just the ids back to a second query to ensure all are marked as unread. Optimize this by simply doing a single `UPDATE` query with the necessary joins.

Co-authored-by: iomodo <wineson@gmail.com>
2022-11-09 14:00:07 -04:00
Shota Gvinepadze
b9d00a1f28 Simplify thread_store/GetThreadForUser (#21588) 2022-11-09 12:16:20 +04:00
Jesse Hallam
279754c6b0 Refactor common JoinThread helper struct (#21511)
* Refactor common JoinThread helper struct

* avoid exporting ToThreadResponse
2022-11-04 12:05:59 -03:00
Shota Gvinepadze
96c8dc1281 [MM-45868] Replace TeamId column with ThreadTeamId (#21505)
* Replace TeamId column with TreadTeamId

* make migrations-extract
2022-10-26 19:50:37 +04:00
Shota Gvinepadze
fab9d350c7 [MM-45868] Add teamId to Threads table (#20915)
* Add teamId to Threads table

* Get rid of multiple teamId reads

* Fix failed test

* Add teamId to standard queries

* Fix linter

* Get teamId from db
2022-10-24 16:10:27 +04:00
Tim Scheuermann
eb37139f16 MM-45994 ensure database operations return their errors (#20857) 2022-08-26 11:12:59 +02:00
Ibrahim Serdar Acikgoz
717a4d04a9 Use any instead of interface{} (#20577)
* replace interface{} with any
2022-07-05 09:46:50 +03:00
Shivashis Padhi
2cd83d2f8d [MM-44084] Feature: Top threads insights (#20195)
* Add route endpoints, model, store functions, and tests for top threads

* Run make store-layers

* Make the following changes

 - Fix top user threads query
 - Fix passing parameters in api4/insights.go to handler in app
 - Add top user threads test

* Add post-message, user_id, participants information to insights results

* model.TopThread.UserID -> model.TopThread.UserId, for compatibility with MySQL

* Rename name -> channel_name

* Add user information to response

* Link post in response, filter out deleted root posts from top threads

* Handle thread delete cases, add app tests for threads insights

* lint: fix typo

* lint: rename asserts

* lint: require.nil -> require.NoError

* Add integration tests for thread insights

* Add embeds and images to top posts

* Add license checks for top threads endpoints

* Query users in batch to populate post-creator

* Make the following changes

 - Add license to test server in api4/
 - Add tests for threads insights
    - top team threads shouldn't include threads from other teams, DMs
    - Test duration constraint
    - Pagination testing for top threads in model/insights_test.go

* Add i18n-extract

* i18n fixes

* Add username, nickname to user_information

* Hide message, user_id, post_id, reply_count in depth=1 of top threads response

* Fix tests using response.reply_count to use response.post.reply_count

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-06-20 10:27:17 -04:00
Jesse Hallam
9c851e996c Introduce (Get|Select|Exec)Builder (#20029) 2022-05-16 14:48:21 -03:00
Jesse Hallam
a4ad6eda5d s/masterminds/mattermost for squirrel (#20162)
Our fork of https://github.com/Masterminds/squirrel at https://github.com/mattermost/squirrel (previously https://github.com/lieut-data/squirrel) isn't compatible with the upstream project, and causes issues for repositories importing mattermost-server and using squirrel.

Sidestep this by adopting the `mattermost/squirrel` fork explicitly.  (Downstream repos can either switch, or keep using the upstream version from `Masterminds`.)
2022-05-10 11:48:59 -03:00
Jesse Hallam
72a5d99ae3 MM-43770: Rename to Threads.ThreadDeleteAt (#20074)
Old versions of the Mattermost server did not qualify queries scanning both `Posts` and `Threads`, and choke on the ambiguity in deciding between the new `DeleteAt` on `Threads` and the `DeleteAt` on `Posts` in existing queries.

While this problem is transient only while running multiple server versions, it effectively makes our backwards compatibility guarantee void, not to mention complicating cloud deployments.

Work around this by renaming `Threads.DeleteAt` to `Threads.ThreadDeleteAt`. The old migration is nulled out, but remains, since some test servers have already upgraded and manually fixing each affected instance would be problematic. Thew new migration takes care of removing the old column -- if it ever existed.

Fixes: https://mattermost.atlassian.net/browse/MM-43770

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-04-29 14:42:38 -03:00
Jesse Hallam
5bd223c836 MM-43045: minimize JOIN Posts (#19934) 2022-04-19 17:06:31 -03:00
Michel Engelen
ca8aea9a06 [MM-41993]: fixed counting thread mentions in unread root post (#19874)
* removed appending the root post to the posts list

also changed `UpdateAt` to `CreateAt` in thread_store.go in accordance with kyriakos

* fixed failing test after latest change

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-04-11 12:43:14 -04:00
Jesse Hallam
3016fa6010 MM-42919: avoid sequential scan on Posts (#19878)
On Postgres, `GetTeamsUnreadForUser` triggers a sequential scan on `Posts`. We can avoid this by querying the `Threads` table directly and only joining to `Posts` to eliminate deleted threads. (We could avoid the latter if we later denormalize `DeleteAt` onto `Threads`.)

Fixes: https://mattermost.atlassian.net/browse/MM-42919
2022-04-06 09:21:01 -03:00
Jesse Hallam
7b5ac343f0 adopt forked squirrel supporting from UPDATE FROM (#19896)
Fork https://github.com/Masterminds/squirrel as https://github.com/lieut-data/squirrel with the following changes:
* https://github.com/Masterminds/squirrel/pull/256 supporting FROM clause to update builder (Postgres)
* Extension of above to support multiple FROM in UPDATE (Postgres)
* Support for multiple tables in UPDATE (MySQL)

This PR then leverages those changes to simplify a query that previously had to be coded by hand and duplicate for each of MySQL and Postgres.
2022-04-04 09:30:59 -03:00
Jesse Hallam
47c44a9b7d break up getThreadsForUser, leverage errgroup (#19709)
* MM-42282: handle teamId parameter correctly

As per https://community-daily.mattermost.com/core/pl/ugs7ue6e4j8a7cgegk1bxje8to, `ThreadStore.GetThreadsForUser` accepts a `teamId` parameter, but incorrectly handles an empty value of `""` as looking only for channels with an empty `teamId` (aka DMs and GMs) instead of finding all channels and effectively ignoring the team property.

Fixes: https://mattermost.atlassian.net/browse/MM-42282

* break up getThreadsForUser, leverage errgroup

This change breaks up `GetThreadsForUser` in the `ThreadStore` into its constituent `GetTotalUnreadThreads`, `GetTotalThreads`, `GetTotalUnreadMentions`, and the original `GetThreadsForUser` but now solely returning the thread structures. Instead of a monolithic method at the store level, the application layer now handles calling bulk requests, leveraging `errgroup` for simpler parallelization.

This change brings with it a few benefits:
* Simpler code, including more idiomatic usage of squirrel
* Simpler SQL, joining tables only when configured conditions require same. (No performance benefit here, since an unused LEFT JOIN generally has no overhead.)
* Discrete Grafana metrics for each store method, giving us better insight into the performance characteristics in play.
* **Performance boost**: reduced overhead when clearing push notifications.

This last point is what prompted the re-re-reactoring in this PR. As I broke things up, I realized that `clearPushNotificationSync` only used the `TotalUnreadMentions`, but asked for the count of total threads and total unread threads. By exposing the discrete methods, this code path avoids two aggregate queries. We clear notifications when marking a thread as read, and when marking a channel with unread mentions as viewed, so I expect we'll see at least a modest boost to performance from simply not wasting these cycles anymore.

No performance improvements are expected from this PR for the general case of using `GetThreadsForUser` to populate the threads view.

* never discard errors from building queries

* no MustSql

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-03-15 10:29:00 -03:00
Jesse Hallam
b5e78a0ce1 MM-42282: handle teamId parameter correctly (#19685)
As per https://community-daily.mattermost.com/core/pl/ugs7ue6e4j8a7cgegk1bxje8to, `ThreadStore.GetThreadsForUser` accepts a `teamId` parameter, but incorrectly handles an empty value of `""` as looking only for channels with an empty `teamId` (aka DMs and GMs) instead of finding all channels and effectively ignoring the team property.

Fixes: https://mattermost.atlassian.net/browse/MM-42282
2022-03-11 10:57:42 -04:00
Jesse Hallam
f5b5a3c746 MM-40302: CRT, fix performance of MarkAllAsReadInChannels (#19566)
* deadcode: remove UpdateChannelLastViewedAt

* deadcode: remove ThreadStore.(Save(Multiple)|Update|Delete)

* deadcode: followThead in App.MarkChannelAsUnreadFromPost

* document ThreadMembership, Thread structs

* maintain LastUpdated consistently

Whenever we touch a `ThreadMembership` record, we should be setting `LastUpdated` to the current timestamp. The mobile client relies on this to detect changes to these records.

* simplify: never updateThreads from `App.MarkChannelAsUnreadFromPost`

Change all invocations of `ChannelStore.UpdateLastViewedAtPost` from `App.MarkChannelAsUnreadFromPost` to pass `updateThreads` as `false`. When `ChannelStore.UpdateLastViewedAtPost` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `LastViewed`).

The overall CRT feature continued to work, because `App.MarkChannelAsUnreadFromPost` directly updates the relevant thread memberships via `ThreadStore.MaintainMembership`.

* deadcode: updateThreads in ChannelStore.UpdateLastViewedAtPost

* simplify: never updateThreads from App.SendNotifications

Change all invocations of `ChannelStore.IncrementMentionCount` from
`App.SendNotifications` to pass `updateThreads` as `false`. When `ChannelStore.IncrementMentionCount` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `UnreadMentions`).

The overall CRT feature continued to work, because `App.SendNotifications` directly updates the relevant thread memberships mention counts via `ThreadStore.MaintainMembership`.

* deadcode: updateThreads in ChannelStore.IncrementMentionCount

* fix & rename ThreadStore.UpdateUnreadsByChannel

Rename `ThreadStore.UpdateUnreadsByChannel` to `ThreadStore.UpdateLastViewedByThreadIds`, making it unconditionally set the `LastViewed` for the given threads (as well as `LastUpdated`).

All previous invocations of this method that passed `updateViewedTimestamp` have been previously removed.

* unrelated gofmt -w -s changes to satisfy linter

* always set LastUpdated to model.GetMillis()

* deadcode: ThreadStore.SaveMembership

* fix TestMarkUnreadWithThreads

* MM-40302: CRT, use updateThreads param vs. MarkAllAsReadInChannels

`MarkAllAsReadInChannels` was the subject of a significant performance regression in v5.37 and is known to be very inefficient, by virtue of always writing to an ever increasing number of rows, and doing so on common events like simply viewing a channel.

Fortunately, `ChannelStore.UpdateLastViewedAt` already supported an `updateThreads` parameter that implemented the start of an improved algorithm: query the set of threads with newer posts, and then update only /those/. Missing was the need to reset the `UnreadMentions`, but thanks to the previous simplifications in #19523, we can make this change largely without impacting other semantics.

Fixes: https://mattermost.atlassian.net/browse/MM-40302

* fix MySQL

* remove another JOIN

* remove outdated comment

* unit tests
2022-03-06 19:55:59 -04:00
Jesse Hallam
6757edc4e2 MM-41349: CRT, fix LastUpdated semantics (#19523)
* deadcode: remove UpdateChannelLastViewedAt

* deadcode: remove ThreadStore.(Save(Multiple)|Update|Delete)

* deadcode: followThead in App.MarkChannelAsUnreadFromPost

* document ThreadMembership, Thread structs

* maintain LastUpdated consistently

Whenever we touch a `ThreadMembership` record, we should be setting `LastUpdated` to the current timestamp. The mobile client relies on this to detect changes to these records.

* simplify: never updateThreads from `App.MarkChannelAsUnreadFromPost`

Change all invocations of `ChannelStore.UpdateLastViewedAtPost` from `App.MarkChannelAsUnreadFromPost` to pass `updateThreads` as `false`. When `ChannelStore.UpdateLastViewedAtPost` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `LastViewed`).

The overall CRT feature continued to work, because `App.MarkChannelAsUnreadFromPost` directly updates the relevant thread memberships via `ThreadStore.MaintainMembership`.

* deadcode: updateThreads in ChannelStore.UpdateLastViewedAtPost

* simplify: never updateThreads from App.SendNotifications

Change all invocations of `ChannelStore.IncrementMentionCount` from
`App.SendNotifications` to pass `updateThreads` as `false`. When `ChannelStore.IncrementMentionCount` was invoked with `updateThreads` as `true`, it would in turn call `ThreadStore.UpdateUnreadsByChannel` but pass `updateViewedTimestamp` as `false`. This effectively updated the `LastUpdated` field of the corresponding thread memberships but never touched any of the actual data (such as `UnreadMentions`).

The overall CRT feature continued to work, because `App.SendNotifications` directly updates the relevant thread memberships mention counts via `ThreadStore.MaintainMembership`.

* deadcode: updateThreads in ChannelStore.IncrementMentionCount

* fix & rename ThreadStore.UpdateUnreadsByChannel

Rename `ThreadStore.UpdateUnreadsByChannel` to `ThreadStore.UpdateLastViewedByThreadIds`, making it unconditionally set the `LastViewed` for the given threads (as well as `LastUpdated`).

All previous invocations of this method that passed `updateViewedTimestamp` have been previously removed.

* unrelated gofmt -w -s changes to satisfy linter

* always set LastUpdated to model.GetMillis()

* deadcode: ThreadStore.SaveMembership

* fix TestMarkUnreadWithThreads

* GetMasterX
2022-02-28 16:24:34 -04:00
Agniva De Sarker
6898b3d70f Optimize TeamsUnread (#19507)
The GetTeamsUnreadForUser call would be called for every team switch.
In CRT mode, it would make a separate store call for every team, which
would run the 3 aggregate SQL queries in GetThreadsForUser.

This is suboptimal because the complexity is linearly proportional
to the number of teams.

We make the following optimizations:
1. Change the query to a single one which aggregates all teams.
2. The query originally used just 2 out of the 3 queries, so one
query was fully redundant. We remove that query in the new one.
3. Further analysis was done whether it makes sense to run the 2
queries synchronously or not. The load-tests didn't show any degradation
in running them concurrently, so we keep the same behavior.

```release-note
NONE
```
2022-02-17 09:24:39 +05:30
Agniva De Sarker
56e889a3fc Remove ColMap (#19544)
Now that gorp is gone, this is no longer
required.

```release-note
NONE
```
2022-02-15 11:44:04 +05:30
Penthaa Patel
7c9708ef49 [MM-39629] - Migrate from gorp to sqlx in store/sqlstore/thread_store.go (#19094)
Automatic Merge
2022-02-10 06:04:18 +02:00
Kyriakos Z
457aeb8e7e MM-36589: provide previous values for unreads (#18492)
* MM-36589: provide previous values for unreads

To successfully figure out the new counts of mentions or unread replies
for CRT we need to provide previous values alongside with the new.
This is needed so we'll know how many to subtract from the total.

This commit provides those numbers upon publishing websocket ThreadUpdated
and ThreadReadChanged events.

* Fixes errors

* Removes unneeded lines

* Adds GetThreadUnreadReplyCount store method

Uses the new store method to get unread replies instead of
GetThreadForUser.

* Tests, and some changes

- Adds api4 tests to test ws events
- Uses sqlx instead of gorp for new store method
- Fixes case where previous_unread_replies could be a negative value

* Refactors tests and adds more cases

* Fixes previous and current unread counts for commenter

When a user posts a reply to a thread the unread counts had a couple of
issues.
UnreadMentions where not zeroed out, and previous unread counts where
not set correctly.

This commit tries to fix that by marking the thread as read for the
current poster after we set previous unread counts to the websocket
event data.

Also MaintainMembership should zero out UnreadMentions when we are
setting the thread as read.

* Oops

* Fixes tests by updating when maintaining membership

OK, so some tests broke because we zero UnreadMentions in the membership
when we UpdateViewedTimestamp, since the new timestamp is always now.

Some tests broke because MaintainMembership for the commenter so that
the thread is read each time commenter posts moved further down in the
SendNotification method.

BOTH those test cases are fixed with this commit. To be sincere though I
don't understand why the second one is fixed by this.

* SystemAdminUser was not part of the channel

Some tests are failing because SystemAdminUser is not part of the
team and channels.
This commit adds user to team and channels, in an effort to fix
api4/user_tests

* Fixes tests

* Fixes tests

* Addresses review comments

* Fix if clause

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-02-09 15:41:30 -05:00
Ashish Bhate
7026818f80 MM-35298: Follow thread when added to channel (#19311)
* MM-35298: Follow thread when added to channel

* return better error if thread doesn't exist

* update test for possible race

* use correct comparision operator
2022-01-25 14:44:18 -05:00
Josh Soref
294bd44971 [GH-19267] Spelling comments (#19268)
* spelling: comments

Signed-off-by: Josh Soref <jsoref@users.noreply.github.com>
Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2022-01-20 10:07:27 +05:30
Ibrahim Serdar Acikgoz
6595b31f23 Replace go-migrate with morph (#19116) 2022-01-08 10:16:07 +02:00
Agniva De Sarker
12dc171a60 MM-39341: Sentry crash: nil dereference in *User.ClearNonProfileFields (#18966)
In some cases, an invalid participant id like an empty string
might creep into the database. It's not exactly clear
how can this happen, but if it does, then it breaks the logic
of assuming that the users slice will contain all users
in the participants slice.

To prevent this, we check if a match was found before
adding it in the slice.

https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4/7sixm4t7c6rsr3d8ydxbtfgy9gr

```release-note
NONE
```
2021-11-17 20:49:40 +05:30
Agniva De Sarker
5f4199db4f Revert "Optimize TotalUnreadMentions (#18789)" (#18889)
This reverts commit ec56cac42d.
2021-10-29 14:54:11 +05:30
Agniva De Sarker
ec56cac42d Optimize TotalUnreadMentions (#18789)
* Optimize TotalUnreadMentions

We avoid joining with the Threads table entirely
as ChannelId is available from Posts table directly.

Also we replace left joins by inner joins.

https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4?c=c9aa17f3-b918-4a78-86aa-01562e418634

Old plan

```
 Finalize Aggregate  (cost=30869.29..30869.30 rows=1 width=32) (actual time=27.216..31.674 rows=1 loops=1)
   ->  Gather  (cost=30869.18..30869.29 rows=1 width=32) (actual time=27.089..31.665 rows=2 loops=1)
         Workers Planned: 1
         Workers Launched: 1
         ->  Partial Aggregate  (cost=29869.18..29869.19 rows=1 width=32) (actual time=18.442..18.445 rows=1 loops=2)
               ->  Nested Loop  (cost=1881.68..29869.11 rows=25 width=8) (actual time=2.052..18.417 rows=72 loops=2)
                     ->  Hash Join  (cost=1881.12..29771.45 rows=25 width=62) (actual time=2.028..17.744 rows=72 loops=2)
                           Hash Cond: ((threads.channelid)::text = (channels.id)::text)
                           ->  Nested Loop  (cost=0.84..27883.40 rows=2963 width=89) (actual time=0.220..15.849 rows=163 loops=2)
                                 ->  Parallel Index Scan using threadmemberships_pkey on threadmemberships  (cost=0.41..7423.65 rows=2963 width=35) (actual time=0.031..3.937 rows=2504 loops=2)
                                       Index Cond: ((userid)::text = 'tc3p1yqw67d8idcp3g98awexqe'::text)
                                       Filter: following
                                 ->  Index Scan using threads_pkey on threads  (cost=0.42..6.91 rows=1 width=54) (actual time=0.004..0.004 rows=0 loops=5007)
                                       Index Cond: ((postid)::text = (threadmemberships.postid)::text)
                           ->  Hash  (cost=1866.60..1866.60 rows=1094 width=27) (actual time=1.763..1.764 rows=1002 loops=2)
                                 Buckets: 2048  Batches: 1  Memory Usage: 74kB
                                 ->  Index Scan using idx_channels_team_id_type on channels  (cost=0.42..1866.60 rows=1094 width=27) (actual time=0.022..1.493 rows=1002 loops=2)
                                       Index Cond: ((teamid)::text = '8ywxyw9ocp8smxrmjzrkqhrdwe'::text)
                     ->  Index Scan using posts_pkey on posts  (cost=0.56..3.91 rows=1 width=27) (actual time=0.009..0.009 rows=1 loops=145)
                           Index Cond: ((id)::text = (threads.postid)::text)
                           Filter: (deleteat = 0)
 Planning Time: 2.415 ms
 Execution Time: 31.798 ms
```

New plan

```
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Finalize Aggregate  (cost=34717.01..34717.02 rows=1 width=32) (actual time=42.375..48.143 rows=1 loops=1)
   ->  Gather  (cost=34716.89..34717.00 rows=1 width=32) (actual time=42.249..48.117 rows=2 loops=1)
         Workers Planned: 1
         Workers Launched: 1
         ->  Partial Aggregate  (cost=33716.89..33716.90 rows=1 width=32) (actual time=30.960..30.962 rows=1 loops=2)
               ->  Hash Join  (cost=1881.25..33716.83 rows=25 width=8) (actual time=2.438..30.780 rows=1058 loops=2)
                     Hash Cond: ((posts.channelid)::text = (channels.id)::text)
                     ->  Nested Loop  (cost=0.98..31828.77 rows=2963 width=35) (actual time=0.091..27.374 rows=2504 loops=2)
                           ->  Parallel Index Scan using threadmemberships_pkey on threadmemberships  (cost=0.41..6815.65 rows=2963 width=35) (actual time=0.034..4.674 rows=2504 loops=2)
                                 Index Cond: ((userid)::text = 'tc3p1yqw67d8idcp3g98awexqe'::text)
                                 Filter: following
                           ->  Index Scan using posts_pkey on posts  (cost=0.56..8.44 rows=1 width=54) (actual time=0.008..0.008 rows=1 loops=5007)
                                 Index Cond: ((id)::text = (threadmemberships.postid)::text)
                                 Filter: (deleteat = 0)
                     ->  Hash  (cost=1866.60..1866.60 rows=1094 width=27) (actual time=2.289..2.289 rows=1002 loops=2)
                           Buckets: 2048  Batches: 1  Memory Usage: 74kB
                           ->  Index Scan using idx_channels_team_id_type on channels  (cost=0.42..1866.60 rows=1094 width=27) (actual time=0.028..1.927 rows=1002 loops=2)
                                 Index Cond: ((teamid)::text = '8ywxyw9ocp8smxrmjzrkqhrdwe'::text)
```

```release-note
NONE
```

* Bring back coalesce

```release-note
NONE
```
2021-10-29 09:07:10 +05:30
Agniva De Sarker
685b311401 ThreadStore: Remove quadratic complexity for participants population (#18755)
* ThreadStore: Remove quadratic complexity for participants population

While populating the participants, we would traverse the global list
twice to get the users for that thread. For threads with large number
of users, this can take considerable time. We replace that with a map
to change it to O(n).

While here, we improve memory usage of this code by pre-allocating
slices and maps. And also add some comments to help readers.

https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4?c=c9aa17f3-b918-4a78-86aa-01562e418634

```release-note
NONE
```

* Apply in post store as well

```release-note
NONE
```

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-10-28 09:57:54 +05:30
Agniva De Sarker
c91ab6267a Revert "Optimize TotalUnreadThreads (#18788)" (#18845)
This reverts commit 971af6935c.
2021-10-26 14:02:03 +05:30
Agniva De Sarker
971af6935c Optimize TotalUnreadThreads (#18788)
We remove the left joins with inner joins and also
remove the coalesce on posts.DeleteAt which improves
the join plan from a nested loop to a hash join,
and also allows the DeleteAt to be used as part of the
index filter.

Old plan

```
 Aggregate  (cost=666288.49..666288.50 rows=1 width=8) (actual time=5114.328..5119.991 rows=1 loops=1)
   ->  Gather  (cost=2880.69..666288.27 rows=87 width=8) (actual time=614.214..5119.575 rows=533 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Nested Loop  (cost=1880.69..665279.57 rows=36 width=8) (actual time=607.821..5099.078 rows=178 loops=3)
               ->  Hash Join  (cost=1880.28..664932.93 rows=229 width=16) (actual time=224.374..1494.698 rows=1866781 loops=3)
                     Hash Cond: ((posts.channelid)::text = (channels.id)::text)
                     ->  Parallel Seq Scan on posts  (cost=0.00..662980.29 rows=27568 width=43) (actual time=201.053..1013.362 rows=4410819 loops=3)
                           Filter: (COALESCE(deleteat, '0'::bigint) = 0)
                     ->  Hash  (cost=1866.60..1866.60 rows=1094 width=27) (actual time=1.486..1.486 rows=1002 loops=3)
                           Buckets: 2048  Batches: 1  Memory Usage: 74kB
                           ->  Index Scan using idx_channels_team_id_type on channels  (cost=0.42..1866.60 rows=1094 width=27) (actual time=0.028..1.331 rows=1002 loops=3)
                                 Index Cond: ((teamid)::text = '8ywxyw9ocp8smxrmjzrkqhrdwe'::text)
               ->  Index Scan using threadmemberships_pkey on threadmemberships  (cost=0.41..1.50 rows=1 width=35) (actual time=0.002..0.002 rows=0 loops=5600344)
                     Index Cond: (((postid)::text = (posts.rootid)::text) AND ((userid)::text = 'tc3p1yqw67d8idcp3g98awexqe'::text))
                     Filter: (following AND (posts.createat > lastviewed))
                     Rows Removed by Filter: 0
 Planning Time: 2.005 ms
 JIT:
   Functions: 59
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 9.905 ms, Inlining 122.509 ms, Optimization 293.764 ms, Emission 186.064 ms, Total 612.241 ms
 Execution Time: 5125.739 ms
```

New plan

```
 Aggregate  (cost=683129.17..683129.18 rows=1 width=8) (actual time=1650.746..1656.455 rows=1 loops=1)
   ->  Gather  (cost=3766.65..683085.55 rows=17450 width=27) (actual time=641.073..1656.086 rows=533 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         ->  Hash Join  (cost=2766.65..680340.55 rows=7271 width=27) (actual time=617.096..1635.203 rows=178 loops=3)
               Hash Cond: ((posts.rootid)::text = (threadmemberships.postid)::text)
               Join Filter: (posts.createat > threadmemberships.lastviewed)
               Rows Removed by Join Filter: 6
               ->  Hash Join  (cost=1880.28..679334.08 rows=45742 width=16) (actual time=15.196..1242.832 rows=1866781 loops=3)
                     Hash Cond: ((posts.channelid)::text = (channels.id)::text)
                     ->  Parallel Seq Scan on posts  (cost=0.00..662980.29 rows=5513543 width=43) (actual time=0.028..775.118 rows=4410819 loops=3)
                           Filter: (deleteat = 0)
                     ->  Hash  (cost=1866.60..1866.60 rows=1094 width=27) (actual time=1.572..1.573 rows=1002 loops=3)
                           Buckets: 2048  Batches: 1  Memory Usage: 74kB
                           ->  Index Scan using idx_channels_team_id_type on channels  (cost=0.42..1866.60 rows=1094 width=27) (actual time=0.025..1.372 rows=1002 loops=3)
                                 Index Cond: ((teamid)::text = '8ywxyw9ocp8smxrmjzrkqhrdwe'::text)
               ->  Hash  (cost=823.41..823.41 rows=5037 width=35) (actual time=256.240..256.241 rows=5007 loops=3)
                     Buckets: 8192  Batches: 1  Memory Usage: 417kB
                     ->  Bitmap Heap Scan on threadmemberships  (cost=159.45..823.41 rows=5037 width=35) (actual time=253.011..255.255 rows=5007 loops=3)
                           Recheck Cond: ((userid)::text = 'tc3p1yqw67d8idcp3g98awexqe'::text)
                           Filter: following
                           Heap Blocks: exact=601
                           ->  Bitmap Index Scan on idx_thread_memberships_user_id  (cost=0.00..158.19 rows=5037 width=0) (actual time=0.627..0.627 rows=5037 loops=3)
                                 Index Cond: ((userid)::text = 'tc3p1yqw67d8idcp3g98awexqe'::text)
 Planning Time: 1.952 ms
 JIT:
   Functions: 83
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 10.148 ms, Inlining 115.819 ms, Optimization 395.923 ms, Emission 244.130 ms, Total 766.021 ms
 Execution Time: 1661.791 ms
```

No special test has been done on MySQL since these are pretty
basic optimizations and should apply to both equally.

https://community-daily.mattermost.com/boards/workspace/zyoahc9uapdn3xdptac6jb69ic/285b80a3-257d-41f6-8cf4-ed80ca9d92e5/495cdb4d-c13a-4992-8eb9-80cfee2819a4?c=c9aa17f3-b918-4a78-86aa-01562e418634

```release-note
NONE
```
2021-10-26 08:56:38 +05:30
Claudio Costa
92837fa1ee [MM-22051] Remove To/From JSON (#18070)
* Posts

* Add missing translation

* Fix internal store marshaling

* [MM-22051] Remove To/From JSON (Channels) (#18116)

* Channels

* Channel members

* ChannelSearch

* Channel categories, list, sidebar, stats, view

* Fix conversions

* [MM-22051] Remove To/From JSON (Users) (#18121)

* User related structs

* Fix return

* Team related structures (#18127)

* [MM-22051] Remove To/From JSON (Status, Bot, Reaction, Thread, FileInfo) (#18130)

* Status

* Bot

* Reaction

* Thread

* FileInfo

* Some fixes

* Translations update from Weblate (#18143)

* Translated using Weblate (German)

Currently translated at 100.0% (2309 of 2309 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (2309 of 2309 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2309 of 2309 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/

Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/

* Translated using Weblate (German)

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/de/

* Translated using Weblate (Turkish)

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/tr/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/hu/

* Translated using Weblate (English (Australia))

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/en_AU/

* Translated using Weblate (Bulgarian)

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/bg/

* Translated using Weblate (Japanese)

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/ja/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2301 of 2301 strings)

Translation: mattermost-languages-shipped/mattermost-server
Translate-URL: https://translate.mattermost.com/projects/mattermost/mattermost-server_master/zh_Hans/

Co-authored-by: JtheBAB <srast@bioc.uzh.ch>
Co-authored-by: Kaya Zeren <kayazeren@gmail.com>
Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu>
Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au>
Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com>
Co-authored-by: kaakaa <stooner.hoe@gmail.com>
Co-authored-by: aeomin <lin@aeomin.net>

Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: JtheBAB <srast@bioc.uzh.ch>
Co-authored-by: Kaya Zeren <kayazeren@gmail.com>
Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu>
Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au>
Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com>
Co-authored-by: kaakaa <stooner.hoe@gmail.com>
Co-authored-by: aeomin <lin@aeomin.net>

* [MM-22051] Remove To/From JSON methods from model (#18138)

* Scheme

* Role

* Session

* Config

* Status

* Fix logic

* Emoji

* GuestsInvite

* Group

* Command

* ClusterInfo

* License

* Job

* System

* Plugin

* Command2

* IncomingWebhook

* OutgoingWebhook

* Fix tests

* Update traslation

* Some fixes

* Add missing return

* Simplify

* Make Config.ToJSONFiltered() return []byte

* Make Busy.ToJSON() return []byte

* Include error in log

* Split logic

* [MM-22051] Remove To/From JSON (final) (#18150)

* SwitchRequest

* PluginEventData

* Permalink

* PushNotification

* SuggestCommand

* PluginsResponse

* WebSocketMessage

* RemoteCluster

* SharedChannel

* PluginStatuses

* InitialLoad

* ClusterDiscovery

* ClusterStats

* MfaSecret

* GroupSyncable

* SAML

* WebSocketRequest

* TypingRequest

* SecurityBulletin

* OAuthApp

* IntegrationAction

* DataRetention

* Preference

* FileInfoList

* Compliance

* Preferences

* FileInfoSearchResults

* TermsOfService

* InstallMarketplacePluginRequest

* GitLabUser

* UploadSessions

* Remove unused helpers

* Fix tests

* [MM-23280] Fix linting for ToJSON/FromJSON (#18153)

* SwitchRequest

* PluginEventData

* Permalink

* PushNotification

* SuggestCommand

* PluginsResponse

* WebSocketMessage

* RemoteCluster

* SharedChannel

* PluginStatuses

* InitialLoad

* ClusterDiscovery

* ClusterStats

* MfaSecret

* GroupSyncable

* SAML

* WebSocketRequest

* TypingRequest

* SecurityBulletin

* OAuthApp

* IntegrationAction

* DataRetention

* Preference

* FileInfoList

* Compliance

* Preferences

* FileInfoSearchResults

* TermsOfService

* InstallMarketplacePluginRequest

* GitLabUser

* UploadSessions

* Remove unused helpers

* Fix tests

* Fix linting for ToJSON/FromJSON

* Fix conversions

Co-authored-by: Weblate (bot) <hosted@weblate.org>
Co-authored-by: JtheBAB <srast@bioc.uzh.ch>
Co-authored-by: Kaya Zeren <kayazeren@gmail.com>
Co-authored-by: Tóth Csaba // Online ERP Hungary Kft <csaba.toth@online-erp.hu>
Co-authored-by: Matthew Williams <Matthew.Williams@outlook.com.au>
Co-authored-by: Nikolai Zahariev <nikolaiz@yahoo.com>
Co-authored-by: kaakaa <stooner.hoe@gmail.com>
Co-authored-by: aeomin <lin@aeomin.net>
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-09-01 14:43:12 +02:00
Kyriakos Z
bb05e7c412 MM-35017: order and inclusion of participants (#18235)
* MM-35017: order and inclusion of participants

From now on root poster is not considered a thread participant,
only repliers are participants.

Ordering: A second reply to the thread from the same user should place
the user last at the participants list.

* Fixes shadow

* Fixes tests

* Order By CreateAt for participants of old threads

* Removes unnecessary check on root id

* Removes GetParticipantProfilesByIds it's not needed

At first GetParticipantProfilesByIds was created because GetProfileByIds
gets users by order of username.
This was not needed, we can order by user ids in Go.

This commit removes GetParticipantProfilesByIds and replaces it by
GetProfileByIds as it was done before.

* Fixes participants order for pre CRT threads

Older threads (before CRT) are being converted to CRT threads upon
reply.
This commit considers the order of participants to be inserted to
the new thread.

* Adds tests for thread participants

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-08-30 17:13:55 -04:00
Claudio Costa
c4c1fda128 [MM-36387] Address db performance audit items (#18078) 2021-08-21 08:05:52 +03:00
Kyriakos Z
a0c5d8feab MM-36234,MM-37030,MM-37031: CRT, desktop thread notifications (#18088)
* CRT: desktop thread notifications

* Fixes go lint

* Adds default for desktop CRT notifications

* Adds email and push notifications for CRT threads

Adds user ids of thread followers with CRT to crtMentions so they will get
notified appropriately.

* Minor change

* Refactor a bit

CRTMentions.addMention had a bug on the return and de-duplication.
This commit fixes duplicate notifications by looking up if the user is to be
notified on CRT on both email and push notifications.

* Minor refactor

* Changes according to review comments

- Fixes adding to followers a user that had explicitly unfollowed a
  thread.
- Simplified send email according to email_threads option
- Send mentions and followers in separate arrays via the websocket
- Fixes push notifications message for push_threads

* Adds a comment on a buggy use case

* Updates comment to correct ticket link

* Fixes when user notifications is set to all

There was a bug where if user had set notifications to all
then they would receive desktop notifications even for non following threads.

A similar bug existed in push notifications, where if a user has set it
to all the threads setting would still be considered.

This commit fixes that by adding users to notificationsForCRT
StringArray when they have the non thread setting to 'all'.

* Fixes notifications to users unfollowing threads

Users which had previously explicitly unfollowed a thread
should not receive notifications about those threads.

* Update store mocks

* Fixes push notifications for CRT

Push notification about replies for CRT users should have a title of
"Reply to Thread".

CRT users with global user setting to 'UserNotifyAll' should not get
notifications for unfollowed threads.

This commit fixes those issues.

* Fixes i18n error

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
2021-08-19 17:28:46 +03:00
Agniva De Sarker
e1b0644b0d Using native JSON operations to add thread participants (#18093)
Automatic Merge
2021-08-12 16:45:03 +02:00
Ashish Bhate
296076bf2d [MM-36544][MM-37439] Don't re-follow on reply to unfollowed thread (#18020)
Summary
If a user has unfollowed a thread, another user's reply in the thread should not cause the first user to re-follow the thread. The first user will be re-followed if they are mentioned in the thread.
Simplify and make flexible the logic surrounding following and remove some duplicate code.

Ticket Link
https://mattermost.atlassian.net/browse/MM-36544
https://mattermost.atlassian.net/browse/MM-37439
2021-07-30 18:47:41 +05:30
Claudio Costa
1ae1c38c9f [MM-36995] Start using db native JSON datatypes (#17930)
* Start using db native JSON datatypes

* Fix syntax to work on MySQL 5.7.12
2021-07-28 08:50:36 +02:00
Joram Wilander
a0cc420e2a MM-35392 Load thread unreads for other teams on app load (#17944)
* Add ability to include thread unreads in team unreads api response

* Do not include GMs/DMs in team unreads for threads

* Fix bad merge
2021-07-22 10:24:20 -04:00
Agniva De Sarker
c4b4e1bc38 MM-36271: Bump major version to 6.0 (#17973)
https://mattermost.atlassian.net/browse/MM-36271

```release-note
We bump the major version to 6.0
```
2021-07-22 12:21:47 +05:30
Ashish Bhate
f204c745cb [MM-35345]: fix unreads in threads and migration (#17938)
Summary
Fix unreads query for threads to check deleted option
Normalize unreads query to look for threads after given time
Fix migration to only run once, and increment timestamp by one so that threads are definitely marked as read.

Ticket Link
Fixes issues with https://mattermost.atlassian.net/browse/MM-35345
And possibly some issues with thread unreads.
2021-07-16 19:26:16 +05:30
Ashish Bhate
e50cfca2ea [MM-35345][MM-35494] fixes for incorrect mentions and unreads for threads and channels (#17803)
Summary:
The CRT backend was first released in version 5.29.0. Since then, the behaviour of the CRT feature has been refined, several bugs have been fixed, and a few sql columns have been added. Before these various fixes went in, the threads and channel membership tables have accumulated incorrect mention and unreads data. This PR fixes some of this bad historical data.
Summary of fixes:

- Marks threads as read for users where the last reply time of the thread is earlier than the time the user viewed the channel. Marking a thread means setting the mention count to zero and setting the last viewed at time of the the thread as the last viewed at time of the channel. This is done through a "sql migration"
- Fix channel counts, i.e. the total message count, total root message count, mention count, and mention count in root messages for users who have viewed the channel after the last post in the channel. This is done as a "sql migration"


Ticket Link:
Parts of
https://mattermost.atlassian.net/browse/MM-35494
https://mattermost.atlassian.net/browse/MM-35345
2021-07-14 17:39:40 +05:30
Joram Wilander
e08ebf3871 MM-36429 Do not increment mention counts when marking root posts with no replies as unread (#17826)
Automatic Merge
2021-06-24 22:35:03 +02:00