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

Meteor 3.1 #15

Merged
Merged
Show file tree
Hide file tree
Changes from 20 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
42 changes: 42 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
function @setup-test() {
local meteor_version=${1:-"3.1"}

echo "🚀 Setting up test environment for Meteor ${meteor_version}"

rm -rf test
meteor create --release ${meteor_version} --bare test

(
cd test
meteor npm i --save puppeteer@1.18.1 simpl-schema@3.4.6 chai@4.3.6
)
}

function @test() {
local meteor_version=${1:-"3.1"}

echo "🚀 Running tests with Meteor ${meteor_version}"

(
cd test
METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteor test-packages \
--raw-logs \
--once \
--driver-package meteortesting:mocha \
--release ${meteor_version} \
--exclude-archs=web.browser.legacy \
../
)
}

function @testd {
(
cd test
METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteord test-packages \
--raw-logs \
--once \
--driver-package meteortesting:mocha \
--exclude-archs=web.browser.legacy \
../
)
}
9 changes: 5 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
name: Tests

on: [push, pull_request]
on: [pull_request]

jobs:
test:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
meteor: ["3.0"]
meteor: ["3.0.3", "3.0.4", "3.1"]
redis-version: [4, 5, 6, 7]

steps:
Expand All @@ -29,4 +30,4 @@ jobs:
meteor npm i --save puppeteer@1.18.1 simpl-schema@3.4.6 chai@4.3.6
- name: Test
working-directory: ./test
run: METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteor test-packages --raw-logs --once --driver-package meteortesting:mocha ../
run: METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteor test-packages --raw-logs --once --driver-package meteortesting:mocha --release ${{ matrix.meteor }} ../
13 changes: 6 additions & 7 deletions lib/cache/ObservableCollection.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { DiffSequence } from "meteor/diff-sequence";
import { EJSON } from "meteor/ejson";
import { LocalCollection } from "meteor/minimongo";
import { _ } from "meteor/underscore";
import { LocalCollection, Minimongo } from "meteor/minimongo";
import extractFieldsFromFilters from "./lib/extractFieldsFromFilters";
import fieldProjectionIsExclusion from "./lib/fieldProjectionIsExclusion";
import getChannels from "./lib/getChannels";
import extractFieldsFromFilters from "./lib/extractFieldsFromFilters";
import { MongoIDMap } from "./mongoIdMap";
import { EJSON } from "meteor/ejson";
import isRemovedNonExistent from "../utils/isRemovedNonExistent";
import getStrategy from "../processors/getStrategy";

const allowedOptions = [
"limit",
Expand Down Expand Up @@ -188,11 +186,12 @@ export default class ObservableCollection {
* @param safe {Boolean} If this is set to true, it assumes that the object is cleaned
*/
async add(doc, safe = false) {
doc = EJSON.clone(doc);

if (!safe) {
if (this.fieldsArray) {
// projection function clones the document already.
doc = this.projectFieldsOnDoc(doc);
} else {
doc = EJSON.clone(doc);
}
}

Expand Down
24 changes: 17 additions & 7 deletions lib/mongo/ObserveMultiplex.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// This code is MIT and licensed to Meteor.

import { Meteor } from "meteor/meteor";
import { _ } from "meteor/underscore";
import { LocalCollection } from "meteor/minimongo";
import { _ } from "meteor/underscore";
import OptimisticInvocation from "./OptimisticInvocation";

export function ObserveMultiplexer(options) {
Expand Down Expand Up @@ -42,6 +42,16 @@ export function ObserveMultiplexer(options) {
});
}

// Helper function for strict object freezing
function strictFreeze(obj) {
return new Proxy(obj, {
set() {
throw new Error("Cannot mutate a frozen object");
}
});
}
const freezeObject = Meteor.isProduction ? Object.freeze : strictFreeze;

Object.assign(ObserveMultiplexer.prototype, {
addHandleAndSendInitialAdds: async function (handle) {
var self = this;
Expand Down Expand Up @@ -210,24 +220,25 @@ Object.assign(ObserveMultiplexer.prototype, {
// can continue until these are done. (But we do have to be careful to not
// use a handle that got removed, because removeHandle does not use the
// queue; thus, we iterate over an array of keys that we control.)

const safeArgs = freezeObject(args);

for (const handleId of Object.keys(self._handles)) {
var handle = self._handles && self._handles[handleId];
if (!handle) return;
var callback = handle["_" + callbackName];
// clone arguments so that callbacks can mutate their arguments

// We silence out removed exceptions
if (callback === "removed") {
try {
await callback.apply(null, EJSON.clone(args));
await callback.apply(null, safeArgs);
} catch (e) {
// Supressing `removed non-existent exceptions`
if (!isRemovedNonExistent(e)) {
throw e;
}
}
} else {
callback && (await callback.apply(null, EJSON.clone(args)));
callback && (await callback.apply(null, safeArgs));
}
}
});
Expand All @@ -248,8 +259,7 @@ Object.assign(ObserveMultiplexer.prototype, {
await self._cache.docs.forEachAsync(async function (doc, id) {
if (!_.has(self._handles, handle._id))
throw Error("handle got removed before sending initial adds!");
var fields = EJSON.clone(doc);
delete fields._id;
const { _id, ...fields } = doc;
if (self._ordered) await add(id, fields, null);
// we're going in order, so add at end
else await add(id, fields);
Expand Down
12 changes: 7 additions & 5 deletions lib/mongo/PollingObserveDriver.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { _ } from "meteor/underscore";
import { LocalCollection } from "meteor/minimongo";
import { _ } from "meteor/underscore";

function listenAll(cursorDescription, listenCallback) {
var listeners = [];
Expand Down Expand Up @@ -64,11 +64,13 @@ export default function PollingObserveDriver(options) {
self._multiplexer = options.multiplexer;
self._stopCallbacks = [];
self._stopped = false;
self._synchronousCursor = self._mongoHandle._createSynchronousCursor(
self._cursorDescription
); // previous results snapshot. on each poll cycle, diffs against
// results drives the callbacks.

self._synchronousCursor =
self._mongoHandle._createAsynchronousCursor?.(self._cursorDescription) ??
self._mongoHandle._createSynchronousCursor(self._cursorDescription);

// previous results snapshot. on each poll cycle, diffs against
// results drives the callbacks.
self._results = null; // The number of _pollMongo calls that have been added to self._taskQueue but
// have not started running. Used to make sure we never schedule more than one
// _pollMongo (other than possibly the one that is currently running). It's
Expand Down
8 changes: 6 additions & 2 deletions lib/mongo/extendMongoCollection.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Mongo } from "meteor/mongo";
import { _ } from "meteor/underscore";
import _validatedInsert from "./allow-deny/validatedInsert";
import _validatedUpdate from "./allow-deny/validatedUpdate";
import _validatedRemove from "./allow-deny/validatedRemove";
import Mutator from "./Mutator";
import _validatedUpdate from "./allow-deny/validatedUpdate";
import extendObserveChanges from "./extendObserveChanges";
import Mutator from "./Mutator";

export default () => {
const Originals = {
Expand Down Expand Up @@ -79,6 +79,10 @@ export default () => {
_validatedUpdate,
_validatedRemove,

_validatedInsertAsync: _validatedInsert,
_validatedUpdateAsync: _validatedUpdate,
_validatedRemoveAsync: _validatedRemove,

/**
* Configure defaults for your collection
*
Expand Down
12 changes: 8 additions & 4 deletions package.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package.describe({
name: "cultofcoders:redis-oplog",
version: "3.0.0-rc.3",
version: "3.1.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 3.0.0-rc.3
There was no 3.0 release. If this is enough to get us Meteor 3 compat I'm happy to release this as 3.0

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tests pass and some companies are already using it in production. I think it should be 3.0 do reduce confusion IMO.

// Brief, one-line summary of the package.
summary: "Replacement for Meteor's MongoDB oplog implementation",
// URL to the Git repository containing the source code for this package.
Expand All @@ -17,7 +17,7 @@ Npm.depends({
});

Package.onUse(function (api) {
api.versionsFrom(["3.0"]);
api.versionsFrom(["3.0.1", "3.1"]);
api.use([
"underscore",
"ecmascript",
Expand All @@ -43,16 +43,20 @@ Package.onTest(function (api) {
api.use("aldeed:collection2@4.0.4");
api.use("reywood:publish-composite@1.8.12");

api.use("underscore");
api.use("ecmascript");
api.use("tracker");
api.use("mongo");
api.use("random");
api.use("accounts-password");

api.use("alanning:roles@4.0.0");
api.use("ddp-server");
api.use("ejson");
api.use("meteortesting:mocha");
api.use("matb33:collection-hooks@2.0.0-rc.4");
api.use("alanning:roles@4.0.0");

api.use(["meteortesting:mocha@3.2.0"]);

api.mainModule("testing/main.server.js", "server");
api.addFiles("testing/publishComposite/boot.js", "server");
api.addFiles("testing/optimistic-ui/boot.js", "server");
Expand Down
4 changes: 2 additions & 2 deletions testing/boot.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { RedisOplog, SyntheticMutator } from 'meteor/cultofcoders:redis-oplog';
import { Mongo } from 'meteor/mongo';
import { _ } from 'meteor/underscore';
import { RedisOplog, SyntheticMutator } from 'meteor/cultofcoders:redis-oplog';

if (Meteor.isServer) {
RedisOplog.init({
Expand Down Expand Up @@ -44,7 +44,7 @@ const config = {
},
};

export { Collections, opts, config };
export { Collections, config, opts };

if (Meteor.isServer) {
_.each(Collections, (Collection, key) => {
Expand Down
58 changes: 29 additions & 29 deletions testing/initial_add.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import { assert } from 'chai';
import {Mongo} from 'meteor/mongo';
import { Mongo } from 'meteor/mongo';

const InitialAddCollection = new Mongo.Collection('initial_add')
const InitialAddCollection = new Mongo.Collection('initial_add');
describe('Initial Add', function () {
let lastDocId;
before(function () {
InitialAddCollection.remove({});
for (let i = 0; i <= 10; i++) {
lastDocId = InitialAddCollection.insert({number: i})
}
});
let lastDocId;
before(async function () {
await InitialAddCollection.removeAsync({});
for (let i = 0; i <= 10; i++) {
lastDocId = await InitialAddCollection.insertAsync({ number: i });
}
});

it('Should not crash on initial add', function (done) {
Meteor.defer(() => {
let err;
InitialAddCollection.find().observeChanges({
added(_id, doc) {
if (err) return;
Meteor._sleepForMs(10) // simulate a more costly operation
try {
assert.isDefined(doc)
} catch (e) {
err = e
}
}
});
done(err);
});
Meteor.defer(() => {
InitialAddCollection.remove({_id: lastDocId})
})
})
it('Should not crash on initial add', function (done) {
Meteor.defer(async () => {
let err;
await InitialAddCollection.find().observeChanges({
async added(_id, doc) {
if (err) return;
await Meteor._sleepForMs(10); // simulate a more costly operation
try {
assert.isDefined(doc);
} catch (e) {
err = e;
}
},
});
done(err);
});
Meteor.defer(async () => {
await InitialAddCollection.removeAsync({ _id: lastDocId });
});
});
});
9 changes: 6 additions & 3 deletions testing/optimistic-ui/client.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Meteor } from 'meteor/meteor';
import { assert } from 'chai';
import { Items } from './collections';
import { waitForHandleToBeReady, callWithPromise } from '../lib/sync_utils';
import { Meteor } from 'meteor/meteor';
import { Random } from 'meteor/random';
import { callWithPromise, waitForHandleToBeReady } from '../lib/sync_utils';
import './boot';
import { Items } from './collections';

describe('Optimistic UI', () => {
it('Should not cause a flicker with method calls', function (done) {
Expand Down Expand Up @@ -63,9 +63,12 @@ describe('Optimistic UI', () => {
let alreadyIn = 0;
const observer = cursor.observeChanges({
changed(docId, doc) {
console.log('changed', alreadyIn, doc);

alreadyIn++;
if (alreadyIn > 1) {
done('A flicker was caused.');
return;
}

assert.lengthOf(doc.liked, 2);
Expand Down
2 changes: 1 addition & 1 deletion testing/vent/client.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert } from 'chai';
import { Random } from 'meteor/random';
import { Vent } from 'meteor/cultofcoders:redis-oplog';
import { Random } from 'meteor/random';

describe('Vent', function () {
it('Should receive the event accordingly', function (done) {
Expand Down
Loading