Commit Graph

254 Commits

Author SHA1 Message Date
Benjamin Bouvier
06d5fdb5ff fix(event cache): enable foreign keys on a connection basis
As opposed to WAL mode, foreign keys must be enabled for each database
connection, according to
https://www.sqlite.org/foreignkeys.html#fk_enable

Unfortunately, we can't track which connection objects have already
executed the pragma, so the safer we can do is enable it everytime we
try to acquire a connection from the pool.

Fixes #4785.
2025-03-11 15:03:42 +01:00
Benjamin Bouvier
961a893b8c test(event cache): double-check cascading happened in the clear linked chunk test 2025-03-11 15:03:42 +01:00
Ivan Enderlin
3d653d3fdc fix(sqlite): Design a new schema to get faster insertions.
This patch is twofold. First off, it provides a new schema allowing to
improve the performance of `SqliteEventCacheStore` for 100_000 events
from 6.7k events/sec to 284k events/sec on my machine.

Second, it now assumes that `EventCacheStore` does NOT store invalid
events. It was already the case, but the SQLite schema was not rejecting
invalid event in case some were handled. It's now explicitely forbidden.
2025-03-05 13:57:08 +01:00
Ivan Enderlin
b22bb3ee9f fix(sqlite): Use a prepared statement to insert events.
This patch uses a prepared statement to insert events in the linked
chunks. It offers more predictable performance, and SQLite prefers that.
2025-03-05 13:57:08 +01:00
Ivan Enderlin
892c99f0f3 test(sqlite): Improve a test to check uniqueness constraint. 2025-03-05 12:02:30 +01:00
Benjamin Bouvier
ac3250c58b refactor(event cache): use u64 instead of usize in MediaCachePolicy
This is more predictible and we're still far from 128-bits wide cpu,
right? RIGHT?
2025-03-04 18:10:59 +01:00
Ivan Enderlin
7b52306ff2 feat(base): Add EventCacheStore::find_event.
This patch adds the method `find_event` on the `EventCacheStore` trait.
It helps to find a single event from the store.
2025-02-25 12:07:17 +01:00
Ivan Enderlin
43c066e837 task(base): EventCacheStore::filter_duplicated_events returns Position.
This patch changes `EventCacheStore::filter_duplicated_events` to return
the `Position` of the duplicated event.
2025-02-24 17:37:47 +01:00
Ivan Enderlin
6c57003d17 feat(sqlite) Add an index on events.event_id and .room_id.
This patch adds an index on `events.event_id` and on `events.room_id`
so that queries on this column are faster. It mostly happens for the
`Deduplicator`, which runs for every backwards pagination or sync.

This patch also updates the query in `filter_duplicated_events` to
sort event by their `chunk_id` and `position` so that the results are
constant, it helps when testing.
2025-02-19 11:50:23 +01:00
Ivan Enderlin
d6566484a1 doc(sqlite): Fix typos in comments. 2025-02-18 11:38:24 +01:00
Ivan Enderlin
0e4d8ec62f feat(sqlite): Detect cycles when loading last chunk of LinkedChunk.
This patch updates `SqliteEventCacheStore::load_last_chunk` to detect
cycle for the last chunk only.
2025-02-18 11:38:24 +01:00
Ivan Enderlin
bed4d5034e test(sqlite): Test SqliteEventCacheStore::load_last_chunk and load_previous_chunk.
This patch adds tests for the `SqliteEventCacheStore::load_last_chunk`
and `load_previous_chunk` methods.
2025-02-18 11:38:24 +01:00
Ivan Enderlin
e2a2f32e82 task(sqlite): Implement load_last_chunk and last_previous_chunk.
This patch replaces `todo!()` by real implementations for the
`load_last_chunk` and `last_previous_chunk` methods.
2025-02-18 11:38:24 +01:00
Ivan Enderlin
334c66b0a0 task(base): Update EventCacheStore to add load_last_chunk and load_previous_chunk.
This patch update the `EventCacheStore` trait to:

1. rename `reload_linked_chunk` into `load_all_chunks` and put this
   method behind `#[cfg(test)]` so that it is removed from the public API,
2. add `load_last_chunk`,
3. add `load_previous_chunk`.

These 2 new methods are implemented inside the `MemoryStore` (with its
real implementation in the `RelationalLinkedChunk`), but `todo!()` are
added for the SQLite implementation.
2025-02-18 11:38:24 +01:00
Benjamin Bouvier
1068d88c3e fix(event cache store): shortcut when there's no duplicate events to check at all
Otherwise this causes a panic when repeating the events variable, when
generating the SQL query below.
2025-02-13 13:43:49 +01:00
Ivan Enderlin
d45addee10 feat(base): Add EventCacheStore::filter_duplicated_events.
This patch adds and implements the
`EventCacheStore::filter_duplicated_events` method. It is implemented on
the `MemoryStore` and the `SqliteEventCacheStore`.

This method remove the unique events and reutrn the duplicated events.
2025-02-12 16:50:14 +01:00
Ivan Enderlin
714caae545 chore(sqlite): Remove a useless indentation.
This patch removes a useless indentation.
2025-02-12 16:13:40 +01:00
Kévin Commaille
65ee18a52d feat(sqlite): Run VACUUM operation after removing a room
A room can be associated to a lot of data, depending on the number of members in the room.
So freeing space on the filesystem should be worth it in some cases.

An (extreme) example: I have a test account that is in ~60 rooms, a few of those big public rooms, including Matrix HQ. The size of the matrix-sdk-state.sqlite3 file is 542 MB. Using this PR and leaving, then forgetting Matrix HQ brings the DB down to 255 MB.
2025-02-11 14:13:25 +00:00
Kévin Commaille
ed18c5113f fix: Fix changelogs for new media service feature after new release
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-05 00:28:56 +01:00
Kévin Commaille
0f4b3aa187 Merge branch 'main' into media-cache-auto-cleanup 2025-02-05 00:12:18 +01:00
Damir Jelić
4c46e42201 chore: Release matrix-sdk version 0.10.0 2025-02-04 16:32:55 +01:00
Kévin Commaille
f641a639cd Merge branch 'main' into media-cache-auto-cleanup 2025-02-04 11:56:32 +01:00
Kévin Commaille
df3cb002a5 chore: Add changelog entries
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-03 11:22:23 +01:00
Kévin Commaille
6ebd4295b9 feat(sqlite): Limit size of WAL file
The WAL file can grow depending on the transactions that are run. A
critical case is VACUUM which basically writes the content of the DB
file to the WAL file before writing it back to the DB file.

SQLite doesn't try to reduce the size of the file after that unless we
set an explicit limit,
so we could end up taking twice the size of the database on the
filesystem.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-03 11:22:23 +01:00
Kévin Commaille
c5104d68fd feat(sqlite): Run PRAGMA optimize regularly
As recommended by the SQLite docs.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-03 11:22:23 +01:00
Kévin Commaille
0064839283 fix(sqlite): Vaccum the SqliteStateStore
It should have been done in the migration of version 7, to reduce the
size of the database on the filesystem after the media cache was moved
to the SqliteEventCacheStore. Better late than never.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-03 11:22:23 +01:00
Kévin Commaille
7da3aaaa8a chore: Add new PR links to MediaRetentionPolicy changelog entries
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-02 12:28:43 +01:00
Kévin Commaille
5aaa6bf187 feat(base): Add automatic media cache cleanups to MediaService
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-02 12:20:13 +01:00
Kévin Commaille
8dc2ec9dc4 feat(base): Allow to clone MediaService
We want to be able to send it to a new task, so the easiest way is to be able to clone it.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-02 12:03:12 +01:00
Kévin Commaille
4e1ae3d5e9 feat(base): Store last media cleanup time with EventCacheStoreMedia
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-02 11:52:42 +01:00
Kévin Commaille
582b3a91d6 refactor(sqlite): Add methods to get and set values in the kv table by (de)serializing them
Since it's a common occurrence, it will reduce duplication.

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-02-02 11:47:43 +01:00
Damir Jelić
57919f5480 chore: Bump most of our deps 2025-01-31 17:14:37 +01:00
Ivan Enderlin
5049d1a3b6 chore(sqlite): Use repeat_n(…, n) instead of repeat(…).take(n).
Thanks Clippy!
2025-01-31 14:07:43 +01:00
Kévin Commaille
df9c355aed Merge branch 'main' into media-retention-policy
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-01-28 15:46:55 +01:00
Kévin Commaille
8262726369 chore(sqlite): Add changelog entry for EventCacheStore changes
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-01-28 15:44:44 +01:00
Kévin Commaille
eb9b86971a feat(base): Add methods for MediaRetentionPolicy to EventCacheStore
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-01-28 15:44:42 +01:00
Kévin Commaille
8ca5983093 feat(sqlite): Implement EventCacheStoreMedia for SqliteEventCacheStore
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-01-28 15:38:18 +01:00
Benjamin Bouvier
3428494468 refactor: rename SyncTimelineEvent to TimelineEvent 2025-01-22 20:24:48 +01:00
Benjamin Bouvier
425e48a46d feat(linked chunk): add LinkedChunk::replace_item_at to replace an item from a given position 2025-01-16 12:26:32 +01:00
Valere
c969f903b7 Merge pull request #4526 from matrix-org/valere/test_encrypted_crypto_sql_snapshot
tests: Add an encrypted snapshot of a SQLite db for regression tests
2025-01-15 09:37:27 +01:00
Valere
ee32b1f600 tests: Add an encrypted snapshot of a SQLite db for regression tests 2025-01-13 17:50:50 +01:00
Daniel Salinas
9641aa9082 feat(send queue): Add an enqueued time to to-be-sent events (#4385)
Add a new created_at to the send_queue_events and
dependent_send_queue_events stored records. This will allow clients to
understand how stale a pending message might be in the event that the
queue encounters and error and becomes wedged.

This change is exposed through the FFI on the `EventTimelineItem` struct
as a new optional field named `local_created_at`. It will be `None` for
any Remote event, and `Some` for Local events (except for those that
were enqueued before the migrations were run).

Signed-off-by: Daniel Salinas

---------

Signed-off-by: Daniel Salinas <zzorba@users.noreply.github.com>
Co-authored-by: Daniel Salinas <danielsalinas@daniels-mbp-2.myfiosgateway.com>
Co-authored-by: Benjamin Bouvier <benjamin@bouvier.cc>
Co-authored-by: Daniel Salinas <danielsalinas@Daniels-MBP-2.attlocal.net>
2025-01-13 16:41:05 +00:00
Benjamin Bouvier
aca8c8b8ee chore: remove some allow(dead_code) annotations and associated dead code (#4472)
We have quite a few `allow(dead_code)` annotations. While it's OK to use
in situations where the Cargo-feature combination explodes and makes it
hard to reason about when something is actually used or not, in other
situations it can be avoided, and show actual, dead code.
2025-01-08 10:37:18 +01:00
Integral
f18e0b18a1 Replace PathBuf/Utf8PathBuf with Path/Utf8Path when ownership not needed 2024-12-19 13:29:09 +01:00
Damir Jelić
bb573117e1 chore: Release matrix-sdk version 0.9.0 2024-12-18 15:12:23 +01:00
Jorge Martín
05d46e6027 Rename JoinRequest in the SDK crates to KnockRequest, make Room::mark_knock_requests_as_seen thread safe and pass user_ids instead of event_ids: the user ids will be used to get the related member state events and they'll only be marked as seen if they're in a knock state.
Also, add extra checks to the integration tests.
2024-12-16 14:08:09 +01:00
Jorge Martín
9a899c1cb1 feat(room): add 'seen request to join ids' to the stores
This will allow us to keep track of which join room requests are marked as 'seen' by the current user and return them as such.

Also, add some methods to `Room` to mark new join requests as seen and to get the current ids for the seen join requests.
2024-12-16 14:08:09 +01:00
Valere
2b39476d9b feat(crypto): Support storing the dehydrated device pickle key 2024-12-13 13:05:19 +01:00
Benjamin Bouvier
150d9e4b05 fix(event cache store): always use immediate mode when handling linked chunk updates
If a linked chunk update starts with a RemoveChunk update, then the
transaction may start with a SELECT query and be considered a read
transaction. Soon enough, it will be upgraded into a write transaction,
because of the next UPDATE/DELETE operations that happen thereafter. If
there's another write transaction already happening, this may result in
a SQLITE_BUSY error, according to
https://www.sqlite.org/lang_transaction.html#deferred_immediate_and_exclusive_transactions

One solution is to always start the transaction in immediate mode. This
may also fail with SQLITE_BUSY according to the documentation, but it's
unclear whether it will happen in general, since we're using WAL mode
too. Let's try it out.
2024-12-12 17:59:42 +01:00
Benjamin Bouvier
0264e49968 task(event cache): rename a few things
- rename RawLinkedChunk -> RawChunk
- rename RawChunk::id -> RawChunk::identifier
- precise that a `RawChunk` is mostly a `Chunk` with different
previous/next links.
2024-12-11 12:10:24 +01:00