Commit Graph

255 Commits

Author SHA1 Message Date
Ivan Enderlin 660d4e7ccb feat(sqlite): Add StoreOpenConfig and open_with_config for all stores.
This patch adds a new `StoreOpenConfing` type to configure the store
when opening it and when creating the pool of connections to SQLite via
`deadpool_sqlite`.

This patch also adds a new `open_with_config` constructor on all
stores, namely `SqliteCryptoStore`, `SqliteEventCacheStore` and
`SqliteStateStore`.
2025-03-26 11:01:52 +01:00
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