This patch exposes the pause/resume mechanism for SDK stores all the way up to
the FFI `Client`, so apps can temporarily release SQLite resources when moving
to the background and re-acquire them on resume.
The main use case is iOS backgrounding, where keeping SQLite file descriptors and
locks open can contribute to `0xdead10cc` terminations by the operating system.
This patch implements the main pause/resume logic in the underlying SDK stores.
The in memory stores no-op trough the default trait implementations.
The main change are limited to the sqlite crate:
- a new type called `SqliteConnections` has been introduced which now holds a
store's read connection pools as well as the always on write connection. This
lives as an optional on each store's level and gets set to None whenever the
store is paused
- during the pausing phase `SqliteConnections` (through its `pause_connections`
method) does the following:
- closes the read pool, directly dropping idle connections
- waits for in flight writes to finish
- tries a best effort WAL checkpoint
- drops the write connection on a blocking thread
- and waits for in-flight read connections to drain
- this is all best effort with an eventual timeout
- resuming connections is also shared between the stores through
`SqliteConnections` and consists in building a new pool with the previous
configuration and creating a new write connection
This extracts the `/capabilities` logic to its own `HomeserverCapabilities` component in the SDK that can be manually asked to fetch, cache locally and return these capabilities.
# Overview
There are scenarios in which it is sensible to have an event exist in
the same room more than once. Notably, this is true in the context of a
thread, where an event exists in the main timeline of a room, as well as
in a thread of that same room.
Support for this behavior has been implemented in the
`SQLiteEventCacheStore` in #6065; however, this was never implemented
for the `IndexeddbEventCacheStore` or the `MemoryStore`. This pull
request extends this behavior to both of those stores.
# Changes
## Integration Tests
First, `test_event_chunks_allows_same_event_in_room_and_thread` was
moved from `matrix_sdk_sqlite::event_cache_store` to
`matrix_sdk_base::event_cache::store::integration_tests`. Then, a few
additional integration tests were added to ensure that behavior is
consistent across implementations of `EventCacheStore`.
## `IndexeddbEventCacheStore`
In order to accommodate the behavioral changes specified by the
integration tests, it was necessary to modify the schema in the
IndexedDB implementation of `EventCacheStore`. Namely, the events object
store was cleared and removed and then replaced with a nearly identical
one, the only difference being the removal of a uniqueness constraint on
one of the indices.
The remaining changes mostly involved updating the behavior of top-level
`EventCacheStore` functions - e.g., filtering out events where they were
duplicated or removing positioning information where it was not
relevant.
## `MemoryStore`
The changes to `MemoryStore` mostly involved updating the behavior of
top-level `EventCacheStore` function - e.g., filtering out events where
they were duplicated or removing positioning information where it was
not relevant.
That being said, it also involved some breaking changes to
`RelationalLinkedChunk`.
1. `RelationalLinkedChunk::items` - this function returned an `Iterator`
that did not contain information about the `LinkedChunkId`, so this
information was added to the items in the `Iterator`.
2. `RelationalLinkedChunk::save_item` - this function did not update the
item in all linked chunks of the provided `Room`. It now does this, but
requires that the provided `Item` be `Clone`.
(1) could probably have been a new function, but I thought a nicer
interface was worth the breaking change. (2) could probably be prevented
by re-organizing `RelationalLinkedChunk`'s internal data structures to
remove the `Clone` requirement, but that seemed like it could turn into
a large refactoring project, so I opted for something simpler albeit
somewhat crude.
In both cases, I'm open to suggestions and would be happy to revisit if
something else is preferred.
---
Closes#6094.
- [x] I've documented the public API Changes in the appropriate
`CHANGELOG.md` files.
- [x] I've read [the `CONTRIBUTING.md`
file](https://github.com/matrix-org/matrix-rust-sdk/blob/main/CONTRIBUTING.md),
notably the sections about Pull requests, Commit message format, and AI
policy.
- [ ] This PR was made with the help of AI.
Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
---------
Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
They are error prone because they need to be bumped for every migration
otherwise the new migration will not happen because we exit early.
So instead we get rid of the early returns and log each individual
upgrade separately. It makes more noise when creating a new database,
but since it is logged at the DEBUG level it is not much of a problem.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Similarly to #5382 and #5744, this patch introduces a write-only
connection in `SqliteCryptoStore`. The idea is to get many read-only
connections, and a single write-only connection behind a lock, so that
there is a single writer at a time.
This patch renames the `acquire` method to `read`, and it introduces a
new `write` connection.
This patch replaces the `interact(…).unwrap()` by a proper error.
So far, `interact()` was only returning `InteractError::Panic`
despites `InteractError::Aborted` exists. With
https://github.com/deadpool-rs/deadpool/pull/461, we now get
`InteractError::Aborted` when the SDK is shutdown, sometimes. This
results in hitting the `unwrap` and having a panic again. This patch
solves the problem by changing the `unwrap` to a proper error. Note: in
case of `InteractError::Panic`, we continue to panic.
This patch makes sense with or without the merge of the PR on
`deadpool`.
While https://github.com/matrix-org/matrix-rust-sdk/pull/6017 is mostly
functional, there are two issues:
- I did not process `changes.room_key_bundles_fully_downloaded` in
`matrix-sdk-sqlite`, meaning any updates made via `Changes` would not be
persisted;
- I used a non-encrypting `JsValue` serialisation for the same field in
`matrix-sdk-indexeddb`, which causes errors when passed to the
decryption-enabled deserializer.
Solutions:
- Process the aforementioned changes such that keys are added to SQLite;
- Use a non-encrypting deserialiser, since this is effectively a
hash-set, and the contents aren't sensitive.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
For some reason, the automatic WAL checkpoints don't seem to be working as expected. Since we should periodically run VACUUM operations, we might as well add checkpoints before vacuuming (so the WAL size is reset and can grow to fit the whole DB) and after (so we clean up after that).