Merge branch 'release-2.16' into 339-observe-async-2x

# Conflicts:
#	packages/mongo/mongo_livedata_tests.js
This commit is contained in:
Nacho Codoñer
2024-03-21 15:31:33 +01:00
2 changed files with 232 additions and 0 deletions

View File

@@ -160,6 +160,10 @@ export default class LocalCollection {
return id;
}
insertAsync(doc, callback) {
return new Promise(resolve => resolve(this.insert(doc, callback)));
}
// Pause the observers. No callbacks from observers will fire until
// 'resumeObservers' is called.
pauseObservers() {
@@ -273,6 +277,10 @@ export default class LocalCollection {
return result;
}
removeAsync(selector, callback) {
return new Promise(resolve => resolve(this.remove(selector, callback)));
}
// Resume the observers. Observers immediately receive change
// notifications to bring them to the current state of the
// database. Note that this is not just replaying all the changes that
@@ -482,6 +490,10 @@ export default class LocalCollection {
return result;
}
updateAsync(selector, mod, options, callback) {
return new Promise(resolve => resolve(this.update(selector, mod, options, callback)));
}
// A convenience wrapper on update. LocalCollection.upsert(sel, mod) is
// equivalent to LocalCollection.update(sel, mod, {upsert: true,
// _returnObject: true}).

View File

@@ -3497,6 +3497,226 @@ if (Meteor.isServer) {
});
}
testAsyncMulti('mongo-livedata - collection sync operations data persistence', [
function (test) { // Using remote collection
const Collection = new Mongo.Collection(
`remotesyncop_persistence${test.runId()}`,
);
Collection.insert({ _id: 'a' });
Collection.update({ _id: 'a' }, { $set: { num: 1 } });
const insertedId = Collection.insert({ num: 2 });
let items = Collection.find().fetch();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a', insertedId]); // temporary data accessible (optimistic-ui)
const aItem = items[0];
const insertedItem = items[1];
test.equal(aItem?.num, 1);
test.equal(insertedItem?.num, 2);
Collection.remove({ _id: insertedId });
items = Collection.find().fetch();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(async () => {
items = Collection.find().fetch();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, []); // data IS NOT persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
async function (test) { // Using local collection
const Collection = new Mongo.Collection(
`localsyncop_persistence${test.runId()}`,
);
Collection._collection.insert({ _id: 'a' });
Collection._collection.update({ _id: 'a' }, { $set: { num: 1 } });
const insertedId = Collection._collection.insert({ num: 2 });
let items = Collection.find().fetch();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a', insertedId]); // temporary data accessible (optimistic-ui)
const aItem = items[0];
const insertedItem = items[1];
test.equal(aItem?.num, 1);
test.equal(insertedItem?.num, 2);
Collection._collection.remove({ _id: insertedId });
items = Collection.find().fetch();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(() => {
items = Collection.find().fetch();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // data is persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
function (test) { // Using methods
const Collection = new Mongo.Collection(
`methodsyncop_persistence${test.runId()}`,
);
Meteor.methods({
[`insertSyncMethodPersistence${test.runId()}`]: async () => {
Collection.insert({ _id: 'a' });
},
});
Meteor.call(`insertSyncMethodPersistence${test.runId()}`);
let items = Collection.find().fetch();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(() => {
items = Collection.find().fetch();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, []); // data IS NOT persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
]);
testAsyncMulti('mongo-livedata - collection async operations data persistence', [
async function (test) { // Using remote collection
const Collection = new Mongo.Collection(
`remoteop_persistence${test.runId()}`,
);
await Collection.insertAsync({ _id: 'a' });
await Collection.updateAsync({ _id: 'a' }, { $set: { num: 1 } });
const insertedId = await Collection.insertAsync({ num: 2 });
let items = await Collection.find().fetchAsync();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a', insertedId]); // temporary data accessible (optimistic-ui)
const aItem = items[0];
const insertedItem = items[1];
test.equal(aItem?.num, 1);
test.equal(insertedItem?.num, 2);
await Collection.removeAsync({ _id: insertedId });
items = await Collection.find().fetchAsync();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(async () => {
items = await Collection.find().fetchAsync();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, []); // data IS NOT persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
async function (test) { // Using local collection
const Collection = new Mongo.Collection(
`localop_persistence${test.runId()}`,
);
await Collection._collection.insertAsync({ _id: 'a' });
await Collection._collection.updateAsync({ _id: 'a' }, { $set: { num: 1 } });
const insertedId = await Collection._collection.insertAsync({ num: 2 });
let items = await Collection.find().fetchAsync();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a', insertedId]); // temporary data accessible (optimistic-ui)
const aItem = items[0];
const insertedItem = items[1];
test.equal(aItem?.num, 1);
test.equal(insertedItem?.num, 2);
await Collection._collection.removeAsync({ _id: insertedId });
items = await Collection.find().fetchAsync();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(async () => {
items = await Collection.find().fetchAsync();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // data is persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
async function (test) { // Using methods
const Collection = new Mongo.Collection(
`methodop_persistence${test.runId()}`,
);
Meteor.methods({
[`insertMethodPersistence${test.runId()}`]: async () => {
await Collection.insertAsync({ _id: 'a' });
},
});
Meteor.callAsync(`insertMethodPersistence${test.runId()}`);
let items = await Collection.find().fetchAsync();
let itemIds = items.map(_item => _item._id);
test.equal(itemIds, ['a']); // temporary data accessible (optimistic-ui)
if (Meteor.isClient) {
return new Promise(resolve => {
Meteor.setTimeout(async () => {
items = await Collection.find().fetchAsync();
itemIds = items.map(_item => _item._id);
test.equal(itemIds, []); // data IS NOT persisted
resolve();
}, 10);
});
}
return Promise.resolve();
},
]);
testAsyncMulti("mongo-livedata - support observeChangesAsync and observeAsync to keep isomorphism on client and server", [
async (test) => {
const Collection = new Mongo.Collection(`observe_changes_async${test.runId()}`);