Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
Co-authored-by: igorT <[email protected]>
Co-authored-by: pete-the-pete <>
  • Loading branch information
igorT committed May 13, 2020
1 parent 4f12aa0 commit 80417a4
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 13 deletions.
24 changes: 24 additions & 0 deletions packages/-ember-data/tests/integration/identifiers/cache-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,29 @@ module('Integration | Identifiers - cache', function(hooks) {
'getOrCreateRecordIdentifier() return identifier'
);
});

test('identifiers are cached by lid and can be looked up by lid igor', async function(assert) {
const houseHash = {
type: 'house',
id: '1',
attributes: {
name: 'Moomin',
},
};
const cache = identifierCacheFor(store);
const identifier = cache.getOrCreateRecordIdentifier(houseHash);

assert.strictEqual(
identifier,
cache.getOrCreateRecordIdentifier({lid: identifier.lid}),
'getOrCreateRecordIdentifier() return identifier'
);

assert.strictEqual(
identifier,
cache.getOrCreateRecordIdentifier({ type: 'not house', lid: identifier.lid}),
'getOrCreateRecordIdentifier() return identifier'
);
});
});
});
40 changes: 29 additions & 11 deletions packages/store/addon/-private/identifiers/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DEBUG } from '@glimmer/env';

import coerceId from '../system/coerce-id';
import normalizeModelName from '../system/normalize-model-name';
import { DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET } from '../ts-interfaces/identifier';
import { DEBUG_CLIENT_ORIGINATED, DEBUG_IDENTIFIER_BUCKET, Identifier } from '../ts-interfaces/identifier';
import { addSymbol } from '../ts-interfaces/utils/symbol';
import isNonEmptyString from '../utils/is-non-empty-string';
import isStableIdentifier, { markStableIdentifier, unmarkStableIdentifier } from './is-stable-identifier';
Expand Down Expand Up @@ -137,7 +137,7 @@ export class IdentifierCache {
/**
* @internal
*/
private _getRecordIdentifier(resource: ResourceIdentifierObject, shouldGenerate: true): StableRecordIdentifier;
private _getRecordIdentifier(resource: ResourceIdentifierObject | Identifier, shouldGenerate: true): StableRecordIdentifier;
private _getRecordIdentifier(
resource: ResourceIdentifierObject,
shouldGenerate: false
Expand All @@ -157,18 +157,31 @@ export class IdentifierCache {
return resource;
}

let lid = coerceId(resource.lid);
let identifier: StableRecordIdentifier | undefined = lid !== null ? this._cache.lids[lid] : undefined;

if (identifier !== undefined) {
return identifier;
}

const _resource = resource as ResourceIdentifierObject;
let type = normalizeModelName(_resource.type);
let id = coerceId(_resource.id);

if (shouldGenerate === false) {
if (!type || !id) {
return;
}
}

// `type` must always be present
if (DEBUG) {
if (!isNonEmptyString(resource.type)) {
if (!isNonEmptyString(_resource.type)) {
throw new Error('resource.type needs to be a string');
}
}

let type = normalizeModelName(resource.type);
let keyOptions = getTypeIndex(this._cache.types, type);
let identifier: StableRecordIdentifier | undefined;
let lid = coerceId(resource.lid);
let id = coerceId(resource.id);

// go straight for the stable RecordIdentifier key'd to `lid`
if (lid !== null) {
Expand Down Expand Up @@ -264,7 +277,7 @@ export class IdentifierCache {
`id` + `type` or `lid` will return the same `lid` value)
- this referential stability of the object itself is guaranteed
*/
getOrCreateRecordIdentifier(resource: ResourceIdentifierObject | ExistingResourceObject): StableRecordIdentifier {
getOrCreateRecordIdentifier(resource: ResourceIdentifierObject | ExistingResourceObject | Identifier): StableRecordIdentifier {
return this._getRecordIdentifier(resource, true);
}

Expand Down Expand Up @@ -325,7 +338,7 @@ export class IdentifierCache {
let newId = coerceId(data.id);

const keyOptions = getTypeIndex(this._cache.types, identifier.type);
let existingIdentifier = detectMerge(keyOptions, identifier, data, newId, this._cache.lids);
let existingIdentifier = detectMerge(this._cache.types, identifier, data, newId, this._cache.lids);

if (existingIdentifier) {
identifier = this._mergeRecordIdentifiers(keyOptions, identifier, existingIdentifier, data, newId as string);
Expand Down Expand Up @@ -519,15 +532,16 @@ function performRecordIdentifierUpdate(
}

function detectMerge(
keyOptions: KeyOptions,
typesCache: ConfidentDict<KeyOptions>,
identifier: StableRecordIdentifier,
data: ResourceIdentifierObject | ExistingResourceObject,
newId: string | null,
lids: IdentifierMap
): StableRecordIdentifier | false {
const { id, type, lid } = identifier;
if (id !== null && id !== newId && newId !== null) {
const existingIdentifier = keyOptions.id[newId];
let keyOptions = getTypeIndex(typesCache, identifier.type);
let existingIdentifier = keyOptions.id[newId];

return existingIdentifier !== undefined ? existingIdentifier : false;
} else {
Expand All @@ -536,6 +550,10 @@ function detectMerge(
if (id !== null && id === newId && newType === type && data.lid && data.lid !== lid) {
const existingIdentifier = lids[data.lid];

return existingIdentifier !== undefined ? existingIdentifier : false;
} else if (id !== null && id === newId && newType !== type && data.lid && data.lid === lid) {
let keyOptions = getTypeIndex(typesCache, newType);
let existingIdentifier = keyOptions.id[id];
return existingIdentifier !== undefined ? existingIdentifier : false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,13 @@ export default class InternalModelFactory {
constructor(public store: CoreStore) {
this.identifierCache = identifierCacheFor(store);
this.identifierCache.__configureMerge((identifier, matchedIdentifier, resourceData) => {
const intendedIdentifier = identifier.id === resourceData.id ? identifier : matchedIdentifier;
const altIdentifier = identifier.id === resourceData.id ? matchedIdentifier : identifier;
let intendedIdentifier = identifier;
if (identifier.id !== matchedIdentifier.id) {
intendedIdentifier = identifier.id === resourceData.id ? identifier : matchedIdentifier;
} else if (identifier.type !== matchedIdentifier.type) {
intendedIdentifier = identifier.type === resourceData.type ? identifier : matchedIdentifier;
}
let altIdentifier = identifier === intendedIdentifier ? matchedIdentifier : identifier;

// check for duplicate InternalModel's
const map = this.modelMapFor(identifier.type);
Expand Down

0 comments on commit 80417a4

Please sign in to comment.