diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 186e541c..1ab5a8da 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -4,14 +4,14 @@ on: [push, pull_request]
jobs:
test:
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
strategy:
matrix:
- meteor: [1.12.2, 2.6.1, 2.7.3, 2.8.1, 2.12]
+ meteor: [1.12.2, 2.8.1, 2.12, 2.15]
redis-version: [4, 5, 6, 7]
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- name: Start Redis
uses: supercharge/redis-github-action@1.5.0
@@ -19,14 +19,14 @@ jobs:
redis-version: ${{ matrix.redis-version }}
- name: Setup Meteor
- uses: meteorengineer/setup-meteor@v1
+ uses: meteorengineer/setup-meteor@v2
with:
meteor-release: ${{ matrix.meteor }}
- name: Setup tests
run: |
meteor create --release ${{ matrix.meteor }} --bare test
cd test
- meteor npm i --save puppeteer@1.18.1 simpl-schema chai
+ meteor npm i --save puppeteer@1.18.1 simpl-schema@1.13.1 chai@4
- name: Test
working-directory: ./test
run: METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteor test-packages --raw-logs --once --driver-package meteortesting:mocha ../
diff --git a/.gitignore b/.gitignore
index 04913f99..3668c4f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ npm-debug.log
.idea/
test/
+node_modules/
diff --git a/.versions b/.versions
index 03eb65d5..0ef2c901 100644
--- a/.versions
+++ b/.versions
@@ -1,68 +1,69 @@
-accounts-base@2.2.8
-accounts-password@2.3.4
+accounts-base@2.2.11
+accounts-password@2.4.0
alanning:roles@3.5.1
aldeed:collection2@3.0.6
allow-deny@1.1.1
-babel-compiler@7.10.4
+babel-compiler@7.10.5
babel-runtime@1.5.1
base64@1.0.12
binary-heap@1.0.11
-boilerplate-generator@1.7.1
+boilerplate-generator@1.7.2
callback-hook@1.5.1
-check@1.3.2
-cultofcoders:redis-oplog@2.2.1
+check@1.4.1
+cultofcoders:redis-oplog@2.3.0
ddp@1.4.1
-ddp-client@2.6.1
-ddp-common@1.4.0
-ddp-rate-limiter@1.2.0
-ddp-server@2.6.2
+ddp-client@2.6.2
+ddp-common@1.4.1
+ddp-rate-limiter@1.2.1
+ddp-server@2.7.1
diff-sequence@1.1.2
dynamic-import@0.7.3
-ecmascript@0.16.7
+ecmascript@0.16.8
ecmascript-runtime@0.8.1
ecmascript-runtime-client@0.12.1
ecmascript-runtime-server@0.11.0
ejson@1.1.3
-email@2.2.5
-fetch@0.1.3
+email@2.2.6
+fetch@0.1.4
geojson-utils@1.0.11
id-map@1.1.1
inter-process-messaging@0.1.1
-local-test:cultofcoders:redis-oplog@2.2.1
+local-test:cultofcoders:redis-oplog@2.3.0
localstorage@1.2.0
-logging@1.3.2
+logging@1.3.4
matb33:collection-hooks@1.1.4
-meteor@1.11.3
+meteor@1.11.5
meteortesting:browser-tests@0.1.2
meteortesting:mocha@0.4.4
-minimongo@1.9.3
-modern-browsers@0.1.9
-modules@0.19.0
+minimongo@1.9.4
+modern-browsers@0.1.10
+modules@0.20.0
modules-runtime@0.13.1
-mongo@1.16.7
+mongo@1.16.10
mongo-decimal@0.1.3
mongo-dev-server@1.1.0
mongo-id@1.0.8
natestrauser:publish-performant-counts@0.1.2
-npm-mongo@4.16.0
+npm-mongo@4.17.2
ordered-dict@1.1.0
practicalmeteor:mocha-core@1.0.1
promise@0.12.2
raix:eventemitter@0.1.3
random@1.2.1
rate-limit@1.1.1
-react-fast-refresh@0.2.7
+react-fast-refresh@0.2.8
reactive-var@1.0.12
reload@1.3.1
retry@1.1.0
reywood:publish-composite@1.7.3
routepolicy@1.1.1
sha@1.0.9
-socket-stream-client@0.5.1
+socket-stream-client@0.5.2
tmeasday:check-npm-versions@0.3.2
-tracker@1.3.2
-underscore@1.0.13
+tracker@1.3.3
+typescript@4.9.5
+underscore@1.6.1
url@1.3.2
-webapp@1.13.5
+webapp@1.13.8
webapp-hashing@1.1.1
zodern:types@1.0.9
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1049d59..2652f16a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
## CHANGELOG
+### 2.3.0
+
+- perf: reduce GC pressure by avoiding EJSON.clone [PR 14](https://github.com/Meteor-Community-Packages/redis-oplog/pull/14) by [@alisnic](https://github.com/alisnic)
+
### 2.2.1
- Update `alanning:roles` to v3.5.1
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d5584094..4f320225 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,7 +4,8 @@
First, thank you for considering contributing to redis-oplog! It's people like you that make the open source community such a great community! 😊
-We welcome any type of contribution, not only code. You can help with
+We welcome any type of contribution, not only code. You can help with
+
- **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
- **Marketing**: writing blog posts, howto's, printing stickers, ...
- **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
@@ -13,7 +14,7 @@ We welcome any type of contribution, not only code. You can help with
## Your First Contribution
-Working on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
+Working on your first Pull Request? You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
## Submitting code
@@ -26,14 +27,16 @@ It is also always helpful to have some context for your pull request. What was t
## Running Tests
-### Setup
+### Setup
+
```
meteor create --release 1.12.2 --bare test
cd test
-meteor npm i --save puppeteer@1.18.1 simpl-schema chai
+meteor npm i --save puppeteer@1.18.1 simpl-schema chai@4
```
### Start Tests
+
```
METEOR_PACKAGE_DIRS="../" TEST_BROWSER_DRIVER=puppeteer meteor test-packages --raw-logs --once --driver-package meteortesting:mocha ../
```
@@ -55,14 +58,12 @@ You can also reach us at hello@redis-oplog.opencollective.com.
Thank you to all the people who have already contributed to redis-oplog!
-
### Backers
Thank you to all our backers! [[Become a backer](https://opencollective.com/redis-oplog#backer)]
-
### Sponsors
Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/redis-oplog#sponsor))
diff --git a/lib/cache/ObservableCollection.js b/lib/cache/ObservableCollection.js
index 127171df..5545b282 100644
--- a/lib/cache/ObservableCollection.js
+++ b/lib/cache/ObservableCollection.js
@@ -196,11 +196,12 @@ export default class ObservableCollection {
* @param safe {Boolean} If this is set to true, it assumes that the object is cleaned
*/
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);
}
}
diff --git a/lib/mongo/ObserveMultiplex.js b/lib/mongo/ObserveMultiplex.js
index 53e0c103..3a80c64c 100644
--- a/lib/mongo/ObserveMultiplex.js
+++ b/lib/mongo/ObserveMultiplex.js
@@ -41,6 +41,15 @@ export function ObserveMultiplexer(options) {
});
}
+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: function(handle) {
var self = this;
@@ -213,16 +222,17 @@ 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);
+
Object.keys(self._handles).forEach(function(handleId) {
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 {
- callback.apply(null, EJSON.clone(args));
+ callback.apply(null, safeArgs);
} catch (e) {
// Supressing `removed non-existent exceptions`
if (!isRemovedNonExistent(e)) {
@@ -230,7 +240,7 @@ Object.assign(ObserveMultiplexer.prototype, {
}
}
} else {
- callback && callback.apply(null, EJSON.clone(args));
+ callback && callback.apply(null, safeArgs);
}
});
});
@@ -250,8 +260,7 @@ Object.assign(ObserveMultiplexer.prototype, {
self._cache.docs.forEach(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) add(id, fields, null);
// we're going in order, so add at end
else add(id, fields);
diff --git a/package.js b/package.js
index 0205473b..a5ac9cc0 100644
--- a/package.js
+++ b/package.js
@@ -1,6 +1,6 @@
Package.describe({
name: 'cultofcoders:redis-oplog',
- version: '2.2.1',
+ version: '2.3.0',
// 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.
@@ -17,7 +17,7 @@ Npm.depends({
});
Package.onUse(function(api) {
- api.versionsFrom(['1.12.2', '2.8.1', '2.12']);
+ api.versionsFrom(['1.12.2', '2.8.1', '2.13', '2.15', '2.16']);
api.use([
'underscore',
'ecmascript',