Hi Mattias, this looks quite similar to what I have done so I guess I'm on the right track :)
Thanks again and best regards, Georg On 10.05.2010 12:59, Mattias Persson wrote: > All right, I see what you mean. You're basically wondering if Neo4j > already has implemented some of the functionality you're trying to > build, right? No, there's no such feature, but you could build it > yourself. I'll give you an example of a solution. > > Say you have a "root node" to represent the revisions. That root node > has a revision counter (which is the last committed revision) and a > linked list of nodes representing the commits, containing f.ex. a commit > message. I just added a class which manages a linked list of nodes in > the http://components.neo4j.org/neo4j-utils/ component, see the > NodeStack class. You can use that or see how it's implemented. > > // Create the root node > Node rootNode = graphDb.createNode(); > graphDb.getReferenceNode().createRelationshipTo( rootNode, > RelTypes.REVISION_ROOT ); > NodeStack revisionList = new NodeStack( rootNode, > RelTypes.REVISION_LIST ); > > // Add a revision > Node revisionNode = revisionList.push(); > int revision = (Integer) rootNode.getProperty( > "last_commited_revision", 0 ); > rootNode.setProperty( "last_commited_revision", ++revision ); > revisionNode.setProperty( "message", "My commit message" ); > revisionNode.setProperty( "revision", revision ); > // You could also index the revisions with LuceneIndexService. > > The "Add a revision" code could be wrapped in a TransactionWrapper (as > you've already done) so that the revisions are stored right there and > then, not in the handler. That would be my bet. > > 2010/5/10 Georg M. Sorst <georgso...@gmx.de <mailto:georgso...@gmx.de>> > > Hi Mattias, > > thanks for your replies, finally getting back myself. Some > clarifications about questions 2 and 3, getting data in and out of > the transaction: What I am looking for is a way to do something like > this: > > int revision = transaction.finish(commitMessage, userId); > > I've actually got this working by using a TransactionWrapper which > intercepts these calls and puts the data in a global Thread map. The > commit message and user id are then read out from the map by the > transaction event handler. This works fine, but passing around the > data in a global data structure just has an awful code smell. > > While another way would be to have the service layer read out the > current revision and write the commit message itself etc. this > smells just as bad IMHO with duplicated code and an unclear calling > chain. > > So what I am looking for is a way to pass the data to the > transaction as explained above, or maybe also something like: > > transaction.setAttribute("message", "my commit message"); > tx.finish(); > int revision = transaction.getAttribute("revision"); > > Now I see my first snippet is quite specific to implementing a > versioning system, but the later might be useful for other cases > too. Is there any way to do this or is anything planned? > > Now that I've actually wrote about it my solution doesn't sound so > bad really :) > > Best regards, > Georg > > > > On 03.05.2010 17:03, Mattias Persson wrote: > > 2010/5/1 Georg M. Sorst<georgso...@gmx.de > <mailto:georgso...@gmx.de>> > > Hi Mattias, hi list > > that's just what I've been looking for, congratulations on > the amazing > progress you are making on Neo4j! > > I am actually trying to use the TransactionEventHandler to > implement > automatic versioning similar to what was discussed a while > ago. The > beforeCommit() handler seems like a perfect fit and provides > all the data I > need. > > Still, I have one problem: in beforeCommit() I fetch and > increment a > revision number that's stored in a special node and use that > number to build > the current revision structure. This brings up a few questions: > > 1. How atomic are Neo4j commits? Will two concurrent commits > interfere when > getting and incrementing the revision number? > > Transactions are atomic, but if transaction T1 reads a value and > modifies > it, but before it modifies it T2 reads the same value in the > intent to > modify it, there's a possibility that T1 and T2 will read the > same value. > And if they both increment the value they both will set it to > the same value > (which would not be the intended behavior). What you would need > to do is to > make sure T1 has a write-lock on the node which carries this > revision > property, that way T2 will have to wait until T1 is committed > and will read > the correct value. There's no "nice" way of locking a node other > than > setting/removing a property or creating/deleting relationships > on it, so I'd > say an ugly, but perfectly working way would be to do something > like this: > > nodeWithRevision.removeProperty( "a dummy property" ); > int counter = (Integer) nodeWithRevision.getProperty( > "revision" ); > > so that neo4j is forced to take a write-lock on that node before > getting the > "counter" property. A nicer way will be exposed soon to do this > instead! > > 2. How can I return the revision number from the > TransactionEventHandler so > > I can use it in the caller (my service classes in this case)? > > I'd say it'd be better if the service classes could read the > revision from > the node which has the revision directly, that way you'd always > get the > committed value. Maybe your handler could have a getRevision() > method which > reads the "revision" property from that revision node. > > > 3. The caller should be able to pass data to the > transaction, for now just > the commit message. Of course I can temporarily store this > in a node or > attach it to the thread etc. but that just seems wrong. How > can I do this > right? > > I don't know what you mean by "pass data to the transaction" if > it would not > be to store something in the graph, f.ex. a property on a node. > What exactly > do you mean by that? > > > Thanks and best regards, > Georg > > > On 27.04.2010 10:15, Mattias Persson wrote: > > Hi everyone! > > I'm quite pleased to announce that the new event > framework has been > committed in kernel 1.1-SNAPSHOT. After feedback from > you guys the > framework > got quite small and cosy. Here's a summary. > > *TransactionEventHandler* > can be registered at a GraphDatabaseService and will > thereafter recieve > diffs of modifications made in each transaction before > and after they are > committed. The transaction can still be modified in > beforeCommit() and > that > method can also throw an exception to prevent the > transaction from > committing, causing a TransactionFailureException to be > thrown from the > code > which is committing the transaction. > > *KernelEventHandler* > can be registered at a GraphDatabaseService and will > receive notifications > about when a shutdown is about to occur for the > GraphhDatabaseService > instance. It will also receive notifications about > "kernel panics" which > is > a state which the kernel can come to from where it > cannot continue without > needing to be restarted. An example of such an error > would be a hard drive > breakdown or when no more space is left on the device > the graph database > is > running on. > > The next step is to write an "auto indexer" for the > IndexService so that > that you won't have to do the manual indexService.index( > node, key, value > ) > anymore. Another thing would be to remove (deprecate) the > IndexService#shutdown() method as it no longer would be > required. > > So it'd be great if you guys would try this out and tell > us how it feels. > > > -- > Georg M. Sorst > Dipl. Inf. (FH) > > http://vergiss-blackjack.de > > Ignaz-Harrer-Str. 13 / Top 19 > 5020 Salzburg > Österreich > > Tel: +43 (0)650 / 53 47 200 > > > > > > -- > Georg M. Sorst > Dipl. Inf. (FH) > > http://vergiss-blackjack.de > > Ignaz-Harrer-Str. 13 / Top 19 > 5020 Salzburg > Österreich > > Tel: +43 (0)650 / 53 47 200 > > > > > -- > Mattias Persson, [matt...@neotechnology.com > <mailto:matt...@neotechnology.com>] > Hacker, Neo Technology > www.neotechnology.com <http://www.neotechnology.com> -- Georg M. Sorst Dipl. Inf. (FH) http://vergiss-blackjack.de Ignaz-Harrer-Str. 13 / Top 19 5020 Salzburg Österreich Tel: +43 (0)650 / 53 47 200 _______________________________________________ Neo mailing list User@lists.neo4j.org https://lists.neo4j.org/mailman/listinfo/user