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

chore: refactor IdentityCache to make resource more opaque #8736

Merged
merged 9 commits into from
Jul 27, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
more tweaks
runspired committed Jul 26, 2023
commit 97dac5a0214975921431e973ce2477415d9a773b
27 changes: 15 additions & 12 deletions packages/json-api/src/-private/cache.ts
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import { LOG_MUTATIONS, LOG_OPERATIONS } from '@ember-data/debugging';
import { DEBUG } from '@ember-data/env';
import { graphFor, peekGraph } from '@ember-data/graph/-private';
import type { LocalRelationshipOperation } from '@ember-data/graph/-private/graph/-operations';
import type { Graph } from '@ember-data/graph/-private/graph/graph';
import type { ImplicitRelationship } from '@ember-data/graph/-private/graph/index';
import type BelongsToRelationship from '@ember-data/graph/-private/relationships/state/belongs-to';
import type ManyRelationship from '@ember-data/graph/-private/relationships/state/has-many';
@@ -118,11 +119,13 @@ export default class JSONAPICache implements Cache {
declare __cache: Map<StableRecordIdentifier, CachedResource>;
declare __destroyedCache: Map<StableRecordIdentifier, CachedResource>;
declare __documents: Map<string, StructuredDocument<ResourceDocument>>;
declare __graph: Graph;

constructor(storeWrapper: CacheCapabilitiesManager) {
this.version = '2';
this.__storeWrapper = storeWrapper;
this.__cache = new Map();
this.__graph = graphFor(storeWrapper);
this.__destroyedCache = new Map();
this.__documents = new Map();
}
@@ -285,7 +288,7 @@ export default class JSONAPICache implements Cache {
this.__cache.set(op.value, cache);
this.__cache.delete(op.record);
}
graphFor(this.__storeWrapper).update(op, true);
this.__graph.update(op, true);
}
}

@@ -308,7 +311,7 @@ export default class JSONAPICache implements Cache {
console.log(`EmberData | Mutation - update ${mutation.op}`, mutation);
}
}
graphFor(this.__storeWrapper).update(mutation, false);
this.__graph.update(mutation, false);
}

/**
@@ -357,8 +360,7 @@ export default class JSONAPICache implements Cache {
const attributes = Object.assign({}, peeked.remoteAttrs, peeked.inflightAttrs, peeked.localAttrs);
const relationships = {};

const graph = graphFor(this.__storeWrapper);
const rels = graph.identifiers.get(identifier);
const rels = this.__graph.identifiers.get(identifier);
if (rels) {
Object.keys(rels).forEach((key) => {
const rel = rels[key]!;
@@ -458,7 +460,7 @@ export default class JSONAPICache implements Cache {
}

if (data.relationships) {
setupRelationships(this.__storeWrapper, identifier, data);
setupRelationships(this.__graph, this.__storeWrapper, identifier, data);
}

if (changedKeys && changedKeys.length) {
@@ -612,7 +614,7 @@ export default class JSONAPICache implements Cache {
const storeWrapper = this.__storeWrapper;
let attributeDefs = storeWrapper.getSchemaDefinitionService().attributesDefinitionFor(identifier);
let relationshipDefs = storeWrapper.getSchemaDefinitionService().relationshipsDefinitionFor(identifier);
const graph = graphFor(storeWrapper);
const graph = this.__graph;
let propertyNames = Object.keys(options);

for (let i = 0; i < propertyNames.length; i++) {
@@ -713,7 +715,7 @@ export default class JSONAPICache implements Cache {

const cached = this.__peek(identifier, false);
if (cached.isDeleted) {
graphFor(this.__storeWrapper).push({
this.__graph.push({
op: 'deleteRecord',
record: identifier,
isNew: false,
@@ -750,7 +752,7 @@ export default class JSONAPICache implements Cache {
);

if (data.relationships) {
setupRelationships(this.__storeWrapper, identifier, data);
setupRelationships(this.__graph, this.__storeWrapper, identifier, data);
}
newCanonicalAttributes = data.attributes;
}
@@ -995,7 +997,7 @@ export default class JSONAPICache implements Cache {
}

if (cached.isNew) {
graphFor(this.__storeWrapper).push({
this.__graph.push({
op: 'deleteRecord',
record: identifier,
isNew: true,
@@ -1033,7 +1035,7 @@ export default class JSONAPICache implements Cache {
identifier: StableRecordIdentifier,
field: string
): SingleResourceRelationship | CollectionResourceRelationship {
return (graphFor(this.__storeWrapper).get(identifier, field) as BelongsToRelationship | ManyRelationship).getData();
return (this.__graph.get(identifier, field) as BelongsToRelationship | ManyRelationship).getData();
}

// Resource State
@@ -1055,7 +1057,7 @@ export default class JSONAPICache implements Cache {
cached.isDeleted = isDeleted;
if (cached.isNew) {
// TODO can we delete this since we will do this in unload?
graphFor(this.__storeWrapper).push({
this.__graph.push({
op: 'deleteRecord',
record: identifier,
isNew: true,
@@ -1329,6 +1331,7 @@ function _isLoading(
}

function setupRelationships(
graph: Graph,
storeWrapper: CacheCapabilitiesManager,
identifier: StableRecordIdentifier,
data: JsonApiResource
@@ -1347,7 +1350,7 @@ function setupRelationships(
continue;
}

graphFor(storeWrapper).push({
graph.push({
op: 'updateRelationship',
record: identifier,
field: relationshipName,
45 changes: 19 additions & 26 deletions packages/model/src/-private/legacy-relationships-support.ts
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import { importSync } from '@embroider/macros';
import { DEBUG } from '@ember-data/env';
import type { UpgradedMeta } from '@ember-data/graph/-private/graph/-edge-definition';
import type { LocalRelationshipOperation } from '@ember-data/graph/-private/graph/-operations';
import type { Graph } from '@ember-data/graph/-private/graph/graph';
import type { ImplicitRelationship } from '@ember-data/graph/-private/graph/index';
import type BelongsToRelationship from '@ember-data/graph/-private/relationships/state/belongs-to';
import type ManyRelationship from '@ember-data/graph/-private/relationships/state/has-many';
@@ -39,6 +40,7 @@ type PromiseBelongsToFactory = { create(args: BelongsToProxyCreateArgs): Promise
export class LegacySupport {
declare record: Model;
declare store: Store;
declare graph: Graph;
declare cache: Cache;
declare references: Record<string, BelongsToReference | HasManyReference>;
declare identifier: StableRecordIdentifier;
@@ -56,6 +58,13 @@ export class LegacySupport {
this.identifier = recordIdentifierFor(record);
this.cache = peekCache(record);

if (HAS_JSON_API_PACKAGE) {
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private'))
.graphFor;

this.graph = graphFor(this.store);
}

this._manyArrayCache = Object.create(null) as Record<string, RelatedCollection>;
this._relationshipPromisesCache = Object.create(null) as Record<
string,
@@ -113,8 +122,7 @@ export class LegacySupport {
return loadingPromise;
}

const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private')).graphFor;
const relationship = graphFor(this.store).get(this.identifier, key);
const relationship = this.graph.get(this.identifier, key);
assert(`Expected ${key} to be a belongs-to relationship`, isBelongsTo(relationship));

let resource = this.cache.getRelationship(this.identifier, key) as SingleResourceRelationship;
@@ -135,8 +143,7 @@ export class LegacySupport {
assert(`Expected a stable identifier`, !relatedIdentifier || isStableIdentifier(relatedIdentifier));

const store = this.store;
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private')).graphFor;
const relationship = graphFor(store).get(this.identifier, key);
const relationship = this.graph.get(this.identifier, key);
assert(`Expected ${key} to be a belongs-to relationship`, isBelongsTo(relationship));

let isAsync = relationship.definition.isAsync;
@@ -213,9 +220,7 @@ export class LegacySupport {
if (HAS_JSON_API_PACKAGE) {
let manyArray: RelatedCollection | undefined = this._manyArrayCache[key];
if (!definition) {
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private'))
.graphFor;
definition = graphFor(this.store).get(this.identifier, key).definition;
definition = this.graph.get(this.identifier, key).definition;
}

if (!manyArray) {
@@ -281,9 +286,7 @@ export class LegacySupport {
if (loadingPromise) {
return loadingPromise;
}
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private'))
.graphFor;
const relationship = graphFor(this.store).get(this.identifier, key) as ManyRelationship;
const relationship = this.graph.get(this.identifier, key) as ManyRelationship;
const { definition, state } = relationship;

state.hasFailedLoadAttempt = false;
@@ -302,9 +305,7 @@ export class LegacySupport {

getHasMany(key: string, options?: FindOptions): PromiseManyArray | RelatedCollection {
if (HAS_JSON_API_PACKAGE) {
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private'))
.graphFor;
const relationship = graphFor(this.store).get(this.identifier, key) as ManyRelationship;
const relationship = this.graph.get(this.identifier, key) as ManyRelationship;
const { definition, state } = relationship;
let manyArray = this.getManyArray(key, definition);

@@ -379,14 +380,12 @@ export class LegacySupport {
// because of the intimate API access involved. This is something we will need to redesign.
assert(`snapshot.belongsTo only supported for @ember-data/json-api`);
}
const graphFor = (importSync('@ember-data/graph/-private') as typeof import('@ember-data/graph/-private'))
.graphFor;
const graph = graphFor(this.store);
const relationship = graph.get(this.identifier, name);
const { graph, identifier } = this;
const relationship = graph.get(identifier, name);

if (DEBUG) {
if (kind) {
let modelName = this.identifier.type;
let modelName = identifier.type;
let actualRelationshipKind = relationship.definition.kind;
assert(
`You tried to get the '${name}' relationship on a '${modelName}' via record.${kind}('${name}'), but the relationship is of kind '${actualRelationshipKind}'. Use record.${actualRelationshipKind}('${name}') instead.`,
@@ -398,15 +397,9 @@ export class LegacySupport {
let relationshipKind = relationship.definition.kind;

if (relationshipKind === 'belongsTo') {
reference = new BelongsToReference(
this.store,
graph,
this.identifier,
relationship as BelongsToRelationship,
name
);
reference = new BelongsToReference(this.store, graph, identifier, relationship as BelongsToRelationship, name);
} else if (relationshipKind === 'hasMany') {
reference = new HasManyReference(this.store, graph, this.identifier, relationship as ManyRelationship, name);
reference = new HasManyReference(this.store, graph, identifier, relationship as ManyRelationship, name);
}

this.references[name] = reference;
31 changes: 16 additions & 15 deletions tests/performance/ember-cli-build.js
Original file line number Diff line number Diff line change
@@ -27,20 +27,21 @@ module.exports = function (defaults) {
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

const { Webpack } = require('@embroider/webpack');
// const { Webpack } = require('@embroider/webpack');

return require('@embroider/compat').compatBuild(app, Webpack, {
//
// staticAddonTestSupportTrees: true,
// staticAddonTrees: true,
// staticHelpers: true,
// staticModifiers: true,
// staticComponents: true,
// splitAtRoutes: ['route.name'], // can also be a RegExp
// packagerOptions: {
// webpackConfig: { }
// }
//
extraPublicTrees: [],
});
// return require('@embroider/compat').compatBuild(app, Webpack, {
// //
// // staticAddonTestSupportTrees: true,
// // staticAddonTrees: true,
// // staticHelpers: true,
// // staticModifiers: true,
// // staticComponents: true,
// // splitAtRoutes: ['route.name'], // can also be a RegExp
// // packagerOptions: {
// // webpackConfig: { }
// // }
// //
// extraPublicTrees: [],
// });
return app.toTree();
};