This change harmonizes server document ID generation regardless of whether
it happens inside of a method or not, by using Alea in both cases.
This cuts time of inserting small documents outside of methods
on the server by over 30%, and more importantly makes it easier to be
confident in benchmarking numbers.
---
BACKGROUND
When calling `coll.insert()` on the server within methods, we use the Alea PRNG
(which is fast, can be seeded, and not cryptographically secure) to generate
the `_id` field for the newly created document (unless an `_id` field was
explicitly passed).
The reason we use Alea is so that we can seed the PRNG from the client, as to
ensure consistently chosen IDs for methods that create multiple documents and
run on both client and server.
Prior to this change, when calling `coll.insert()` on the server *not* inside
methods, we'd use Node's cryptographically secure `crypto.getRandomBytes()`
which is slower (due to allocating buffers that need to cross from JS
into native code).
With this change, we always use Alea when generating a document ID.
---
CRYPTOGRAPHICALLY SECURE IDS STILL AVAILABLE
If an app wants to guarantee using a cryptographically secure PRNG
when generating IDs, just generate IDs yourself:
`coll.insert({_id: Random.id(), ...})`.
`Random.id()` still uses a CSPRNG (unless you're on IE, or
on the server and not enough entropy has been collected, which is
basically never the case).
If you *want* the faster Alea algorithm, use `Random.fast.id()`
(The `Random.fast` object has all the same methods as on `Random`)
---
BENCHMARK RESULTS
Here are the measured times for inserting 5000 documents, before
and after this change (on my machine):
Benchmark | Before | After
--------------------------------- | ------ | ------
direct insert from `meteor shell` | 2179ms | 1520ms
a method called from a browser | 1617ms | 1570ms
a method called from the server | 1491ms | 1487ms
direct insert from the server | 2272ms | 1445ms
(The benchmark can be found here:
f32ea073b7/benchmark2.sh)
Tried to get everything to an rc.0 of the very latest version,
which required some research in some cases about the published
versions. For example, some packages had version histories like:
```
...
1.0.3-winr.2 January 20th, 2015
1.0.3-winr.3 February 24th, 2015 installed
1.0.3 March 17th, 2015 installed
1.0.4-anubhav.0 August 6th, 2015
1.0.4-plugins.0 July 22nd, 2015
1.0.5-galaxy.0 July 17th, 2015
```
In this case, I would bump the version from `1.0.4-plugins.0`
to `1.0.5-rc.0`, skipping `1.0.4`.
This included removing some internal version constraints. It would be
nice if package A could say "use B@2.0.0" (when both have changed), but
when they're both in the release, we need to make a release that has a
B@2.0.0-rc in it, which doesn't match that constraint. Fortunately,
constraints aren't necessary within a release anyway.
This means node's crypto.randomBytes on the server, and
window.crypto.getRandomValues on the client. If node's crypto.randomBytes throws
an exception, we fall back to crypto.pseudoRandomBytes. If
window.crypto.getRandomValues isn't supported by the browser, we fall back to
the alea generator that we had been using previously.
This package was always included in apps, and even if it was possible to remove,
there wasn't a compelling story about when users would remove and replace
it. Plus, not all backwards-compatibility code could even live in it (eg, field
names of objects), so it was incomplete. It also introduced odd load order
constraints.
Instead, we introduce two conventions for backwards-compatibility code:
- Special comments of the form "// XXX COMPAT WITH 0.6.4"
- When feasible, put backwards-compatibility code in a file called
"deprecated.js" in the relevant package.
This is documented at:
https://github.com/meteor/meteor/wiki/Meteor-Style-Guide#deprecated-code-and-backwards-compatibility
Additionally, removed some symbols that existed for backwards compatibility with
Meteor 0.4.0 (changes made 10 months ago): Meteor.is_client, Meteor.is_server,
and (in a method) this.is_simulation.