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

feat(@aws-amplify/datastore): selective sync enhancements #7083

Merged
merged 3 commits into from Oct 29, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 11 additions & 30 deletions packages/datastore/src/datastore/datastore.ts
Expand Up @@ -551,7 +551,6 @@ class DataStore {
SchemaModel,
ModelPredicate<any>
> = new WeakMap<SchemaModel, ModelPredicate<any>>();
private syncModelsUpdated: Set<string> = new Set<string>();

getModuleName() {
return 'DataStore';
Expand Down Expand Up @@ -599,8 +598,7 @@ class DataStore {
this.syncPageSize,
this.conflictHandler,
this.errorHandler,
this.syncPredicates,
this.syncModelsUpdated
this.syncPredicates
);

// tslint:disable-next-line:max-line-length
Expand Down Expand Up @@ -1035,6 +1033,7 @@ class DataStore {
this.initialized = undefined; // Should re-initialize when start() is called.
this.storage = undefined;
this.sync = undefined;
this.syncPredicates = new WeakMap<SchemaModel, ModelPredicate<any>>();
};

stop = async function stop() {
Expand Down Expand Up @@ -1113,6 +1112,10 @@ class DataStore {
// conditionProducer is either a predicate, e.g. (c) => c.field('eq', 1)
// OR a function/promise that returns a predicate
const condition = await this.unwrapPromise(conditionProducer);
if (isPredicatesAll(condition)) {
return [modelDefinition, null];
}

const predicate = this.createFromCondition(
modelDefinition,
condition
Expand All @@ -1123,34 +1126,9 @@ class DataStore {
)
);

this.compareSyncPredicates(syncPredicates);

return this.weakMapFromEntries(syncPredicates);
}

private compareSyncPredicates(
syncPredicates: [SchemaModel, ModelPredicate<any>][]
) {
this.syncModelsUpdated = new Set<string>();

syncPredicates.forEach(([modelDefinition, predicate]) => {
const previousPredicate = ModelPredicateCreator.getPredicates(
this.syncPredicates.get(modelDefinition),
false
);

const newPredicate = ModelPredicateCreator.getPredicates(
predicate,
false
);

const predicateChanged =
JSON.stringify(previousPredicate) !== JSON.stringify(newPredicate);

predicateChanged && this.syncModelsUpdated.add(modelDefinition.name);
});
}

private createFromCondition(
modelDefinition: SchemaModel,
condition: ProducerModelPredicate<PersistentModel>
Expand Down Expand Up @@ -1188,12 +1166,15 @@ class DataStore {
const { name } = modelDefinition;
logger.warn(
`You can only utilize one Sync Expression per model.
Subsequent sync expressions for the ${name} model will be ignored.`
Subsequent sync expressions for the ${name} model will be ignored.`
);
return map;
}

map.set(modelDefinition, predicate);
if (predicate) {
map.set(modelDefinition, predicate);
}

return map;
}, new WeakMap<SchemaModel, ModelPredicate<any>>());
}
Expand Down
37 changes: 28 additions & 9 deletions packages/datastore/src/sync/index.ts
Expand Up @@ -69,6 +69,7 @@ declare class ModelMetadata {
public readonly fullSyncInterval: number;
public readonly lastSync?: number;
public readonly lastFullSync?: number;
public readonly lastSyncPredicate?: null | string;
}

export enum ControlMessage {
Expand Down Expand Up @@ -104,8 +105,7 @@ export class SyncEngine {
private readonly syncPageSize: number,
conflictHandler: ConflictHandler,
errorHandler: ErrorHandler,
private readonly syncPredicates: WeakMap<SchemaModel, ModelPredicate<any>>,
private readonly syncModelsUpdated: ReadonlySet<string>
private readonly syncPredicates: WeakMap<SchemaModel, ModelPredicate<any>>
) {
const MutationEvent = this.modelClasses[
'MutationEvent'
Expand Down Expand Up @@ -410,7 +410,14 @@ export class SyncEngine {
): Promise<Map<SchemaModel, [string, number]>> {
const modelLastSync: Map<SchemaModel, [string, number]> = new Map(
(await this.getModelsMetadata()).map(
({ namespace, model, lastSync, lastFullSync, fullSyncInterval }) => {
({
namespace,
model,
lastSync,
lastFullSync,
fullSyncInterval,
lastSyncPredicate,
}) => {
const nextFullSync = lastFullSync + fullSyncInterval;
const syncFrom =
!lastFullSync || nextFullSync < currentTimeStamp
Expand Down Expand Up @@ -694,34 +701,45 @@ export class SyncEngine {
const ModelMetadata = this.modelClasses
.ModelMetadata as PersistentModelConstructor<ModelMetadata>;

const models: [string, string][] = [];
const models: [string, SchemaModel][] = [];
let savedModel;

Object.values(this.schema.namespaces).forEach(namespace => {
Object.values(namespace.models)
.filter(({ syncable }) => syncable)
.forEach(model => {
models.push([namespace.name, model.name]);
models.push([namespace.name, model]);
});
});

const promises = models.map(async ([namespace, model]) => {
const modelMetadata = await this.getModelMetadata(namespace, model);
let savedModel: ModelMetadata;
const modelMetadata = await this.getModelMetadata(namespace, model.name);
const syncPredicate = ModelPredicateCreator.getPredicates(
this.syncPredicates.get(model),
false
);
const lastSyncPredicate = syncPredicate
? JSON.stringify(syncPredicate)
: null;

if (modelMetadata === undefined) {
[[savedModel]] = await this.storage.save(
this.modelInstanceCreator(ModelMetadata, {
model,
model: model.name,
namespace,
lastSync: null,
fullSyncInterval,
lastFullSync: null,
lastSyncPredicate,
}),
undefined,
ownSymbol
);
} else {
const syncPredicateUpdated = this.syncModelsUpdated.has(model);
const prevSyncPredicate = modelMetadata.lastSyncPredicate
? JSON.stringify(modelMetadata.lastSyncPredicate)
: null;
const syncPredicateUpdated = prevSyncPredicate !== lastSyncPredicate;

[[savedModel]] = await this.storage.save(
(this.modelClasses.ModelMetadata as PersistentModelConstructor<
Expand All @@ -733,6 +751,7 @@ export class SyncEngine {
if (syncPredicateUpdated) {
draft.lastSync = null;
draft.lastFullSync = null;
draft.lastSyncPredicate = lastSyncPredicate;
}
})
);
Expand Down