Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix getCache() internal key filtering #671

Merged
merged 2 commits into from
Dec 18, 2015

Conversation

sdesai
Copy link
Contributor

@sdesai sdesai commented Dec 17, 2015

I didn't get a chance to get the context around this PR from Michael in person before he stepped out on vacation: #640 but it seems to have regressed model.getCache() behavior, by allowing some internal keys to remain in the results of model.getCache() (e.g. refN, ref-index, etc). It seems to be a pretty conscious change, so not sure if it was intentional.

However, in the absence of this context, it seems like the desired behavior is to strip ALL internal keys from the cache, when returning a copy through getCache().

This PR aims to fix the above regression, and also fix what seems to be a gap in the original implementation, where $size would still be left in the results of getCache() at the leaf/sentinel nodes, when cloning boxed values. I don't think this was intentional.

Unit tests added, to make sure:

  1. Stripping refN, ref-index doesn't result in references breaking when the copy of the cache is used to re-hydrate a new model
  2. Make sure no internal keys are left in the cache-copy returned by getCache()

@jhusain @michaelbpaulson @trxcllnt - eyes appreciated, especially since I'm making assumptions about the original design intention.

@trxcllnt
Copy link
Contributor

@sdesai 😍 thanks! cc: @ekosz

@@ -40,7 +58,7 @@ function _copyCache(node, out, fromKey) {
var isUserCreatedcacheNext = !node[$modelCreated];
var value;
if (isObject || isUserCreatedcacheNext) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was another part of the original implementation I didn't understand the motivation for.

I'm not sure what the cacheNext.value === 'object' check was trying to do. We didn't end up cloning cacheNext.value anyway (that is, it's not like we deep cloned the wrapper if we discovered that the value was an 'object').

It seems to imply we only want to maintain the wrapper, for values which are objects (or for nodes which are pre-wrapped by the user - that makes sense), and I don't understand the motivation for the 'values which are objects' decision.

@ThePrimeagen
Copy link
Contributor

@sdesai All is correct. The motivation for 'values which are objects' decision is a subtle one.

var m = new Model();
var m2 = new Model();

// set a complex object.
m.setValue(['foo'], {bar: 'baz'}).subscribe();

// Set the cache from m to m2
m2.setCache(m.getCache());

Without the check for objectyness the following would happen.

m2.get(['foo']).subscribe(log, log, log.bind(null, 'i completed!'));

This would simply console out i completed! because the underlying cache changed from m to m2.

m and m2's cache would be

// m
{
    foo: {
        $type: 'atom',
        value: {
            bar: 'baz'
        }
    }
}

//m2
{
    foo: {
            bar: {
                $type: 'atom',
                value: 'baz'
            }
    }
}

Hope that helps!

@sdesai
Copy link
Contributor Author

sdesai commented Dec 18, 2015

I see. Thanks. Makes sense. It's to distinguish between branches and atoms, and we don't need to take on the cost of the wrapper/clone for the non-object case, because there's nothing ambiguous to distinguish against.

Gonna merge this.

sdesai added a commit that referenced this pull request Dec 18, 2015
Fix getCache() internal key filtering
@sdesai sdesai merged commit d80e48e into Netflix:0.x Dec 18, 2015
@trxcllnt
Copy link
Contributor

@sdesai is this going to be merged into master soon?

@sdesai
Copy link
Contributor Author

sdesai commented Dec 24, 2015

Hey Paul, I believe master has the original (prefix) based filter already. Otherwise can merge it in. This one does have the additional fix for sentinel wrappers

@trxcllnt
Copy link
Contributor

@sdesai from what I can tell, master's version of isInternalKey is still checking for specific internal keys.

@sdesai
Copy link
Contributor Author

sdesai commented Dec 24, 2015

Ok. I'm OOO for Xmas, but will merge it in, in between things

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants