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.
This commit is contained in:
Dustin J. Mitchell 2024-11-27 00:09:03 -05:00 committed by GitHub
parent 4029c03479
commit 1828a31a24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 246 additions and 319 deletions

View file

@ -70,9 +70,9 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, version_id).unwrap();
txn.add_version(client_id, version_id, NIL_VERSION_ID, vec![])?;
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(version_id).unwrap();
txn.add_version(version_id, NIL_VERSION_ID, vec![])?;
txn.commit()?;
}
@ -114,8 +114,8 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, NIL_VERSION_ID).unwrap();
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(NIL_VERSION_ID).unwrap();
txn.commit().unwrap();
}

View file

@ -82,9 +82,11 @@ pub(crate) async fn service(
}
Err(ServerError::NoSuchClient) => {
// Create a new client and repeat the `add_version` call.
let mut txn = server_state.server.txn().map_err(server_error_to_actix)?;
txn.new_client(client_id, NIL_VERSION_ID)
.map_err(failure_to_ise)?;
let mut txn = server_state
.server
.txn(client_id)
.map_err(server_error_to_actix)?;
txn.new_client(NIL_VERSION_ID).map_err(failure_to_ise)?;
txn.commit().map_err(failure_to_ise)?;
continue;
}
@ -111,8 +113,8 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, Uuid::nil()).unwrap();
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(Uuid::nil()).unwrap();
txn.commit().unwrap();
}
@ -181,8 +183,8 @@ mod test {
// Check that the client really was created
{
let mut txn = server.server_state.server.txn().unwrap();
let client = txn.get_client(client_id).unwrap().unwrap();
let mut txn = server.server_state.server.txn(client_id).unwrap();
let client = txn.get_client().unwrap().unwrap();
assert_eq!(client.latest_version_id, new_version_id);
assert_eq!(client.snapshot, None);
}
@ -197,8 +199,8 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, version_id).unwrap();
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(version_id).unwrap();
txn.commit().unwrap();
}

View file

@ -64,9 +64,9 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, Uuid::new_v4()).unwrap();
txn.add_version(client_id, version_id, parent_version_id, b"abcd".to_vec())
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(Uuid::new_v4()).unwrap();
txn.add_version(version_id, parent_version_id, b"abcd".to_vec())
.unwrap();
txn.commit().unwrap();
}
@ -128,9 +128,9 @@ mod test {
// create the client and a single version.
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, Uuid::new_v4()).unwrap();
txn.add_version(client_id, test_version_id, NIL_VERSION_ID, b"vers".to_vec())
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(Uuid::new_v4()).unwrap();
txn.add_version(test_version_id, NIL_VERSION_ID, b"vers".to_vec())
.unwrap();
txn.commit().unwrap();
}

View file

@ -48,8 +48,8 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, Uuid::new_v4()).unwrap();
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(Uuid::new_v4()).unwrap();
txn.commit().unwrap();
}
@ -75,10 +75,9 @@ mod test {
// set up the storage contents..
{
let mut txn = storage.txn().unwrap();
txn.new_client(client_id, Uuid::new_v4()).unwrap();
let mut txn = storage.txn(client_id).unwrap();
txn.new_client(Uuid::new_v4()).unwrap();
txn.set_snapshot(
client_id,
Snapshot {
version_id,
versions_since: 3,