Skip to content

Commit 18bef4f

Browse files
gitKrystanrunspired
andcommitted
fix: better reordering detection when remoteClearsLocal is true (#9771)
* Fix DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE reordering detection * add failing test * notification tests * implement fix * cleanup console logs * fix spurrious type issue --------- Co-authored-by: Chris Thoburn <runspired@users.noreply.github.com>
1 parent 599c7df commit 18bef4f

File tree

12 files changed

+638
-39
lines changed

12 files changed

+638
-39
lines changed

packages/build-config/vite.config.mjs

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export const entryPoints = [
1010
'./src/debugging.ts',
1111
'./src/deprecations.ts',
1212
'./src/canary-features.ts',
13-
'./src/runtime.ts',
1413
];
1514

1615
export default createConfig(

packages/core-types/src/-private.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ type UniversalKey =
1616
| 'RequestCache'
1717
// @warp-drive/core-types/request
1818
| 'SkipCache'
19-
| 'EnableHydration';
19+
| 'EnableHydration'
20+
// @warp-drive/core-types/runtime
21+
| 'WarpDriveRuntimeConfig';
2022

2123
type TransientKey =
2224
// @ember-data/tracking

packages/build-config/src/runtime.ts packages/core-types/src/runtime.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { LOG_CONFIG } from './-private/utils/logging';
1+
import type { LOG_CONFIG } from '@warp-drive/build-config/-private/utils/logging';
22

3-
const RuntimeConfig = {
3+
import { getOrSetUniversal } from './-private';
4+
5+
const RuntimeConfig: { debug: Partial<LOG_CONFIG> } = getOrSetUniversal('WarpDriveRuntimeConfig', {
46
debug: {},
5-
};
7+
});
68

79
const settings = globalThis.sessionStorage?.getItem('WarpDriveRuntimeConfig');
810
if (settings) {

packages/core-types/vite.config.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const entryPoints = [
1818
'./src/utils.ts',
1919
// non-public
2020
'./src/-private.ts',
21+
'./src/runtime.ts',
2122
];
2223

2324
export default createConfig(

packages/graph/src/-private/-diff.ts

+17-23
Original file line numberDiff line numberDiff line change
@@ -235,34 +235,24 @@ function _compare<T>(
235235
// however: if the new remote order matches the current local order
236236
// we can disregard the change notification generation so long as
237237
// we are not configured to reset on remote update (which is deprecated)
238-
if (DEPRECATE_RELATIONSHIP_REMOTE_UPDATE_CLEARING_LOCAL_STATE) {
239-
if (!remoteClearsLocal && i < priorLocalLength) {
240-
const priorLocalMember = priorLocalState![i];
241-
if (priorLocalMember !== member) {
242-
changed = true;
243-
}
244-
} else {
245-
changed = true;
246-
}
247-
} else {
248-
if (i < priorLocalLength) {
249-
const priorLocalMember = priorLocalState![i];
250-
if (priorLocalMember !== member) {
251-
if (DEBUG_RELATIONSHIP_NOTIFICATIONS) {
252-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, no-console
253-
!changed && console.log(`changed because priorLocalMember !== member && member !== prevMember`);
254-
}
255-
changed = true;
256-
}
257-
} else if (i < finalLength) {
258-
// if we have exceeded the length of priorLocalState and we are within the range
259-
// of the finalState then we must have changed
238+
239+
if (i < priorLocalLength) {
240+
const priorLocalMember = priorLocalState![i];
241+
if (priorLocalMember !== member) {
260242
if (DEBUG_RELATIONSHIP_NOTIFICATIONS) {
261243
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, no-console
262-
!changed && console.log(`changed because priorMember !== member && index >= priorLocalLength`);
244+
!changed && console.log(`changed because priorLocalMember !== member && member !== prevMember`);
263245
}
264246
changed = true;
265247
}
248+
} else if (i < finalLength) {
249+
// if we have exceeded the length of priorLocalState and we are within the range
250+
// of the finalState then we must have changed
251+
if (DEBUG_RELATIONSHIP_NOTIFICATIONS) {
252+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, no-console
253+
!changed && console.log(`changed because priorMember !== member && index >= priorLocalLength`);
254+
}
255+
changed = true;
266256
}
267257

268258
// if remote order hasn't changed but local order differs
@@ -273,6 +263,10 @@ function _compare<T>(
273263
if (equalLength && !changed && i < priorLocalLength) {
274264
const priorLocalMember = priorLocalState![i];
275265
if (priorLocalMember !== prevMember) {
266+
if (DEBUG_RELATIONSHIP_NOTIFICATIONS) {
267+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, no-console
268+
!changed && console.log(`changed because priorLocalMember !== prevMember && remoteClearsLocal`);
269+
}
276270
changed = true;
277271
}
278272
}

packages/request/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getRuntimeConfig, setLogging } from '@warp-drive/build-config/runtime';
1+
import { getRuntimeConfig, setLogging } from '@warp-drive/core-types/runtime';
22

33
export { RequestManager as default } from './-private/manager';
44
export { createDeferred } from './-private/future';

packages/store/src/-private/managers/notification-manager.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,20 @@ export default class NotificationManager {
250250
);
251251
}
252252
}
253-
} else if (LOG_METRIC_COUNTS) {
254-
count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
253+
} else {
254+
if (LOG_NOTIFICATIONS) {
255+
log(
256+
'notify',
257+
'discarded',
258+
`${'type' in identifier ? identifier.type : 'document'}`,
259+
identifier.lid,
260+
`${value}`,
261+
key || ''
262+
);
263+
}
264+
if (LOG_METRIC_COUNTS) {
265+
count(`DISCARDED notify ${'type' in identifier ? identifier.type : '<document>'} ${value} ${key}`);
266+
}
255267
}
256268

257269
return hasSubscribers;

packages/store/src/-private/store-service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
} from '@warp-drive/build-config/deprecations';
2525
import { DEBUG, TESTING } from '@warp-drive/build-config/env';
2626
import { assert } from '@warp-drive/build-config/macros';
27-
import { getRuntimeConfig, setLogging } from '@warp-drive/build-config/runtime';
2827
import type { Cache } from '@warp-drive/core-types/cache';
2928
import type { Graph } from '@warp-drive/core-types/graph';
3029
import type {
@@ -34,6 +33,7 @@ import type {
3433
} from '@warp-drive/core-types/identifier';
3534
import type { TypedRecordInstance, TypeFromInstance } from '@warp-drive/core-types/record';
3635
import { EnableHydration, SkipCache } from '@warp-drive/core-types/request';
36+
import { getRuntimeConfig, setLogging } from '@warp-drive/core-types/runtime';
3737
import type { ResourceDocument } from '@warp-drive/core-types/spec/document';
3838
import type {
3939
CollectionResourceDocument,

packages/unpublished-test-infra/src/test-support/asserts/assert-notification.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type Store from '@ember-data/store';
88
import type { DocumentCacheOperation, NotificationType } from '@ember-data/store';
99
import type { StableDocumentIdentifier } from '@warp-drive/core-types/identifier';
1010

11-
type Counter = { count: number };
11+
type Counter = { count: number; delivered: number; ignored: number };
1212
type NotificationStorage = Map<
1313
StableDocumentIdentifier | StableRecordIdentifier | 'document' | 'resource',
1414
Map<NotificationType | DocumentCacheOperation, Counter | Map<string | symbol, Counter>>
@@ -34,7 +34,7 @@ function getCounter(
3434
let bucketStorage = identifierStorage.get(bucket);
3535
if (!bucketStorage) {
3636
if (bucket === 'added' || bucket === 'removed' || bucket === 'updated' || bucket === 'state') {
37-
bucketStorage = { count: 0 };
37+
bucketStorage = { count: 0, delivered: 0, ignored: 0 };
3838
} else {
3939
bucketStorage = new Map();
4040
}
@@ -46,7 +46,7 @@ function getCounter(
4646
const _key = key || Symbol.for(bucket);
4747
counter = bucketStorage.get(_key)!;
4848
if (!counter) {
49-
counter = { count: 0 };
49+
counter = { count: 0, delivered: 0, ignored: 0 };
5050
bucketStorage.set(_key, counter);
5151
}
5252
} else {
@@ -79,7 +79,15 @@ function setupNotifications(context: TestContext, store: Store) {
7979
counter.count++;
8080

8181
// @ts-expect-error TS is bad at curried overloads
82-
return originalNotify.apply(notifications, [identifier, bucket, key]);
82+
const scheduled = originalNotify.apply(notifications, [identifier, bucket, key]);
83+
84+
if (scheduled) {
85+
counter.delivered++;
86+
} else {
87+
counter.ignored++;
88+
}
89+
90+
return scheduled;
8391
};
8492
}
8593

@@ -97,15 +105,16 @@ export function configureNotificationsAssert(this: TestContext, assert: Assert)
97105
identifier: StableRecordIdentifier | StableDocumentIdentifier,
98106
bucket: NotificationType | DocumentCacheOperation,
99107
key: string | null,
100-
count: number
108+
count: number,
109+
message?: string
101110
) {
102111
const counter = getCounter(context, identifier, bucket, key);
103112

104113
this.pushResult({
105114
result: counter.count === count,
106115
actual: counter.count,
107116
expected: count,
108-
message: `Expected ${count} ${bucket} notifications for ${identifier.lid} ${key || ''}, got ${counter.count}`,
117+
message: `${message ? message + ' | ' : ''}Expected ${count} ${bucket} notifications for ${identifier.lid} ${key || ''}, got ${counter.count}`,
109118
});
110119

111120
counter.count = 0;

packages/unpublished-test-infra/src/test-support/asserts/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ declare module '@warp-drive/diagnostic' {
4848
identifier: StableDocumentIdentifier | StableRecordIdentifier,
4949
bucket: NotificationType | CacheOperation,
5050
key: string | null,
51-
count: number
51+
count: number,
52+
message?: string
5253
): void;
5354

5455
clearNotifications(): void;

tests/ember-data__graph/ember-cli-build.js

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module.exports = async function (defaults) {
2222
compatWith: process.env.EMBER_DATA_FULL_COMPAT ? '99.0' : null,
2323
deprecations: {
2424
DISABLE_6X_DEPRECATIONS: false,
25+
DEPRECATE_STORE_EXTENDS_EMBER_OBJECT: false,
2526
},
2627
});
2728

0 commit comments

Comments
 (0)