Hi,

> Am 08.10.2019 um 12:05 schrieb Jonathan van Alteren 
> <jvalte...@objectguild.com>:
> 
> Hello all,
> 
> We are having some issues with using Voyage/Mongo for a customer project that 
> I'd like to get your feedback on. 
> 
> The customer application is a form based business web application using 
> Seaside with object persistence using Voyage with MongoDB on Pharo 7.0. The 
> application is deployed on a dedicated Linux production server running 
> MongoDB version 4.2.
> 
> The application is used to manage meeting agendas and minutes. After opening 
> the agenda view of a future meeting, the user can add an item to the agenda 
> by clicking a button. This calls an item editor component which answers when 
> a Save or Cancel button is clicked. The agenda view component itself also has 
> a Save button, which performs a Voyage save of the object aggregate (agenda + 
> items).
> 
> We've encountered an issue where a user makes changes to an agenda, but does 
> not click the Save button. Instead, the user closes the browser or uses the 
> navigation to go to a different part of the application. When navigating back 
> to the original agenda, the changes made previously (e.g. items added) are 
> still being displayed, even though they were never explicitly saved.
> 
> It does not matter if we select the agenda aggregate object instance using 
> Voyage or access it in a different way. Changes to the state of the object 
> are retained, even though a Voyage save was never sent to the agenda 
> instance. The cause seems to be that the Voyage repository caches the object 
> instance and thus on select, it returns an object that is in a different 
> state than how it was persisted.
> 
> This all seems to come down to object transactionality. 
> 
> We have a need to 'cancel' changes made to an object instance. Before working 
> with Pharo/Smalltalk in a non-image based environment, I was used to do this 
> by retrieving the original object from persistence again. This also allowed 
> for a convenient way to detect changes to an object's state, which we are 
> missing at the moment too.
> 
> We know that moving to GemStone can help us with these issues, but our 
> current planning of customer projects does not allow us to do this within the 
> next 3 months. And we really need to find a way to tackle these issues .
> 
> 
> Your feedback is greatly appreciated!
> 
this is none to be confusing to a lot of people. If you map a memory object 
graph to a database there are no intrinsic points of transactions unless you 
put them into your application model. Gemstone or any transaction based 
handling won‘t help you if your use case is not as coarse grained as discarding 
all modified data and not just some. Or you need to hop into nested 
transactions which are supported by Gemstone IMHO but there is rules to care 
about, too, if you want to use them.

Regarding your application you modify data and this is kept. The cache in mongo 
is a weak dictionary. This means that if you get the object with the changes a 
second time it means these objects are referenced somewhere. Seaside sessions 
seems to be the obvious thing here. If you have a reachable object (e.g. server 
singleton -> handler -> seaside -> seaside session -> business object) then 
mongo keeps the object in its cache because it needs to be able to establish 
identity on further queries. Ein emoving all the changes from an object you 
keep in memory wouldn‘t be really good if the persistence layer would do it. 

The problem is obvious but the solution is not. We could make the cache session 
or request based which would circumvent the problem. But if an object would be 
attached to something outside the session/request which you cannot forbid it 
causes real problems like multiple copies to an identical object.

I don‘t know what you mean with object transactionality because it makes no 
sense in my head. But you have basically two approaches to solve the problem. 
If you would use magritte you would have it at hand. There each UI component 
gets just a memento of the business object for modification. You need to commit 
the UI component in order to modify the business object. So you can commit on 
user interaction and separately on persistence which allows a huge set of use 
cases.
The other one I‘m working on since a while is a proper modification tracking. 
In this you change the objects directly but have a registry with the dirty 
objects which you can act upon. I have a sample modification tracker that uses 
readOnly object write barrier for objects. On write attempt it registers the 
object and the write operation as command pattern. You can undo modifications 
of a single object where all commmands are undone on that object. Or you abort 
all modifications at once. It is basically working but has the problems on 
concurrent access. As the mongo cache is image wide two concurrent requests 
interfere with each other.
So you can see that the problem is not that easy to solve.

TL;DR a memento approach might your best and cleanest option right now.

Norbert
> 
> Kind regards,
> 
> 
> Jonathan van Alteren
> 
> Founding Member | Object Guild
> jvalte...@objectguild.com
> 


Reply via email to