8 Commits

Author SHA1 Message Date
213be852b8 Fix add_version calls when no history exists on the server (#149)
This fixes a bug in 25911b44a6 where the
check in the storage implementation was too strict (not allowing
`clients.latest_version_id == Uuid::nil()`), causing spurious failures.

Well, two bugs, one in each storage implementation.
2025-08-20 15:21:04 -04:00
b858febbca Apply fixes from @ryneeverett
Co-authored-by: ryneeverett <ryneeverett@gmail.com>
2025-07-14 12:30:01 -04:00
25911b44a6 More explicit requirements regarding add_version
The core crate calls `get_client` and verifies the `latest_version_id`
before it invokes `add_version`. With the SQLite backend, transactions
lock the entire database, so these two queries cannot be interleaved
with any changes to the `latest_version_id` and there's no possibility
of incorrect updates. With Postgres (#129) the effect is similar: the
read performed by `get_client` locks that row and prevents other
transactions from writing to it.

However, the storage trait should not rely on this behavior --
`add_version` should verify that it is adding a new version on top of
the correct parent version.
2025-07-13 13:04:38 -04:00
7559364017 Make Storage methods async
This will better support concurrent requests.
2025-07-11 17:37:14 -04:00
5332d90c57 Improve error handling in the inmemory storage implementation. (#79)
Improve error handling in the inmemory storage

This addresses a TODO, in a type that is really only used for testing.

This also adds a test for a similar circumstance -- adding the same
version twice -- in the SQLite storage, but it is already handled
correctly.
2025-01-13 08:32:27 -05:00
1828a31a24 Make storage transactions specific to a client_id (#67)
Transactions for different client_ids cannot interfere with one another,
so this provides an opportunity for the sort of concurrency that a
mult-client hosting solution might need. For example, a postgres backend
could lock the client row in each transaction.
2024-11-27 00:09:03 -05:00
4029c03479 Support sequential consistency in SQLite implementation (#64)
This is a bit tricky because the `Storage` trait is `Send + Sync`, but
an SQLite connection is neither. Since this is not intended for
large-scale use, the simple solution is just to open a new SQLite
connection for each transaction. More complex alternatives include
thread-local connection pools or a "worker thread" that owns the
connection and communicates with other threads via channels.

This also updates the InMemoryStorage implementation to be a bit more
strict about transactional integrity, which led to a number of test
changes.
2024-11-26 16:22:35 -05:00
47ce4c1e3b Split the server into three crates (#56)
This will make it easier to build variations on the server, or embed it
into larger projects.
2024-11-17 15:12:42 -05:00