Chapter 12. Versioned current objects and updates


stasher::versionedptr<classptr>: associate a mcguffin with each object instance
Versioned current objects
Using version mcguffings
stasher::versioned_put: updating multiple versioned objects
stasher::versionscollected: a container for current object version mcguffins
Using stasher::versioned_put()


Managed objects, and specifically current object instances are internal application objects that get automatically updated whenever the corresponding object gets updated in the stasher object repository; but this is not an instantaneous process. Another application updates the object as part of its transaction. This results in a couple of round trips between the stasher server and the application, before a new internal application object gets created and replaces the the existing one. Until this process is done, the application still sees the old object, and only knows about the object's previous uuid.

In this situation, if the application sends its own transaction to update the object at the same time, the transaction will reference the previous object's uuid. It will fail with a stasher::req_rejected_stat error code. The stasher server requires the existing objects' uuids from any transaction that updates them, otherwise the entire transaction fails.

After getting a stasher::req_rejected_stat the application can expect that its internal managed object or current object instance is going to get updated with the new version of this object, at which point the application can try again to update the object. The application can choose to do nothing too. However, a stasher::req_rejected_stat error code does not imply, either way, whether the application has already received the new object, from the stasher object repository. The application may, or may not, already have the updated object.

The application can track each object that went into a transaction, and check if the object was already updated when a transaction fails with a stasher::req_rejected_stat; if not, wait until it does (since that's implied by the status code). But there's no need to do it, because the templates and functions described in this part will do all this hard work.

The templates described in this part keep track of which versions of which objects went into a transaction. They implement the following logic: do not notify the application in the event that a transaction failed with a stasher::req_rejected_stat until at least one of the objects that went into the transaction gets updated. If that already happened by the time that a transaction stasher::req_rejected_stated, the application gets notified immediately. Otherwise the application gets notified after one of the objects gets updated.

These templates and classes do not use any updating mechanism of their own. They work together with the stasher::current<classptr> class template, which is based on the stasher::manager->manage_object() update mechanism. All that happens here is that a stasher::req_rejected_stat transaction status is held, and the application does not get notified, until at least one of the objects gets updated, if it hasn't already.

When multiple objects get updated by a transaction, the stasher::req_rejected_stat error does not explicitly identify which one it was, but the application now has at least one updated stasher::current<classptr> object. The application can try again, and another stasher::req_rejected_stat likely means that the application finally has the current version of everything. stasher::req_rejected_stats are expected to be quite rare, and infrequent, so all this extra work should not happen very often. Furthermore, the application is not required to retry the transaction. There's always the option of changing its mind, and doing something else, instead.