Skip to content

[Feature Request] Pass-Through Transaction Read/WriteSet #30

@rrichardson

Description

@rrichardson

One feature of the Typescript etcd3 client is a Transaction class that offers the put*/get* API.

It does this by capturing every object (or at least its revision) in Read and Write sets, and passes them to conditional checks in the transaction execution itself.

This makes for a much more natural DB interaction experience.

e.g. in Rust it'd be something like:

let txn = client.txn()?; 

let foo = txn.get("bar/foo").await?; 
let baz = txn.get("bar/baz").await?;

let froboz = MyThing::merge(&[&foo, &baz]);
txn.put("bar/froboz", froboz.serialize()?)?;
txn.commit(); 

As mentioned above, the typescript implementation does this by capturing every object and the database's mod_revision
It then finds the lowest mod_revision and uses the Compare::mod_revision to ensure that the objects being written haven't been updated. This can be overly restrictive, but since it doesn't know the actual details of the updates, I think it's the best it can do.

We've been using this approach in hundreds of different service handlers across dozens of services and it has been working quite well.

We've not yet had to bypass this mechanism to create a Transaction object with the traditional fetch/compare/set operation.

Here are some pointers to the actual implementation:

WriteSet: https://github.com/microsoft/etcd3/blob/master/src/stm.ts#L100
ReadSet: https://github.com/microsoft/etcd3/blob/master/src/stm.ts#L100-L148
Txn Execution: https://github.com/microsoft/etcd3/blob/master/src/stm.ts#L497-L527

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions