# Implementing VersionStamps in bindings

**URL:** <https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250>\
**Category:** FoundationDB Core\
**Created:** [April 24, 2018, 7:05pm UTC](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250 "2018-04-24T19:05:11Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![KrzysFR](https://sea1.discourse-cdn.com/foundationdb/user_avatar/forums.foundationdb.org/krzysfr/32/43_2.png) [@KrzysFR](https://forums.foundationdb.org/u/KrzysFR)\
**Post date:** [April 25, 2018, 8:50am UTC](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250/7 "2018-04-25T08:50:37Z")

</div>

> [@alloc](#):
>
> What are your order of operations? The get\_versionstamp method is somewhat weird, but you have to call the future before it is committed, and then that future will be ready only after the commit. So something like:
> 
> CompletableFuture\<byte\> vsFuture = tr.getVersionstamp();  
> tr.commit().join(); // blocking call to wait on commit  
> byte versionstamp = vsFuture.join(); // non-blocking call to get versionstamp
> 
> (But, like, in C# instead of Java.) I think you can get used\_during\_commit if you call getVersionstamp after commit rather than before.

Ok so this is a bit confusing. I’m calling the getVersionstamp method AFTER the commit has completed, but I’m getting an error `Operation issued while a commit was outstanding` which seems wrong to me: The commit was already completed, so it was not “_while_” and there was no “_outstanding_” commit? Maybe the wording of the error message is wrong?

> […] but you have to call the future before it is committed, and then that future will be ready only after the commit

I’m having some issues with this API, because it will seem a little bit weird - from a .NET coder’s point of view - when dealing with tasks, AND it does not appear to compose well with retry loops and multiple layers.

My test creates and commits the transaction manually, but typical application will never do that and go through one of the retry loops (the `db.run(...)` in Java):

```csharp

Task<IActionReuslt> SomeControllerMethod(....)
{
  //... check args ...
  await db.WriteAsync((tr) =>
  {   
     // traditional write operations
     tr.ClearRange(....);
     tr.Set(..., ...);
     // new Versionstamp API
     tr.SetVersionstampedKey(MAKE_KEY_WITH_VERSION_STAMP(), ....);

  }, HttpContext.Cancel);
  //...
  return View(....);
}

```

_obviously, the db code would be inside some Business Logic class, and not inlined in the controller!_

If the code wanted to obtain the actual Versionstamp, as well as some other result extracted from the database, both at the same time, it will look very ugly:

```csharp
//...
Task<Versionstamp> stampTask; // out of scope
Slice result = await db.ReadWriteAsync((tr) =>
{
     var val = await tr.Get('SOME_KEY', ....);

     tr.SetVersionstampedKey(MAKE_KEY_WITH_VERSION_STAMP(), ..);
     stampTask = tr.GetVersionstamp();

     return val;
}, cancel);
Versionstamp stamp = await stampTask; // need an extra await here!
//...
var data = DoSomethingWithIt(result, stamp);
return View(new SpomeViewModel { Data = data, ... });

```

Having to hoist a task outside the scope and do an additional await looks _weird_ in moden .NET code.

The retry loop could return the Versionstamp task alongside the result like this, but again it does not look nice:

```csharp
(Slice result, Task<Versionstamp> stampTask) = await db.ReadWriteAsync((tr) =>
{
     Slice val = await tr.Get('SOME_KEY', ....);

     tr.SetVersionstampedKey(MAKE_KEY_WITH_VERSION_STAMP(), ..);

     return (val, tr.GetVersionstamp());
}, cancel);

Versionstamp stamp = await stampTask; // still need an extra await here

```

I _think_ what the user would expect to happen is that the retry loops returns the Versionstamp directly not a Future:

```csharp
(Slice result, Versionstamp stamp) = await db.ReadWriteAsync((tr) =>
{
     Slice val = await tr.Get('SOME_KEY', ....);

     tr.SetVersionstampedKey(MAKE_KEY_WITH_VERSION_STAMP(), ..);

     return (val, tr.GetVersionstamp());
}, cancel);

```

The inner lambda would have signature `Func<IFdbTransaction, Task<TResult, Task<VersionStamp>>>`, which is a mouthfull, The retryloop method wants to return a `Task<TResult, VersionStamp>`, and not a `Task<TResult, Task<Versionstamp>>` so some generic magic needs to be done.

It may have some effects on the overall API because, in .NET, you cannot have overloads whose signature only differ by the return value. So it would not be easy to have an overload of `ReadWriteAsync(...)` that returns plain results, and another one which also return a tuple with the resolved timestamp. You’d probably have to change the method name, or add some arguments to disambiguate.

I _could_ have a `ReadWriteWithVersionStampAsync<TResult>() => Task<(TResult, VersionStamp>)` overload, but then it may cause issue when composing multiple libraries:

> Let’s say in an HTTP request controller, the outer scope starts a retry loop, and then pass along the transaction to some business logic, which then calls into other Layers (Document, Blob, Index, …). If one layer is refactored somehow, and starts using versionstamps. It would have an impact on the outerscope (in the HTTP controller code) because it needs to _know_ to call GetVersionstamp, _before_ the commit, and extract the value _after_ it has suceeded, and _outside_ the scope of the retry loop. How do I pass back the actual versionstamp into the original layer (which has long since returned and be garbage collected).

It looks like you need dedicated transactions that are fully handled by the Layer code, and will not be able to compose with other layer inside a single transaction ?

---

_[View the full topic](https://forums.foundationdb.org/t/implementing-versionstamps-in-bindings/250)._
