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

Reply via email to