Single document flushing doesn't obey cascade #301

Closed
leek opened this Issue May 5, 2012 · 8 comments

Comments

Projects
None yet
5 participants
Contributor

leek commented May 5, 2012

Is this intentional? Or am I using/understanding something wrong?

<?php

class Post
{
    /**
     * @MongoDB\ReferenceOne(targetDocument="User", cascade={"persist"})
     */
    protected $user;

    /**
     * @MongoDB\PrePersist
     */
    public function prePersist()
    {
        $this->getUser()->setField('changed');
    }
}

class User
{
    /**
     * @MongoDB\String
     */
    protected $field;
}

$dm->persist($post);
$dm->flush($post);

$this->assertEquals('changed', $post->getUser()->getField());
Owner

jmikola commented May 17, 2012

According to UnitOfWork::doPersist() (invoked through DocumentManager::persist()), the following will happen in order:

  1. UoW::persistNew() on the post
    1. Invoke lifecycle callbacks for pre-persist
    2. Dispatch any pre-persist events
    3. Schedule the document for insertion
  2. UoW::cascadePersist() on the post
  3. Invoke UoW::doPersist() on embedded documents and referenced docs with cascading, which means user

What are you seeing?

Contributor

leek commented May 18, 2012

What are you seeing?

Speaking of the example I gave, I'm not seeing the field key of the User reference being updated to changed. Does cascade={"persist"} not flush to the database? There doesn't seem to be a cascade={"flush"}...

Owner

jmikola commented May 18, 2012

If document A defines cascade=("persist") on its relation to B, that means B will also be persisted when you persist A. Persisting involves scheduling documents for insertion. By the time you flush, only scheduled operations will execute through the Mongo connection.

I just realized you're doing a single document flush. That might be restricting insertion to only the post document. You can follow the code through UnitOfWork::commit() to see what's really going on here.

Alternatively, you can pass an array of documents to DocumentManager::flush(), so I'd start there (passing in $post and its $user).

Contributor

leek commented May 18, 2012

@jmikola I hear what you're saying, and I realize I could specifically flush $user myself. I guess that is why I wanted to clarify behavior - IMO, single document flush or not, the cascade setting should be obeyed. If it isn't, then perhaps adding a cascade={"flush"} option would make sense.

Owner

jmikola commented May 18, 2012

Since single-document flushes didn't exist at the time the cascade methods were conceived, this may be worth considering. Ping @jwage.

Owner

jwage commented Oct 11, 2012

Yes I think it might make sense to do this.

@vmattila vmattila added a commit to vmattila/mongodb-odm that referenced this issue May 2, 2014

@vmattila vmattila Implemented a test to confirm behavior of issue #301 1e46790
Contributor

vmattila commented May 2, 2014

I was just about to write a failing test case for this behavior but it did not fail - so the behavior seems to be correct.

What I started to think is the behavior of updates. If I update a referenced document but flush only the main document, I'd still somehow expect that the referenced document is also flushed... so there is a slight difference in behavior whether it's insert or update operation. Especially if the change tracking policy is DEFERRED_EXPLICIT things are getting more confusing...

Somehow I like the idea of cascade="flush" as @leek suggested.

Member

malarzm commented Jun 8, 2015

We'll use #869 to track feature request

malarzm closed this Jun 8, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment