Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 0 additions & 2 deletions packages/core-data/src/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const {
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_RECORD_MAP_KEY,
LOCAL_EDITOR_ORIGIN,
LOCAL_SYNC_MANAGER_ORIGIN,
WORDPRESS_META_KEY_FOR_CRDT_DOC_PERSISTENCE,
} = unlock( syncPrivateApis );

Expand All @@ -26,7 +25,6 @@ export {
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_RECORD_MAP_KEY,
LOCAL_EDITOR_ORIGIN,
LOCAL_SYNC_MANAGER_ORIGIN,
WORDPRESS_META_KEY_FOR_CRDT_DOC_PERSISTENCE,
};

Expand Down
19 changes: 7 additions & 12 deletions packages/sync/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,26 @@ export const CRDT_DOC_META_PERSISTENCE_KEY = 'fromPersistence';
export const CRDT_RECORD_MAP_KEY = 'document';

/**
* Root-level key for the map that holds entity record metadata. This map should
* only contain metadata that is not represented by the entity record itself.
* Root-level key for the map that holds the state information about the CRDT
* document itself.
*/
export const CRDT_RECORD_METADATA_MAP_KEY = 'documentMeta';
export const CRDT_STATE_MAP_KEY = 'state';

/**
* Y.Map key representing the timestamp of the last save operation.
*/
export const CRDT_RECORD_METADATA_SAVED_AT_KEY = 'savedAt';
export const CRDT_STATE_MAP_SAVED_AT_KEY = 'savedAt';

/**
* Y.Map key representing the Y.Doc client ID of the user who performed the last
* save operation.
*/
export const CRDT_RECORD_METADATA_SAVED_BY_KEY = 'savedBy';
export const CRDT_STATE_MAP_SAVED_BY_KEY = 'savedBy';

/**
* Root-level key for the map that holds the state information about the CRDT
* document itself. It should not contain information related to the entity
* record.
* Y.Map key representing the version of the CRDT document schema.
*/
export const CRDT_STATE_MAP_KEY = 'state';

// Y.Map keys for the state map.
export const CRDT_STATE_VERSION_KEY = 'version';
export const CRDT_STATE_MAP_VERSION_KEY = 'version';

/**
* Origin string for CRDT document changes originating from the local editor.
Expand Down
24 changes: 12 additions & 12 deletions packages/sync/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import type { Awareness } from 'y-protocols/awareness';
import {
CRDT_RECORD_MAP_KEY as RECORD_KEY,
LOCAL_SYNC_MANAGER_ORIGIN,
CRDT_RECORD_METADATA_MAP_KEY as RECORD_METADATA_KEY,
CRDT_RECORD_METADATA_SAVED_AT_KEY as SAVED_AT_KEY,
CRDT_STATE_MAP_KEY,
CRDT_STATE_MAP_SAVED_AT_KEY as SAVED_AT_KEY,
} from './config';
import {
logPerformanceTiming,
Expand Down Expand Up @@ -151,15 +151,15 @@ export function createSyncManager( debug = false ): SyncManager {

const ydoc = createYjsDoc( { objectType } );
const recordMap = ydoc.getMap( RECORD_KEY );
const recordMetaMap = ydoc.getMap( RECORD_METADATA_KEY );
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );
const now = Date.now();

// Clean up providers and in-memory state when the entity is unloaded.
const unload = (): void => {
providerResults.forEach( ( result ) => result.destroy() );
handlers.onStatusChange( null );
recordMap.unobserveDeep( onRecordUpdate );
recordMetaMap.unobserve( onRecordMetaUpdate );
stateMap.unobserve( onStateMapUpdate );
ydoc.destroy();
entityStates.delete( entityId );
};
Expand All @@ -183,7 +183,7 @@ export function createSyncManager( debug = false ): SyncManager {
void internal.updateEntityRecord( objectType, objectId );
};

const onRecordMetaUpdate = (
const onStateMapUpdate = (
event: Y.YMapEvent< unknown >,
transaction: Y.Transaction
) => {
Expand All @@ -194,7 +194,7 @@ export function createSyncManager( debug = false ): SyncManager {
event.keysChanged.forEach( ( key ) => {
switch ( key ) {
case SAVED_AT_KEY:
const newValue = recordMetaMap.get( SAVED_AT_KEY );
const newValue = stateMap.get( SAVED_AT_KEY );
if ( 'number' === typeof newValue && newValue > now ) {
// Another peer has saved the record. Refetch it so that we have
// a correct understanding of our own unsaved edits.
Expand Down Expand Up @@ -247,7 +247,7 @@ export function createSyncManager( debug = false ): SyncManager {

// Attach observers.
recordMap.observeDeep( onRecordUpdate );
recordMetaMap.observe( onRecordMetaUpdate );
stateMap.observe( onStateMapUpdate );

// Get and apply the persisted CRDT document, if it exists.
internal.applyPersistedCrdtDoc( objectType, objectId, record );
Expand Down Expand Up @@ -276,19 +276,19 @@ export function createSyncManager( debug = false ): SyncManager {
}

const ydoc = createYjsDoc( { collection: true, objectType } );
const recordMetaMap = ydoc.getMap( RECORD_METADATA_KEY );
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );
const now = Date.now();

// Clean up providers and in-memory state when the entity is unloaded.
const unload = (): void => {
providerResults.forEach( ( result ) => result.destroy() );
handlers.onStatusChange( null );
recordMetaMap.unobserve( onRecordMetaUpdate );
stateMap.unobserve( onStateMapUpdate );
ydoc.destroy();
collectionStates.delete( objectType );
};

const onRecordMetaUpdate = (
const onStateMapUpdate = (
event: Y.YMapEvent< unknown >,
transaction: Y.Transaction
) => {
Expand All @@ -299,7 +299,7 @@ export function createSyncManager( debug = false ): SyncManager {
event.keysChanged.forEach( ( key ) => {
switch ( key ) {
case SAVED_AT_KEY:
const newValue = recordMetaMap.get( SAVED_AT_KEY );
const newValue = stateMap.get( SAVED_AT_KEY );
if ( 'number' === typeof newValue && newValue > now ) {
// Another peer has mutated the collection. Refetch it so that we
// obtain the updated records.
Expand Down Expand Up @@ -341,7 +341,7 @@ export function createSyncManager( debug = false ): SyncManager {
);

// Attach observers.
recordMetaMap.observe( onRecordMetaUpdate );
stateMap.observe( onStateMapUpdate );
}

/**
Expand Down
8 changes: 0 additions & 8 deletions packages/sync/src/private-apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@
import {
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_RECORD_MAP_KEY,
CRDT_RECORD_METADATA_MAP_KEY,
CRDT_RECORD_METADATA_SAVED_AT_KEY,
CRDT_RECORD_METADATA_SAVED_BY_KEY,
LOCAL_EDITOR_ORIGIN,
LOCAL_SYNC_MANAGER_ORIGIN,
WORDPRESS_META_KEY_FOR_CRDT_DOC_PERSISTENCE,
} from './config';
import { lock } from './lock-unlock';
Expand All @@ -22,10 +18,6 @@ lock( privateApis, {
Delta,
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_RECORD_MAP_KEY,
CRDT_RECORD_METADATA_MAP_KEY,
CRDT_RECORD_METADATA_SAVED_AT_KEY,
CRDT_RECORD_METADATA_SAVED_BY_KEY,
LOCAL_EDITOR_ORIGIN,
LOCAL_SYNC_MANAGER_ORIGIN,
WORDPRESS_META_KEY_FOR_CRDT_DOC_PERSISTENCE,
} );
18 changes: 9 additions & 9 deletions packages/sync/src/test/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {
import { createSyncManager } from '../manager';
import {
CRDT_RECORD_MAP_KEY,
CRDT_RECORD_METADATA_MAP_KEY as RECORD_METADATA_MAP_KEY,
CRDT_RECORD_METADATA_SAVED_AT_KEY as SAVED_AT_KEY,
CRDT_RECORD_METADATA_SAVED_BY_KEY as SAVED_BY_KEY,
CRDT_STATE_MAP_KEY,
CRDT_STATE_MAP_SAVED_AT_KEY as SAVED_AT_KEY,
CRDT_STATE_MAP_SAVED_BY_KEY as SAVED_BY_KEY,
} from '../config';
import { createPersistedCRDTDoc } from '../persistence';
import { getProviderCreators } from '../providers';
Expand Down Expand Up @@ -524,9 +524,9 @@ describe( 'SyncManager', () => {

// Verify that the record metadata was not updated.
const ydoc = capturedDoc as unknown as Y.Doc;
const metadataMap = ydoc.getMap( RECORD_METADATA_MAP_KEY );
expect( metadataMap.get( SAVED_AT_KEY ) ).toBeUndefined();
expect( metadataMap.get( SAVED_BY_KEY ) ).toBeUndefined();
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );
expect( stateMap.get( SAVED_AT_KEY ) ).toBeUndefined();
expect( stateMap.get( SAVED_BY_KEY ) ).toBeUndefined();
} );

it( 'does not update when entity is not loaded', async () => {
Expand Down Expand Up @@ -622,11 +622,11 @@ describe( 'SyncManager', () => {

// Verify that the record metadata was updated.
const ydoc = capturedDoc as unknown as Y.Doc;
const metadataMap = ydoc.getMap( RECORD_METADATA_MAP_KEY );
expect( metadataMap.get( SAVED_AT_KEY ) ).toBeGreaterThanOrEqual(
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );
expect( stateMap.get( SAVED_AT_KEY ) ).toBeGreaterThanOrEqual(
now
);
expect( metadataMap.get( SAVED_BY_KEY ) ).toBe( ydoc.clientID );
expect( stateMap.get( SAVED_BY_KEY ) ).toBe( ydoc.clientID );
} );
} );

Expand Down
10 changes: 3 additions & 7 deletions packages/sync/src/test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_DOC_VERSION,
CRDT_STATE_MAP_KEY,
CRDT_STATE_VERSION_KEY,
CRDT_STATE_MAP_VERSION_KEY as VERSION_KEY,
} from '../config';

describe( 'utils', () => {
Expand Down Expand Up @@ -44,9 +44,7 @@ describe( 'utils', () => {
const ydoc = createYjsDoc( {} );
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );

expect( stateMap.get( CRDT_STATE_VERSION_KEY ) ).toBe(
CRDT_DOC_VERSION
);
expect( stateMap.get( VERSION_KEY ) ).toBe( CRDT_DOC_VERSION );
} );
} );

Expand Down Expand Up @@ -142,9 +140,7 @@ describe( 'utils', () => {
expect( deserialized ).toBeInstanceOf( Y.Doc );

const stateMap = deserialized!.getMap( CRDT_STATE_MAP_KEY );
expect( stateMap.get( CRDT_STATE_VERSION_KEY ) ).toBe(
CRDT_DOC_VERSION
);
expect( stateMap.get( VERSION_KEY ) ).toBe( CRDT_DOC_VERSION );
} );
} );

Expand Down
11 changes: 5 additions & 6 deletions packages/sync/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import * as buffer from 'lib0/buffer';
import {
CRDT_DOC_META_PERSISTENCE_KEY,
CRDT_DOC_VERSION,
CRDT_RECORD_METADATA_MAP_KEY as RECORD_METADATA_KEY,
CRDT_RECORD_METADATA_SAVED_AT_KEY as SAVED_AT_KEY,
CRDT_RECORD_METADATA_SAVED_BY_KEY as SAVED_BY_KEY,
CRDT_STATE_MAP_KEY,
CRDT_STATE_VERSION_KEY,
CRDT_STATE_MAP_SAVED_AT_KEY as SAVED_AT_KEY,
CRDT_STATE_MAP_SAVED_BY_KEY as SAVED_BY_KEY,
CRDT_STATE_MAP_VERSION_KEY as VERSION_KEY,
} from './config';
import type { CRDTDoc } from './types';

Expand All @@ -34,7 +33,7 @@ export function createYjsDoc( documentMeta: DocumentMeta = {} ): Y.Doc {
const ydoc = new Y.Doc( { meta: metaMap } );
const stateMap = ydoc.getMap( CRDT_STATE_MAP_KEY );

stateMap.set( CRDT_STATE_VERSION_KEY, CRDT_DOC_VERSION );
stateMap.set( VERSION_KEY, CRDT_DOC_VERSION );

return ydoc;
}
Expand All @@ -46,7 +45,7 @@ export function createYjsDoc( documentMeta: DocumentMeta = {} ): Y.Doc {
* @param {CRDTDoc} ydoc CRDT document.
*/
export function markEntityAsSaved( ydoc: CRDTDoc ): void {
const recordMeta = ydoc.getMap( RECORD_METADATA_KEY );
const recordMeta = ydoc.getMap( CRDT_STATE_MAP_KEY );
recordMeta.set( SAVED_AT_KEY, Date.now() );
recordMeta.set( SAVED_BY_KEY, ydoc.clientID );
}
Expand Down
Loading